Is Hibernate ready to work with the available builds of Java 9?
I remember that I already tried it and it failed. Unfortunately I don't remember the specific cause.
By the way, Hibernate Validator 5.2.3 already works with Java 9.
Hibernate 5.3 lists Java 11 as supported in the latest release 5.3. 22. Moreover, Hibernate 5.6 is also Java 11 compatible.
Hibernate 5.3 This version supports Java 8 and the latest versions and JPA 2.1 and the latest versions.
Download the latest version of Hibernate from http://www.hibernate.org/downloads.
I wondered the same thing, and tried running my Hibernate app under an early access release of Java 9. Here's what I learned.
The first problem I encountered was a ClassNotFoundException for javax.xml.bind.JAXBException. JAXB has been in the runtime classpath since Java 6, but in Java 9 it is no longer published by default. There are at least two ways you can fix this:
Include the JAXB library in your application. If your Hibernate app is annotation-driven, it may not actually require any implementation of JAXB, in which case you can get away with only including the JAXB API. Here is the dependency I added to my pom:
<!-- JAXB API -->
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>2.2.11</version>
</dependency>
With the JAXB problem resolved, I ran the app and received several thousand lines of stack traces that looked like this:
java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.defineClass(java.lang.String,byte[],int,int,java.security.ProtectionDomain) throws java.lang.ClassFormatError accessible: module java.base does not "opens java.lang" to unnamed module @49f97198
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:337)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:281)
at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:197)
at java.base/java.lang.reflect.Method.setAccessible(Method.java:191)
at javassist.util.proxy.SecurityActions.setAccessible(SecurityActions.java:103)
at javassist.util.proxy.FactoryHelper.toClass2(FactoryHelper.java:181)
at javassist.util.proxy.FactoryHelper.toClass(FactoryHelper.java:164)
at javassist.util.proxy.ProxyFactory.createClass3(ProxyFactory.java:507)
at javassist.util.proxy.ProxyFactory.createClass2(ProxyFactory.java:492)
at javassist.util.proxy.ProxyFactory.createClass1(ProxyFactory.java:428)
at javassist.util.proxy.ProxyFactory.createClass(ProxyFactory.java:400)
at org.hibernate.proxy.pojo.javassist.JavassistProxyFactory.postInstantiate(JavassistProxyFactory.java:72)
at org.hibernate.tuple.entity.PojoEntityTuplizer.buildProxyFactory(PojoEntityTuplizer.java:162)
at org.hibernate.tuple.entity.AbstractEntityTuplizer.<init>(AbstractEntityTuplizer.java:163)
at org.hibernate.tuple.entity.PojoEntityTuplizer.<init>(PojoEntityTuplizer.java:58)
After these exceptions, your app may appear to run normally. But don't be fooled: lazy initialization of objects has been disabled. You may experience significant performance problems as a result.
These errors are occurring because the Hibernate's runtime bytecode enhancement is being blocked by the strong encapsulation rules in the new module system. See this stackoverflow post for a great description of this problem.
As noted in that post, you can eliminate these errors by adding another command line argument when you launch the JVM. But that approach is only a workaround, and not a good long-term solution.
After much trial and error, I discovered a better solution:
This avoids the need for Hibernate to perform Javassist-based class modifications at runtime, eliminating the stack trace shown above. I tested this with Hibernate 5.0.12.FINAL, 5.1.5.Final, and 5.2.9.Final.
HOWEVER, you should thoroughly test your application afterward. The bytecode changes applied by Hibernate at build-time appear to differ from the ones applied at runtime, causing slightly different application behavior. Unit tests in my app that have succeeded for years suddenly failed when I enabled build-time bytecode enhancement. (I had to chase down new LazyInitializationException errors and other problems.) And the behavior seems to vary from one version of Hibernate to another; I could fix my unit tests to work in 5.0.12, only to see them fail again in 5.1.5. Proceed with caution.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With