【发布时间】:2014-05-13 16:04:56
【问题描述】:
接受答案的调查和详细信息在问题的 cmets 中。
我有一个小型 Java 项目,它读取时间表并将 Joda-Time Intervals 放入已排序的地图(在本例中为 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());
}
当插入第一个间隔时,代码会在比较器中中断。 通常我会认为间隔本身有问题,但是我检查了几种可能性,并注意到我迷失了许多奇怪的事情:
- 间隔很好,
o1和o2是具有相同长时间戳的有效日期时间。 - 没有捕获到异常。线程刚刚停止工作。
- 当我从 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 启动部署的版本)
- Eclipse 和部署的 lib 文件夹 (2.1) 中的 Joda 时间库版本相同
- 这不是一项新功能,并且相同的代码在不同的分支中工作,并且已经使用了几个星期了
- 我已尝试阻止 Eclipse 使用其自己的缓存 Ivy 库,而是使用已部署目录中的库。相同的东西 - 在 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,但如果我删除 Collection 声明或读取的行,或者在 try 块之前将任何内容放入映射中(然后按原样执行其余操作) -一切正常。让我想到了竞态条件,但是这里涉及的所有变量都是本地变量(文件名除外,它保证已设置)。
另外,在尝试一些东西时,我发现从 2.1 切换到 Joda-time 2.3 显然可以解决问题。但是,我在他们的错误修复更新日志中没有看到任何看起来甚至远程相关的内容。
【问题讨论】:
-
如果我们能看到
doWork()的定义可能会有所帮助。另外,当您说“已部署”时,您的确切含义是什么?你是在容器中运行它吗? -
感谢格式编辑。部署我的意思是它被打包到一个 jar 中并复制到一个远程驱动器,没有容器或 Web 服务器(我意识到我们在这里使用这个术语完全不同)。
-
另外,错误是否重现似乎取决于一些模糊的因素,例如是否存在额外的导入或波动性或线程中未使用的变量(但在同一类中声明)
-
只是猜测:远程端是否也有JodaTime版本?也许是 2.0 版之前的旧版本,其中
Comparable-handling 发生了一些变化(参见通用接口ReadableInstant)?请看一看。 -
在我之前的评论中,我想说:也许在远程端并行有两个不同的 Joda 版本。另请参阅 2.0 版的release notes。
标签: java eclipse datetime jodatime