I have an application running in Tomcat 9.0.45 with JDK 11 (OpenJDK 11.0.11).
After upgrading some libraries (Spring 4.3.30 to 5.3.9) using maven, the application throws the following Exception:
java.lang.NoClassDefFoundError: java/lang/constant/Constable
at my.app.SomeClass.process(SomeClass.java:123) ~[classes/:?]
at org.springframework.scheduling.support.DelegatingErrorHandlingRunnable.run(DelegatingErrorHandlingRunnable.java:54) [spring-context-5.3.9.jar:5.3.9]
at java.base/java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:515) [?:?]
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264) [?:?]
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304) [?:?]
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128) [?:?]
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628) [?:?]
at java.base/java.lang.Thread.run(Thread.java:829) [?:?]
Caused by: java.lang.ClassNotFoundException: java.lang.constant.Constable
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1364) ~[catalina.jar:9.0.45]
at org.apache.catalina.loader.WebappClassLoaderBase.loadClass(WebappClassLoaderBase.java:1187) ~[catalina.jar:9.0.45]
... 11 more
Obviously, it tries to run JRE 12 code in a JRE 11 environment.
As the Exception does not occur prior to updating the libraries, I guess some dependency got into the project that uses the JRE 12 code.
How can I find out which library/dependency causes the problem?
WebappClassLoaderBase debug log does not give any new information:
org.apache.catalina.loader.WebappClassLoaderBase.loadClass loadClass(java.lang.constant.Constable, false)
org.apache.catalina.loader.WebappClassLoaderBase.loadClass Searching local repositories
org.apache.catalina.loader.WebappClassLoaderBase.findClass findClass(java.lang.constant.Constable)
org.apache.catalina.loader.WebappClassLoaderBase.findClass --> Returning ClassNotFoundException
Strangely, the Exception does not occur on my dev machine, so I also can't debug.
Any ideas are very much appreciated.
Edit: compiling with maven 3.8.1 using aspectj-maven-plugin 1.12.6.
The Constable interface (javadoc) was only added in Java 12.
So, your theory that the exception / stacktrace is caused by trying to run Java 12+ code on Java 11 is correct.
It is not entirely clear why this has happened. While the most recent versions of Spring are compatible with Java 16 ... they should also run on Java 11 (and indeed Java 8). It is possible that the Spring team have messed up and shipped some JARs that have been built incorrectly. But I doubt it.
I suspect that you have made a mistake in building your code. Maybe you compiled with a Java 12+ tool chain, against the Java SE 12+ runtime using a target version of Java 11?
#Stephen C pointed to the right direction - something has compiled something that way.
Turns out the machine that compiles the code, did not have Java 11 installed, but Java 16. (Still, that compiled perfectly runnable Java 11 code for Spring 4.3.30.)
I have removed Java 16 from the machine and installed Java 11 only. The code now runs without throwing the ClassNotFoundException.
As of why that happened, I still have no idea.
Related
I am trying to upgrade a project from Java 8 to Java 17. I am getting following error when to trying to bring up the service and not sure how to fix it. I have searched for java.lang.IllegalAccessError issues and all I see are related to Powermock.
Javassist library is not explicitly specified, but Gradle using the latest version available(org.javassist:javassist:3.28.0-GA) and I don't see multiple versions loaded. I tried --illegal-access=permit VM option, but didn't work. Any ideas or suggestion? Thanks in advance.
As part of Java 8 to 17 upgrade, I upgraded all the important libraries to the latest version including Dropwizard framework suit, Lombok, Apache Spark, Swagger, and etc.
java.lang.IllegalAccessError: class jdk.internal.reflect.ConstructorAccessorImpl loaded by com.company.custom.metadata.run.CompanyLoader #f2ff811 cannot access jdk/internal/reflect superclass jdk.internal.reflect.MagicAccessorImpl
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1016)
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:877)
at javassist.Loader.findClass(Loader.java:419)
at javassist.Loader.loadClass(Loader.java:350)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
at java.base/java.lang.System$2.defineClass(System.java:2189)
at java.base/jdk.internal.reflect.ClassDefiner.defineClass(ClassDefiner.java:65)
at java.base/jdk.internal.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:400)
at java.base/jdk.internal.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:394)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:310)
at java.base/jdk.internal.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:393)
at java.base/jdk.internal.reflect.MethodAccessorGenerator.generateConstructor(MethodAccessorGenerator.java:92)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:55)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:500)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:481)
at org.jboss.logging.Logger.doGetMessageLogger(Logger.java:2573)
at org.jboss.logging.Logger.getMessageLogger(Logger.java:2530)
at org.jboss.logging.Logger.getMessageLogger(Logger.java:2516)
at org.hibernate.validator.internal.util.logging.LoggerFactory.make(LoggerFactory.java:22)
at org.hibernate.validator.internal.engine.ValidatorFactoryConfigurationHelper.<clinit>(ValidatorFactoryConfigurationHelper.java:51)
at org.hibernate.validator.internal.engine.ValidatorFactoryImpl.<init>(ValidatorFactoryImpl.java:135)
at org.hibernate.validator.HibernateValidator.buildValidatorFactory(HibernateValidator.java:38)
at org.hibernate.validator.internal.engine.AbstractConfigurationImpl.buildValidatorFactory(AbstractConfigurationImpl.java:433)
at io.dropwizard.jersey.validation.Validators.newValidatorFactory(Validators.java:26)
at io.dropwizard.setup.Bootstrap.<init>(Bootstrap.java:67)
at io.dropwizard.Application.run(Application.java:86)
at com.company.api.CompanyService.main(CompanyService.java:571)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:567)
at javassist.Loader.run(Loader.java:328)
at com.company.custom.metadata.CompanyServiceRun.run(CompanyServiceRun.java:151)
at com.company.custom.metadata.CompanyServiceRun.main(CompanyServiceRun.java:198)
Edit: As per the suggestion, now I am upgrading my project to Java 17. But I still got the same error and stack trace.
This is the problem:
https://learn.microsoft.com/en-us/java/openjdk/transition-from-java-8-to-java-11
In Java 11, using reflection to access to JDK-internal API will result
in an illegal reflective access warning. By default, the warning is
only issued for the first illegal access. Setting
--illegal-access=warn will cause a warning on every illegal
reflective access. You will find more case if illegal access with the
option set to warn. But you will also get a lot of redundant warnings.
Once the application runs on Java 11, set --illegal-access=deny to
mimic the future behavior of the Java runtime. Starting with Java 16,
the default will be --illegal-access=deny.
Up thorugh Java 16, the workaround has been --illegal-access=permit, but apparently that's no longer an option:
https://github.com/NationalSecurityAgency/ghidra/issues/3355
JDK 17: --illegal-access=permit removed #3355
This post discusses the background behind and rationale for introducing this "breaking change":
https://blogs.oracle.com/javamagazine/post/a-peek-into-java-17-continuing-the-drive-to-encapsulate-the-java-runtime-internals
I have a Java desktop application that was running fine in Java 1.8; I'm upgrading to Java 1.11 for a client, and am getting the above error.
Full stacktrace:
java.lang.ExceptionInInitializerError
at net.sourceforge.tess4j.Tesseract.init(Tesseract.java:442)
at net.sourceforge.tess4j.Tesseract.doOCR(Tesseract.java:326)
at net.sourceforge.tess4j.Tesseract.doOCR(Tesseract.java:309)
at net.sourceforge.tess4j.Tesseract.doOCR(Tesseract.java:290)
at net.sourceforge.tess4j.Tesseract.doOCR(Tesseract.java:274)
at drivingrecordtool.file.DrivingRecordPDFTextReader.getOCRText(DrivingRecordPDFTextReader.java:152)
at drivingrecordtool.file.DrivingRecordPDFTextReader.getText(DrivingRecordPDFTextReader.java:46)
at drivingrecordtool.file.DrivingRecordFileReader.doInBackground(DrivingRecordFileReader.java:78)
at drivingrecordtool.file.DrivingRecordFileReader.doInBackground(DrivingRecordFileReader.java:1)
at java.desktop/javax.swing.SwingWorker$1.call(SwingWorker.java:304)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.desktop/javax.swing.SwingWorker.run(SwingWorker.java:343)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.lang.IllegalStateException: zip file closed
at java.base/java.util.zip.ZipFile.ensureOpen(ZipFile.java:913)
at java.base/java.util.zip.ZipFile.getEntry(ZipFile.java:348)
at java.base/java.util.zip.ZipFile$1.getEntry(ZipFile.java:1130)
at java.base/java.util.jar.JarFile.getEntry0(JarFile.java:586)
at java.base/java.util.jar.JarFile.getEntry(JarFile.java:516)
at java.base/sun.net.www.protocol.jar.URLJarFile.getEntry(URLJarFile.java:131)
at java.base/java.util.jar.JarFile.getJarEntry(JarFile.java:478)
at java.base/jdk.internal.loader.URLClassPath$JarLoader.getResource(URLClassPath.java:945)
at java.base/jdk.internal.loader.URLClassPath.getResource(URLClassPath.java:315)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:455)
at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:452)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:451)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:588)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
at net.sourceforge.tess4j.util.LoadLibs.getTessAPIInstance(LoadLibs.java:83)
at net.sourceforge.tess4j.TessAPI.<clinit>(TessAPI.java:42)
... 15 more
The Tesseract library has a Java wrapper that I've used for months successfully but now seems involved in the error, whatever it is. I've been using the same DLL and started getting this failure, and I've updated the Tesseraact DLL and the wrapper to their latest version.
More puzzling is that the application runs fine within eclipse, and only fails like this when run from a command line (Windows 10). I have uninstalled and reinstalled the DLL a couple of times, rebooted the machine each time, and am running out of things to try. I went through the entire Maven dependencies list and deleted all files found there from my repository, then refreshed the eclipse project to reload all the files in the list.
I saw one suggestion of placing a breakpoint in ZipFile, but that won't help since the problem does not appear in eclipse.
I'm willing to upgrade the Java further, but it would be nice, first, to have some knowledge of what the problem is so that I have some confidence that will fix it.
Can someone suggest what might be wrong, or strategies to find out?
I am currently following a game engine tutorial by ThinMatrix, this is the video https://www.youtube.com/watch?v=VS8wlS9hF8E&t=97s, and I keep getting this error:
Exception in thread "main" java.lang.NoClassDefFoundError: sun/misc/Unsafe
at lwjgl/org.lwjgl.MemoryUtilSun$AccessorUnsafe.getUnsafeInstance(MemoryUtilSun.java:74)
at lwjgl/org.lwjgl.MemoryUtilSun$AccessorUnsafe.<init>(MemoryUtilSun.java:62)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
at java.base/java.lang.reflect.ReflectAccess.newInstance(ReflectAccess.java:128)
at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:347)
at java.base/java.lang.Class.newInstance(Class.java:645)
at lwjgl/org.lwjgl.MemoryUtil.loadAccessor(MemoryUtil.java:375)
at lwjgl/org.lwjgl.MemoryUtil.<clinit>(MemoryUtil.java:63)
at lwjgl/org.lwjgl.opengl.WindowsDisplay.setTitle(WindowsDisplay.java:523)
at lwjgl/org.lwjgl.opengl.Display.setTitle(Display.java:541)
at lwjgl/org.lwjgl.opengl.Display.createWindow(Display.java:312)
at lwjgl/org.lwjgl.opengl.Display.create(Display.java:848)
at lwjgl/org.lwjgl.opengl.Display.create(Display.java:797)
at GameEngine/renderEngine.DisplayManager.createDisplay(DisplayManager.java:20)
at GameEngine/engineTester.MainGameLoop.main(MainGameLoop.java:10)
Caused by: java.lang.ClassNotFoundException: sun.misc.Unsafe
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:520)
... 18 more
I have tried using both Java JRE 14 and Java JRE 17, both of these give me the same error. I tried reinstalling both of the above motioned JREs.
Does anyone have a solution to this?
There is no good solution to this.
The correct solution is to find and use a version of lwjgl that doesn't use Unsafe. (There may be one, but I couldn't figure it out from the release notes.)
The hack solution (for Java 17) is to use an --add-opens option to smash through the access control barriers that they have added to stop people using Unsafe.
However, as the comments on In Java 17 how do I avoid resorting to --add-opens? point out, this is at best a short term fix.
You shouldn't use Java 14. It is end-of-life.
You could roll back to an earlier LTS version of Java (Java 8 or 11) but that stops you from using newer Java features, and they will eventually go end-of-life anyway. So this is not a good solution.
Using journey browser project I have set up a simple maven project in eclipse, using the dependency provided on the page, I have tried to run the code example (also provided on the page)
And I get an NPE:
Exception in thread "main" java.lang.ExceptionInInitializerError
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:315)
at java.desktop/java.awt.Toolkit$2.run(Toolkit.java:588)
at java.desktop/java.awt.Toolkit$2.run(Toolkit.java:583)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.desktop/java.awt.Toolkit.getDefaultToolkit(Toolkit.java:582)
at java.desktop/java.awt.Toolkit.getEventQueue(Toolkit.java:1494)
at java.desktop/java.awt.EventQueue.isDispatchThread(EventQueue.java:1086)
at java.desktop/javax.swing.SwingUtilities.isEventDispatchThread(SwingUtilities.java:1493)
at com.codebrig.journey.JourneyBrowserView.<init>(JourneyBrowserView.java:78)
at com.codebrig.journey.JourneyBrowserView.<init>(JourneyBrowserView.java:71)
at JourneyBrowser.main(JourneyBrowser.java:13)
Caused by: java.lang.NullPointerException
at java.base/java.lang.ClassLoader.loadLibrary(ClassLoader.java:2646)
at java.base/java.lang.Runtime.loadLibrary0(Runtime.java:830)
at java.base/java.lang.System.loadLibrary(System.java:1870)
at java.desktop/sun.awt.windows.WToolkit$1.run(WToolkit.java:118)
at java.desktop/sun.awt.windows.WToolkit$1.run(WToolkit.java:115)
at java.base/java.security.AccessController.doPrivileged(Native Method)
at java.desktop/sun.awt.windows.WToolkit.loadLibraries(WToolkit.java:114)
at java.desktop/sun.awt.windows.WToolkit.<clinit>(WToolkit.java:129)
... 12 more
Can anyone explain what is happening and why here, I have tried this on 64bit windows with java Coretto 11(jdk11.0.7_10),I initially found a bug here, relating to loadLibray in open JDK and thought that maybe the problem, I just don't have a good enough understanding to work out how to get around it?
I'm not sure, but I think that Corretto bug is probably the one that is causing the problem. As noted, it is from their "upstream"; i.e the OpenJDK codebase. It was due to regression that appeared in jdk11.0.7 due to a backport of a fix for another problem. Apparently, the fix changes some internal JDK fields and that breaks application code. As JDK-8240521 puts it:
The backport of the JDK-8231584 changes internal JDK fields processing. The problem is that the many third-party applications copy-pasted a hack that depends on particular JDK implementation.
If I am reading the Oracle bug entries correctly, the reversion of the broken fix should be in JDK11.0.8. Alternatively, an earlier JDK 11 release than 11.0.7 shouldn't have the broken fix.
Let me know if changing your Java 11 install solves the problem. (If not, I'll see if I can get the line numbers to match up.)
My app works great with java 1.8 (and earlier), however when I rebuilt the application to use java 9, I receive the following stack trace. The reason for the update is because I need to use the new ProcessHandle.current(), which does not exist in earlier versions.
c:\>java -jar ./build/bin/DataMover.jar
DataMover Service: starting...
Exception in thread "main" java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
at java.base/java.lang.reflect.Method.invoke(Unknown Source)
at org.eclipse.jdt.internal.jarinjarloader.JarRsrcLoader.main(JarRsrcLoader.java:58)
Caused by: java.lang.NoClassDefFoundError: org/glassfish/jersey/server/ResourceConfig
at dataMoverServerPackage.Main.main(Unknown Source)
... 5 more
Caused by: java.lang.ClassNotFoundException: org.glassfish.jersey.server.ResourceConfig
at java.base/java.net.URLClassLoader.findClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
... 6 more
For whomever is curious, here is the java version output.
c:\>java -version
java version "9.0.1"
Java(TM) SE Runtime Environment (build 9.0.1+11)
Java HotSpot(TM) 64-Bit Server VM (build 9.0.1+11, mixed mode)
Here is the relevant main() function.
public static void main(String[] args)
{
try
{
...
final ResourceConfig resourceConfig = new ResourceConfig(DataMoverServerResource.class);
I did research and read that the big difference between Java 6,7,8 and Java 9 is modules. In particular earlier versions of Java included the Java EE JDK, whereas Java 9 includes the java.se module, not the EE. All com.sun.* classes are inaccessible in Java 9, as I read. These pieces of information may or may not be relevant. I do not know the internal makeup of the jersey.server API, just some articles talked of that.
I am using a jar in jar loader, so the jersey stuff is in the base jar.
I am torn between an internal dependency issue on Jersey or the jersey jar. The loader seems happy just fails later at the java.base/jdk.internal, which tells me a module might be missing.
If there were an internal module, such as java.xml.bind, like I read in one post, which is included in Java EE, then the exception trace would indicate that and I would know to add that module using the --add-module option to java, such as --add-module java.xml.bind, but that is not the case here, at least with that module.
Here is a link to one possibly relevant article. Maybe the java.net is the problem, much like the at javax.xml.bind at the bottom of the stack trace in that question was the underlying cause. I discounted the ext folder answer in this question, as that question pertained to 1.8, which works for me and I have jar-in-jar. I note the question here because it keeps turning up on searches. This question was also not relevant, though similar. The list goes on.
I use Eclipse, but build using ant. The Jersey stuff libraries are in my Maven .m2 folder. I did right click on my project and select Maven > Update. That is at 2.7.
I came across this site, which talks about Java 9 migration. In the site, I read that if you add java.se.ee, you will have access to all Java EE modules. That recommendation failed, same output. The command that I tried was:
java --add-modules java.se.ee -jar ./build/bin/DataMover.jar
I did check SO and quite a few other sites but have turned up empty so far. Thoughts?