Tales of a Java 7 Migration

This week we rolled out a new release of a large, 6 to 7 year old Java I application. Among other things we migrated to Java 7 right before Java 6 became end of life. The migration was fairly straight forward and simple. The biggest reason why we could’t migrate earlier is because our whole tool chain (Eclipse, FindBugs, Checkstyle and Sonar) had to be Java 7 ready.

As documented in the Java SE 7 and JDK 7 Compatibility Java 7 is mostly backwards compatible, still there were minor changes that affected us.

The order of the methods returned by reflection has changed. We were not affected by this but we ran into JBAS-6981 which is fixed in JBoss AS 6 and we back ported to JBoss AS 5.1.

Java 7 byte code (major 51.0) has to be verified using the type-checking verifier meaning stack map frames have to be present. This was not an issue for us directly but we use two libraries that use CGLib for class file generation (Spring and EasyMock) and CGLib 2.x was not able to produce stack map frames. CGlib 3.0 fixes this and Spring 3.2 ships with a custom CGLib version. However this version is in the Spring name space and therefore not available to EasyMock and our code coverage reports were failing because of this. As CGLib 3.0 is not available in Maven Central we manually deployed it to our in-house Nexus. We sill ran into a bug in CGLib 3.0 so we had to make a custom release. Unfortunately CGLib does not seem actively maintained so we don’t have much hope of our fix being merged soon.

The following code compiles with Java 6 but not with Java 7

public interface MultiValueMap<K, V> extends Map<K, Collection<V>> {

  void put(K key, V value);

}

we ended up renaming the method.

The class sun.management.ManagementFactory is no longer available, we switched to java.lang.management.ManagementFactory (which we should have used in the first place).

The class java.text.SimpleDateFormat seems to behave sightly differently when used in not-documented ways (if you follow the contract, it will behave the same in Java 6 and 7).

We used a couple of regexes to migrate our code to diamond operator, try-with-resources and multi-catch which worked OK. Then we found out that IntelliJ IDEA can do this automatically for us so we ran it over the whole code base which worked out very well.