At the moment we are building our Java code with JDK 8 for Java 8, and run it on a JDK 8.
If we just change the runtime environment to JDK 11, what might break?
At the moment we are building our Java code with JDK 8 for Java 8, and run it on a JDK 8.
If we just change the runtime environment to JDK 11, what might break?
There are (at least) two specific things to look for:
Reflective access to private APIs
Use of MethodHandles
Java 9 and subsequent introduced the module system which enforces (lack of) access to private APIs, even through reflection. Java 8 applications would only run without modification on Java 9 but there are no guarantees for subsequent JREs. As a practical example, I have some Processor implementations that find the JavaFileManager through reflection:
try {
/*
* com.sun.tools.javac.processing.JavacProcessingEnvironment
* .getContext() -> com.sun.tools.javac.util.Context
*/
Object context =
processingEnv.getClass()
.getMethod("getContext")
.invoke(processingEnv);
fm =
(JavaFileManager)
context.getClass()
.getMethod("get", Class.class)
.invoke(context, JavaFileManager.class);
} catch (Exception exception) {
}
that now generates a warning:
WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by ball.annotation.processing.AbstractProcessor (file:/Users/ball/.m2/repository/ball/ball-util/6.0.1-SNAPSHOT/ball-util-6.0.1-SNAPSHOT.jar) to method com.sun.tools.javac.processing.JavacProcessi\
ngEnvironment.getContext()
WARNING: Please consider reporting this to the maintainers of ball.annotation.processing.AbstractProcessor
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
The method for accessing MethodHandles in Java 8 will not work in Java 9 and subsequent and vice versa.
Java 8's
Constructor<MethodHandles.Lookup> constructor =
MethodHandles.Lookup.class
.getDeclaredConstructor(Class.class);
constructor.setAccessible(true);
Class<?> declarer = method.getDeclaringClass();
Object result =
constructor.newInstance(declarer)
.in(declarer)
.unreflectSpecial(method, declarer)
.bindTo(proxy)
.invokeWithArguments(argv);
In Java 9 and later must be replaced with:
Class<?> declarer = method.getDeclaringClass();
Object result =
MethodHandles.lookup()
.findSpecial(declarer, method.getName(),
methodType(method.getReturnType(),
method.getParameterTypes()),
declarer)
.bindTo(proxy)
.invokeWithArguments(argv);
In addition to what already has been said, some libraries break on JRE updates. I've had that experience with Jasper (the JSP compiler used in Tomcat), because Jasper needs to read classfiles from the JRE, and old Jasper version + new JRE version = error.
In the end, you'll just have to test it and see what happens.