2014-04-02 45 views
4

调查和接受答案的详细信息在问题的评论中。DateTime compareTo不适用于DateTime

我有一个小型的Java项目,它读取一个调度并将Joda时间间隔放入一个有序的映射(本例中为TreeMap)以供进一步处理。 这是通过ScheduledExecutorService的完成:

executor.scheduleWithFixedDelay(new Runnable() { 
     @Override 
     public void run() { 
      try { 
       doWork(); 
      } catch (Exception e) { 
       e.printStackTrace(); 
       throw new RuntimeException(e); 
      } 
     } 
    }, 1, 1, TimeUnit.SECONDS); 

doWork()然后读取的文件时,产生了一些时间间隔,然后填充使用此比较的地图(地图构造函数中指定):

@Override 
public int compare(Interval o1, Interval o2) { 
    return o1.getStart().compareTo(o2.getStart()); 
} 

然后,该代码插入第一个时间间隔时会在比较器中断开。 通常我会觉得有什么不对的间隔本身,但是我已经检查了几种可能性,并注意到我迷路了多奇怪的事情:

  • 的间隔很好,o1o2与有效DateTime是否相同的长时间戳。
  • 没有发现任何异常。线程停止工作。
  • 当我从Eclipse启动应用程序时,一切正常。它只在启动部署版本时中断。通过部署,我的意思是它被打包成一个.jar并复制到共享目录,这里没有容器。
  • 更改

    try { 
        doWork(); 
    } catch (Exception e) { 
        e.printStackTrace(); 
        throw new RuntimeException(e); 
    } 
    

    try { 
        doWork(); 
    } catch (Throwable e) { 
        e.printStackTrace(); 
        throw new RuntimeException(e); 
    } 
    

    修复它。 (即地图填充得很好,包括原始的第一个间隔)。

最后一部分让我觉得这是一个JIT或JVM的错误,而不是代码。 我也探讨过这个正在构建问题的可能性,但它似乎并没有这样的情况:

  • Eclipse和构建服务器使用的Java 7(Eclipse的7.0.51,构建服务器:7.0。 25,使用7.0.51 JRE启动已部署的版本
  • Joda时间库版本与Eclipse和部署的lib文件夹(2.1)相同
  • 这不是一个新功能,而且代码非常相似不同的分支,现在已经有几个星期了
  • 我试着停止使用自己的缓存常春藤库的Eclipse,而是使用t他在部署的目录中存储库。相同的东西 - 来自Eclipse的作品在使用Java启动jar时不起作用。

后一点远程调试我已再现等的东西:Method "compareTo" with signature "(Lorg/joda/time/ReadableInstant;)I" is not applicable on this object与目标对象在比较代码设置断点时是class org.joda.time.DateTime

任何有关如何进一步调试的帮助,将不胜感激。

编辑:

private void doWork() { 
     SortedMap<Interval, String> map = new TreeMap<>(new Comparator<Interval>() { 
      @Override 
      public int compare(Interval o1, Interval o2) { 
       return o1.getStart().compareTo(o2.getStart()); 
      } 
     }); 

     Collection<String> col1 = new HashSet<>(); 
     Collection<String> col2 = new HashSet<>(); 
     String string = ""; 
     long ts = 0; 

     try (FileInputStream input = new FileInputStream(fileName); 
       InputStreamReader isr = new InputStreamReader(input); 
       BufferedReader reader = new BufferedReader(isr)) { 
      String line = reader.readLine(); 
      map.put(new Interval(new DateTime(), new DateTime()), ""); 
     } 
} 

虽然这看起来并不像一个SSCCE由于很多额外的代码,如果我删除了收集的声明或读行,或之前把任何东西在地图上尝试阻止(然后按原样完成) - 一切正常。让我想到竞态条件,但是这里涉及的所有变量都是本地的(除了fileName,它保证已经设置)。

此外,虽然尝试的东西,我发现从2.1切换到乔达时间2.3显然解决了这个问题。然而,我没有看到他们的更新日志中的任何东西,甚至远程相关。

+0

这可能是有益的,如果我们可以看到'doWork()'的定义。另外,当你说“部署”时,你的意思是什么?你在容器中运行这个吗? –

+0

感谢您的格式编辑。通过部署我的意思是它被打包成一个罐子,并复制到一个远程驱动器,没有容器或网络服务器(我意识到我们在这里使用这个术语很不一样)。 – Ordous

+0

此外,它似乎是否重现错误取决于一些不明确的因素,如额外的进口或挥发性或变量未在线程中使用(但在同一类中声明) – Ordous

回答

1

这里对我的意见基地总结答案:

是否远程端有第二JodaTime版本?也许是版本2.0之前的Comparable处理发生了一些变化的旧版本(请参阅Generified接口ReadableInstant)? Pre 2.0有问题的方法有签名compareTo(Object)而2.0和更高版本新签名compareTo(ReadableInstant),也请参阅release notes。这种两个joda-jar和一个连接类加载问题的情况将解释以下异常消息:

带签名的方法“compareTo”(Lorg/joda/time/ReadableInstant;)I“不适用于此对象目标对象是类org.joda.time.DateTime

(你的问题非常棘手,并已当之无愧更upvotes。很高兴听到你找到了JRuby的库中包含的旧JodaTime版本的原因。)