I have a project with a unit test that works under Java 7, but not under Java 8. Is there a good way to investigate such things? (I'm sure that the test is correct; this suggests that there's a subtle bug in the implementation.)
Really I suppose what I would like is a quick way to identify where the code paths diverge. But this is hard, because there might be all sorts of differences in the code paths at a very low level through the JDK, and I don't want to get bogged down in irrelevant differences that are down to tiny optimisations.
So the nice thing would maybe be to ask at what top level trace the paths diverge; and then, starting from just before that point, to ask at what second level trace the paths diverge; and so on.
But I've no idea whether there's a way to do this. I fear I could waste a lot of time if I don't have a systematic approach.
The code, by the way, is the Apache Phoenix repository, where under Java 8, I get the following failure:
Tests run: 1, Failures: 1, Errors: 0, Skipped: 0, Time elapsed: 0.006 sec <<< FAILURE! - in org.apache.phoenix.schema.PMetaDataImplTest
testEviction(org.apache.phoenix.schema.PMetaDataImplTest) Time elapsed: 0.006 sec <<< FAILURE!
java.lang.AssertionError: expected:<3> but was:<2>
at org.junit.Assert.fail(Assert.java:88)
at org.junit.Assert.failNotEquals(Assert.java:834)
at org.junit.Assert.assertEquals(Assert.java:645)
at org.junit.Assert.assertEquals(Assert.java:631)
at org.apache.phoenix.schema.PMetaDataImplTest.testEviction(PMetaDataImplTest.java:98)
One of the most visible changes between Java 7 and Java 8 is a change to how hash data structures handle collisions - previously linked lists were used, now the entries are stored in balanced trees. In some cases this can affect the iteration order of these data structures. This isn't a language regression since these data structures explicitly do not specify an iteration order, but careless code and tests can easily be written that assume a certain order.
In rare situations, this change could introduce a change to the iteration order of
HashMap
andHashSet
. A particular iteration order is not specified forHashMap
objects - any code that depends on iteration order should be fixed.
So the first thing I would do when debugging Java 7 -> 8 failures is look for miss-uses of HashMap
, HashSet
, and ConcurrentHashMap
. Once you've found the mistake you have a few choices:
LinkedHashMap
, TreeMap
, or ImmutableMap
.int[] expected = {1,2,3}
and then looping over the elements. You can make this easier using Guava's static constructors (ImmutableSet.of(1,2,3)
) or Truth's fluent assertion syntax (assertThat(someSet).containsExactly(1, 2, 3)
).If hash ordering proves to not be the root cause your issue is likely much more subtle and your best option will likely be to step through with a debugger, as suggested. Be sure to at least skim What's New in JDK 8 as well for clues.