Question

The investigation and details for the accepted answer are in the comments to the question.

I have a small Java project that reads a schedule and puts Joda-Time Intervals into a sorted map (TreeMap in this case) for further processing. This is done via a 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() then reads a file, creates some intervals and then populates the map using this comparator (specified in the map constructor):

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

The code then breaks in the comparator when inserting the very first interval. Usually I would think there is something wrong with the interval itself, however I have checked several possibilities and noticed multiple odd things that I got lost in:

  • The interval is fine, o1 and o2 are valid DateTimes with the same long timestamp.
  • No exception is caught. The thread just ceases work.
  • When I launch the app from Eclipse, everything works fine. It only breaks when launching a deployed version. By deployed I mean it was packed into a .jar and copied over to a shared directory, no containers here.
  • Changing

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

    to

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

    fixes it. (I.e. map gets populated fine, including the original first interval).

The last part makes me think it is a bug with JIT or JVM, rather than with the code. I have also explored the possibility of this being a build issue, however it does not seem to be the case:

  • Both Eclipse and the build server use Java 7 (Eclipse 7.0.51, Build server: 7.0.25, Launched the deployed version with a 7.0.51 JRE)
  • Joda time library version is the same both in Eclipse and deployed lib folder (2.1)
  • This is NOT a new feature and the very same code works in a different branch, and has been for a couple of weeks now
  • I have tried stopping Eclipse from using its own cached Ivy libraries, and instead use the libraries in the deployed directory. Same stuff - works from Eclipse, doesn't work when launching jar with Java.

After a bit of remote-debugging I have reproduced something of the like: Method "compareTo" with signature "(Lorg/joda/time/ReadableInstant;)I" is not applicable on this object with the target object being class org.joda.time.DateTime when breakpointing in the comparator code.

Any help in how to debug this further would be appreciated.

EDIT:

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()), "");
        }
}

While this does not look like an SSCCE due to a lot of extra code, if I remove the Collection declarations or the line read, or put anything in the map before the try block (and then do the rest as is) - everything works fine. Makes me think of race conditions, however all variables involved here are local (except fileName, which is guaranteed to have been set).

Also, while trying out stuff I found that switching to Joda-time 2.3 from 2.1 apparently fixes the problem. However I do not see anything in their changelog of bugfixes that looks even remotely relevant.

Was it helpful?

Solution

Here a summarizing answer on base of my comments:

Does the remote side have a second JodaTime version? Maybe an older one before version 2.0 where the Comparable-handling changed a little bit (see generified interface ReadableInstant)? Pre 2.0 the method in question had the signature compareTo(Object) while in 2.0 and later the new signature compareTo(ReadableInstant), see also the release notes. This situation of two joda-jars and a connected classloading-issue would explain following exception message:

Method "compareTo" with signature "(Lorg/joda/time/ReadableInstant;)I" is not applicable on this object with the target object being class org.joda.time.DateTime.

(Your question was tricky and has deserved even more upvotes. Glad to hear that you found the reason in JRuby-library containing an older JodaTime-version.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top