Upgrade to JAVA 20 from JAVA 10
Issues faced during the upgrade
Following are the issues encountered during the upgrade process
Click to see details of ExceptionInInitializerError
Fatal error compiling: java.lang.ExceptionInInitializerError
Right after changing the JAVA version from 10
to 20
in the pom.xml file,
mvn clean compile
started failing with fatal error.
Click here for stacktrace
[ERROR] Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.7.0:testCompile (default-testCompile) on project ynami: Fatal error compiling: java.lang.ExceptionInInitializerError: Unable to make field private com.sun.tools.javac.processing.JavacProcessingEnvironment$DiscoveredProcessors com.sun.tools.javac.processing.JavacProcessingEnvironment.discoveredProcs accessible: module jdk.compiler does not "opens com.sun.tools.javac.processing" to unnamed module @11216e2e
Fix
Fix for this problem in my setup/environment was just to set the latest version (i.e. 1.18.28
) for the lombok
maven
plugin in the pom.xml file.
Click to see details of InaccessibleObjectException
Application run failed: java.lang.reflect.InaccessibleObjectException
Right after fixing the issues with compiling the project,
mvn clean spring-boot:run
started failing with Application run failed
with InaccessibleObjectException
exception.
Click here for stacktrace
Caused by: 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 @3f3e6f71 at java.base/java.lang.reflect.AccessibleObject.throwInaccessibleObjectException(AccessibleObject.java:387) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:363) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:311) at java.base/java.lang.reflect.Method.checkCanSetAccessible(Method.java:201) at java.base/java.lang.reflect.Method.setAccessible(Method.java:195) at org.springframework.cglib.core.ReflectUtils$1.run(ReflectUtils.java:61) at java.base/java.security.AccessController.doPrivileged(AccessController.java:571) at org.springframework.cglib.core.ReflectUtils.<clinit>(ReflectUtils.java:52) at org.springframework.cglib.core.KeyFactory$Generator.generateClass(KeyFactory.java:243) at org.springframework.cglib.core.DefaultGeneratorStrategy.generate(DefaultGeneratorStrategy.java:25) at org.springframework.cglib.core.AbstractClassGenerator.generate(AbstractClassGenerator.java:329) ... 30 common frames omitted 2023-08-13 00:12:58.495 ERROR 96857 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
Fix
I guess, since Java 17, we need to add the following add-opens
to VM options in order to use reflection.
So fix for this problem in my setup/environment was just to set the jvmArguments
with add-opens
in the
spring-boot-maven-plugin
maven plugin in the pom.xml file.
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<!-- The following 'add-opens' args are required for reflection -->
<jvmArguments>
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
</jvmArguments>
</configuration>
</plugin>
But don't forget to add the following to VM options if running this application from IDE:
--add-opens java.base/java.lang=ALL-UNNAMED --add-opens java.base/java.lang.reflect=ALL-UNNAMED
But since the spring boot upgrade, seems like we don't need to set them in the VM options nor in the
spring-boot-maven-plugin
in pom.xml file.
Click to see details of InaccessibleObjectException
Application run failed: java.lang.reflect.InaccessibleObjectException
Right after fixing the issues with compiling the project,
mvn clean failsafe:integration-test -Pit
started failing with Application run failed
with
InaccessibleObjectException
and similar exceptions.
Click here for stacktrace
java.lang.reflect.InaccessibleObjectException: Unable to make protected final java.lang.Class java.lang.ClassLoader.findLoadedClass(java.lang.String) accessible: module java.base does not "opens java.lang" to unnamed module
Fix
I guess, since Java 17, we need to add the following add-opens
to VM options in order to use reflection.
So fix for this problem in my setup/environment was just to set the argLine
with add-opens
in
the maven-failsafe-plugin
maven plugin in the pom.xml file.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<!--suppress UnresolvedMavenProperty -->
<argLine>
--add-opens java.base/java.util=ALL-UNNAMED
--add-opens java.base/java.text=ALL-UNNAMED
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
--add-opens java.desktop/java.awt.font=ALL-UNNAMED
-D${failsafe.jacoco.exec.file.name.arg}
</argLine>
<test>it.pk.lucidxpo.**/*IntegrationTest.class</test>
<skipTests>${skip.integration.tests}</skipTests>
<testFailureIgnore>${ignore.test.failures}</testFailureIgnore>
<reportsDirectory>${integration.tests.results.directory}</reportsDirectory>
</configuration>
</plugin>
NOTE the use of -D
with -D${testArgLine}
as without -D
, we'll end up with java.lang.ClassNotFoundException: ${testArgLine}
Apparently, the use of -D
with -D${testArgLine}
has fixed the java.lang.ClassNotFoundException: ${testArgLine}
error,
but it has caused another problem, and that is the reason the jacoco is not able to generate it.exec
data file.
So, we'll have to use @
for placeholder replacement instead of -D$
or just $
for the proper jacoco results.
But don't forget to add the following to VM options if running the integration tests from IDE:
--add-opens java.base/java.util=ALL-UNNAMED
--add-opens java.base/java.text=ALL-UNNAMED
--add-opens java.base/java.lang=ALL-UNNAMED
--add-opens java.base/java.lang.reflect=ALL-UNNAMED
--add-opens java.desktop/java.awt.font=ALL-UNNAMED
But since the spring boot upgrade, seems like we just need to set --add-opens java.base/java.lang=ALL-UNNAMED
in the VM options and the following in pom.xml file:
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<version>${maven-surefire-plugin.version}</version>
<configuration>
<!--suppress UnresolvedMavenProperty -->
<argLine>
@{failsafe.jacoco.exec.file.name.arg}
--add-opens java.base/java.lang=ALL-UNNAMED
</argLine>
<test>it.pk.lucidxpo.**/*IntegrationTest.class</test>
<skipTests>${skip.integration.tests}</skipTests>
<testFailureIgnore>${ignore.test.failures}</testFailureIgnore>
<reportsDirectory>${integration.tests.results.directory}</reportsDirectory>
</configuration>
</plugin>
How do I use properties set by other plugins in argLine?
Maven does property replacement for ${...}
values in pom.xml before any plugin is run. So Surefire would never see
the place-holders in its argLine property.
Since the Version 2.17 using an alternate syntax for these properties, @{...}
allows late replacement of properties
when the plugin is executed, so properties that have been modified by other plugins will be picked up correctly.
Click to see details of NoClassDefFoundError: javax/xml/bind/JAXBException
Application run failed: BeanCreationException, NoClassDefFoundError: javax/xml/bind/JAXBException
After fixing the InaccessibleObjectException
exception,
mvn clean spring-boot:run
now failing with Application run failed
with BeanCreationException
,
NoClassDefFoundError
, ClassNotFoundException
etc. exceptions.
Click here for stacktrace
Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled. 13-08-2023 00:36:07.144 [restartedMain] ERROR org.springframework.boot.SpringApplication.reportFailure - Application run failed org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1699) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:573) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:495) at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:317) at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:315) ...... Caused by: java.lang.NoClassDefFoundError: javax/xml/bind/JAXBException at org.hibernate.boot.spi.XmlMappingBinderAccess.<init>(XmlMappingBinderAccess.java:43) at org.hibernate.boot.MetadataSources.<init>(MetadataSources.java:87) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:209) at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.<init>(EntityManagerFactoryBuilderImpl.java:164) at org.springframework.orm.jpa.vendor.SpringHibernateJpaPersistenceProvider.createContainerEntityManagerFactory(SpringHibernateJpaPersistenceProvider.java:51) at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:365) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.buildNativeEntityManagerFactory(AbstractEntityManagerFactoryBean.java:390) at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:377) at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.afterPropertiesSet(LocalContainerEntityManagerFactoryBean.java:341) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1758) at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1695) ... 19 common frames omitted Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBException at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521) ... 30 common frames omitted 2023-08-13 00:36:07.144 ERROR 99605 --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
Fix
Fix for this problem in my setup/environment was just to set the latest version (i.e. 2.3.1
) for the jaxb-api
maven
dependency as well as changing its scope from test
to default
in the pom.xml file.
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
<version>${jaxb.api.version}</version>
</dependency>
So, now mvn clean spring-boot:run
is happy and the server is up and running without any exceptions.
Click to see details of ReflectionsException
ReflectionsException: could not create class file
After fixing the server startup problems,
now running the unit tests from IDE, are failing with could not create class file
with ReflectionsException
,
IOException
, bad magic number
etc. exceptions.
Click here for stacktrace
Caused by: org.reflections.ReflectionsException: could not create class file from Base.css at org.reflections.adapters.JavassistAdapter.getOfCreateClassObject(JavassistAdapter.java:102) at org.reflections.adapters.JavassistAdapter.getOfCreateClassObject(JavassistAdapter.java:24) at org.reflections.scanners.AbstractScanner.scan(AbstractScanner.java:30) ... 61 common frames omitted Caused by: java.io.IOException: bad magic number: 68746d6c at javassist.bytecode.ClassFile.read(ClassFile.java:825) at javassist.bytecode.ClassFile.<init>(ClassFile.java:154) at org.reflections.adapters.JavassistAdapter.getOfCreateClassObject(JavassistAdapter.java:100) ... 63 common frames omitted 21:14:18.761 [main] DEBUG org.reflections.Reflections - could not scan file static/css/Base.css in url file:/Users/muhammadfaisal/Documents/projects/YNaMi/target/classes/ with scanner SubTypesScanner org.reflections.ReflectionsException: could not create class object from file static/css/Base.css at org.reflections.scanners.AbstractScanner.scan(AbstractScanner.java:32) at org.reflections.Reflections.scan(Reflections.java:253) at org.reflections.Reflections.scan(Reflections.java:202) at org.reflections.Reflections.<init>(Reflections.java:123) at pk.lucidxpo.ynami.utils.ReflectionHelper.getTypesAnnotatedWith(ReflectionHelper.java:222) at ut.pk.lucidxpo.ynami.EntityExtendsVerifierTest.shouldVerifyThatAllTheEntitiesAreExtendedFromAuditable(EntityExtendsVerifierTest.java:24) at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104) at java.base/java.lang.reflect.Method.invoke(Method.java:578) at org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:436) at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:55) Caused by: org.reflections.ReflectionsException: could not create class file from Base.css at org.reflections.adapters.JavassistAdapter.getOfCreateClassObject(JavassistAdapter.java:102) at org.reflections.adapters.JavassistAdapter.getOfCreateClassObject(JavassistAdapter.java:24) at org.reflections.scanners.AbstractScanner.scan(AbstractScanner.java:30) ... 61 common frames omitted Caused by: java.io.IOException: bad magic number: 68746d6c at javassist.bytecode.ClassFile.read(ClassFile.java:825) at javassist.bytecode.ClassFile.<init>(ClassFile.java:154) at org.reflections.adapters.JavassistAdapter.getOfCreateClassObject(JavassistAdapter.java:100) ... 63 common frames omitted 21:14:18.761 [main] DEBUG org.reflections.Reflections - could not scan file static/css/main.css in url file:/Users/muhammadfaisal/Documents/projects/YNaMi/target/classes/ with scanner TypeAnnotationsScanner org.reflections.ReflectionsException: could not create class object from file static/css/main.css at org.reflections.scanners.AbstractScanner.scan(AbstractScanner.java:32) at org.reflections.Reflections.scan(Reflections.java:253) at org.reflections.Reflections.scan(Reflections.java:202) at org.reflections.Reflections.<init>(Reflections.java:123) at pk.lucidxpo.ynami.utils.ReflectionHelper.getTypesAnnotatedWith(ReflectionHelper.java:222)
Fix
Fix for this problem in my setup/environment was just to set the latest version (i.e. 0.10.2
) for the
org.reflections
maven plugin in the pom.xml file.
Click to see details of UnsupportedOperationException
UnfinishedMockingSessionException, UnsupportedOperationException, IllegalStateException: Could not find sun.misc.Unsafe
After fixing the reflection problems faced in tests,
now running the unit tests from IDE, are failing with Could not find sun.misc.Unsafe
with IllegalStateException
,
UnsupportedOperationException
, UnfinishedMockingSessionException
etc. exceptions.
Click here for stacktrace
org.mockito.exceptions.base.MockitoException: Mockito cannot mock this class: class org.modelmapper.ModelMapper. Mockito can only mock non-private & non-final classes. If you're not sure why you're getting this error, please report to the mailing list. Java : 20 JVM vendor name : Oracle Corporation JVM vendor version : 20.0.1+9-29 JVM name : Java HotSpot(TM) 64-Bit Server VM JVM version : 20.0.1+9-29 JVM info : mixed mode, sharing OS name : Mac OS X OS version : 13.4.1 Underlying exception : java.lang.UnsupportedOperationException: Cannot define class using reflection at org.mockito.junit.jupiter.MockitoExtension.beforeEach(MockitoExtension.java:165) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeEachCallbacks$0(TestMethodTestDescriptor.java:129) at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeMethodsOrCallbacksUntilExceptionOccurs(TestMethodTestDescriptor.java:155) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeEachCallbacks(TestMethodTestDescriptor.java:128) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:107) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58) Suppressed: java.lang.NullPointerException: Cannot invoke "org.mockito.MockitoSession.finishMocking()" because the return value of "org.junit.jupiter.api.extension.ExtensionContext$Store.remove(Object, java.lang.Class)" is null at org.mockito.junit.jupiter.MockitoExtension.afterEach(MockitoExtension.java:211) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterEachCallbacks$11(TestMethodTestDescriptor.java:217) at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$13(TestMethodTestDescriptor.java:229) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:227) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAfterEachCallbacks(TestMethodTestDescriptor.java:216) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:119) ... 48 more Caused by: java.lang.UnsupportedOperationException: Cannot define class using reflection at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection$Dispatcher$Unavailable.defineClass(ClassInjector.java:821) at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection.inject(ClassInjector.java:185) at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default$InjectionDispatcher.load(ClassLoadingStrategy.java:187) at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:79) at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:4457) ... 54 more Caused by: java.lang.IllegalStateException: Could not find sun.misc.Unsafe at net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe$Dispatcher$Disabled.initialize(ClassInjector.java:1366) at net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe.inject(ClassInjector.java:1202) at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$ForUnsafeInjection.load(ClassLoadingStrategy.java:458) at net.bytebuddy.dynamic.TypeResolutionStrategy$Passive.initialize(TypeResolutionStrategy.java:79) at net.bytebuddy.dynamic.DynamicType$Default$Unloaded.load(DynamicType.java:4457) at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection$Dispatcher$Indirect.make(ClassInjector.java:684) at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection$Dispatcher$CreationAction.run(ClassInjector.java:302) at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection$Dispatcher$CreationAction.run(ClassInjector.java:290) at java.base/java.security.AccessController.doPrivileged(AccessController.java:319) at net.bytebuddy.dynamic.loading.ClassInjector$UsingReflection.<clinit>(ClassInjector.java:70) at net.bytebuddy.dynamic.loading.ClassLoadingStrategy$Default$InjectionDispatcher.load(ClassLoadingStrategy.java:184) ... 79 more Caused by: java.lang.NoSuchMethodException: sun.misc.Unsafe.defineClass(java.lang.String,[B,int,int,java.lang.ClassLoader,java.security.ProtectionDomain) at java.base/java.lang.Class.getMethod(Class.java:2321) at net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe$Dispatcher$CreationAction.run(ClassInjector.java:1269) at net.bytebuddy.dynamic.loading.ClassInjector$UsingUnsafe$Dispatcher$CreationAction.run(ClassInjector.java:1257) org.mockito.exceptions.misusing.UnfinishedMockingSessionException: Unfinished mocking session detected. Previous MockitoSession was not concluded with 'finishMocking()'. For examples of correct usage see javadoc for MockitoSession class. at org.mockito.junit.jupiter.MockitoExtension.beforeEach(MockitoExtension.java:165) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeBeforeEachCallbacks$0(TestMethodTestDescriptor.java:129) at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeMethodsOrCallbacksUntilExceptionOccurs(TestMethodTestDescriptor.java:155) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeBeforeEachCallbacks(TestMethodTestDescriptor.java:128) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:107) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:58) Suppressed: java.lang.NullPointerException: Cannot invoke "org.mockito.MockitoSession.finishMocking()" because the return value of "org.junit.jupiter.api.extension.ExtensionContext$Store.remove(Object, java.lang.Class)" is null at org.mockito.junit.jupiter.MockitoExtension.afterEach(MockitoExtension.java:211) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAfterEachCallbacks$11(TestMethodTestDescriptor.java:217) at org.junit.jupiter.engine.execution.ThrowableCollector.execute(ThrowableCollector.java:40) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeAllAfterMethodsOrCallbacks$13(TestMethodTestDescriptor.java:229) at java.base/java.util.ArrayList.forEach(ArrayList.java:1511) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAllAfterMethodsOrCallbacks(TestMethodTestDescriptor.java:227) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeAfterEachCallbacks(TestMethodTestDescriptor.java:216) at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:119) ... 48 more
Fix
Fix for this problem in my setup/environment was just to add the net.bytebuddy:byte-buddy
maven
dependency in test
scope in the pom.xml file.
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy</artifactId>
<version>1.14.5</version>
<scope>test</scope>
</dependency>
So, now all the unit as well as integration tests are running and passing without any exceptions.