5

There is a complex piece of code that does many complex mathematical operations.

When it is built and tested by maven on jdk 1.7 it passes all the tests. When using jdk 1.8 it fails.

Trying to find the spot where the calculations go wrong in a debugger seems almost hopeless.

What are my options? Is there a tool that can scan for incompatibilities between jdk 1.7 and 1.8 in my code?

Is my best option to run the code in two separate debuggers and see where the difference would be?

EDIT:

@Philipp Claßen That is the most likely cause so far. I was hoping there would be an automated way of checking for this.

@dkatzel The code was not written by me, poorly commented and does scientific calculations that are "woodo" to me.

@Mike Samuel I see no benefit of this approach over running two debuggers in parallel.

Thank you all for helping. Seems that two debuggers is the best way to go.

EDIT 2 The author of the original code was relying on hash map ordering. That was the problem.

asked Dec 12, 2014 at 19:57
10
  • Check the release notes for clues. Otherwise, I think you're going to have to run two debuggers. Commented Dec 12, 2014 at 19:58
  • 1
    can you please post some code? Commented Dec 12, 2014 at 19:59
  • I can guarantee that seeing code will not help. Unless you would like to go through thousands of lines. Commented Dec 12, 2014 at 20:01
  • 1
    You describe two scenarios where it should be five: 1) build using 1.7 and tested/executed on 1.7, 2) build using 1.7 and tested/executed on 1.8, 3) build using 1.8 with -target 1.7 and tested/executed on 1.7, 4) build using 1.8 with -target 1.7 and tested/executed on 1.8, 5) build using 1.8 with -target 1.8 and tested/executed on 1.8. It would be useful to know which of these scenarios fails or whether/which of the failing scenarios produce same results. Commented Dec 12, 2014 at 20:44
  • 1
    If you suspect that there might be code relying on HashMap ordering, you may run a test on jdk1.7 where you replaced the HashMap implementation enforcing a different order. If that’s the only difference to the original jdk1.7 you will know soon if that’s the issue. Commented Dec 12, 2014 at 20:52

4 Answers 4

7

Look out for sources of nondeterminism.

Especially code that relies on the ordering of elements in Collections like HashMaps is dangerous, as the ordering is unspecified and depends on the JVM.

I have seen it in every JVM upgrade that such (buggy) code worked by luck and broke immediately once the JVM implementation changed.

answered Dec 12, 2014 at 20:23
Sign up to request clarification or add additional context in comments.

Comments

3

Add logging statements to log every intermediate result. You can use something like

static void dumpDoubleWithLineNumber(double d) {
 StackTraceElement[] stack = Thread.currentThread().getStackTrace();
 // Thread.getStackTrace() and this method are elements 0 and 1
 StackTraceElement caller = stack[2];
 System.err.println(
 caller.toString()
 + " : " + d 
 + " / " + Long.toString(Double.toLongBits(d), 16));
}

Then run it once under Java 7, once under Java 8, and diff the results.

answered Dec 12, 2014 at 20:14

5 Comments

I am sorry , but considering that he already has test cases, and the code is 1000s of lines, isn't this a little Hello World approach? I would rather start with Test cases and their stack traces..
@Shaunak, I don't know what a Hello World approach is, but the test stack traces only tell you where the failure was detected. A diff of logs from one failing test will tell you where the divergence started. 1000's of lines is quite a small program. Putting in a few hundred log statements should take 20 minutes tops. Trying to reason backwards from a test failure might take hours or days.
Exactly what we write test cases for! and looks like he already has good set of test cases that caught the problem.
I actually liked this solution.
@Shaunak, The tests have told Andrey that there is a problem, but Andrey hasn't caught it yet. Telemetry can help with that.
3

Seems like you have a good set of tests that caught the problem. Perhaps a good start would be to compare the tests that pass and the tests that fail. What did the tests that fail do differently?

If the tests that fail do too much, then you need more finer grained tests. Tests should really only test one thing in isolation. This means you should have lots of tests that test each part of the complex calculation.

New versions of Java really try hard not to break old working code so it is unlikely a bug in the JDK...however it is possible...

answered Dec 12, 2014 at 20:20

Comments

0

If there is a specific object, you want to monitor and the points, where the object is changed are not too many, you could try to set conditional breakpoints, which will print out information to System.out instead of supending the Thread. That works fine for eclipse, may be also for other IDEs
For example, to monitor the value d at a specific point of code, you create a breakpoint with the following condition:

System.out.println(Thread.currentThread().getStackTrace()[1] + " value="+d); return false;

This condition is never true but always evaluated, so it prints out something like that:

test.Main.main(Main.java:23) value=1.0

If this works in your IDE, you can run your program with Java 7 and java 8 in the IDE and comparing the output. If you can identify the line where the differences occurs, you may go on with conventional debugging.

May be you can find more here : http://help.eclipse.org/luna/index.jsp?topic=%2Forg.eclipse.jdt.doc.user%2Ftasks%2Ftask-manage_conditional_breakpoint.htm

answered Dec 12, 2014 at 21:29

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.