Java 9 Runtime Exception calling org.glassfish.jersey.server.ResourceConfig - java

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?

Related

java.lang.NoClassDefFoundError: sun/reflect/Reflection while running from jar

I built a jar using Ecplise, setting the main class properly.
When I run "java -Xms512m -Xmx1024m -jar foo.jar config.ini" from the command line (Windows), I get an below exception
Exception in thread "main" java.lang.NoClassDefFoundError: sun/reflect/Reflection
at com.jidesoft.plaf.UIDefaultsLookup.getCallerClassLoader(Unknown Source)
at com.jidesoft.plaf.UIDefaultsLookup.get(Unknown Source)
at com.jidesoft.plaf.vsnet.VsnetWindowsUtils.initComponentDefaultsWithMenu(Unknown Source)
at com.jidesoft.plaf.LookAndFeelFactory.installJideExtension(Unknown Source)
at com.jidesoft.plaf.LookAndFeelFactory.installJideExtension(Unknown Source)
at com.jidesoft.plaf.LookAndFeelFactory.installJideExtension(Unknown Source)
at com.jidesoft.swing.JideButton.updateUI(Unknown Source)
at java.desktop/javax.swing.AbstractButton.init(AbstractButton.java:2136)
at java.desktop/javax.swing.JButton.<init>(JButton.java:131)
at java.desktop/javax.swing.JButton.<init>(JButton.java:85)
at com.jidesoft.swing.JideButton.<init>(Unknown Source)
at com.jidesoft.swing.JideButton.<init>(Unknown Source)
at ro.sync.ui.application.lb.<init>(Unknown Source)
at ro.sync.exml.m.d.<init>(Unknown Source)
at ro.sync.exml.m.d.dqe(Unknown Source)
at ro.sync.exml.m.c.<init>(Unknown Source)
at ro.sync.ecss.extensions.api.component.AuthorComponentFactory$2.<init>(Unknown Source)
at ro.sync.ecss.extensions.api.component.AuthorComponentFactory.init(Unknown Source)
at ro.sync.ecss.extensions.api.component.AuthorComponentFactory.init(Unknown Source)
at ro.sync.ecss.samples.AuthorComponentSample.<init>(AuthorComponentSample.java:311)
at ro.sync.ecss.samples.AuthorComponentSample.main(AuthorComponentSample.java:545)
Caused by: java.lang.ClassNotFoundException: sun.reflect.Reflection
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
... 21 more
If you were really using Java 8 to run this, your JAR would probably work just fine ...
But the evidence suggests that you are actually running the code in a Java 9 or later JVM, where the "missing" sun.reflect.Reflection class has been moved to the jdk.unsupported module.
The simplest solution will be to run this on Java 8 only. Alternatively, you will need to figure out where in your code-base (or dependencies) the sun.reflect.Reflection class is being used. (It looks like it is in com.jidesoft.plaf code.)
If it is your code that is using the class, figure out how to do what Reflection is doing ... without relying on internal APIs.
If it is a dependency, look for a newer version of the dependency that supports Java 9 and later.
This may help you work around the (apparent) Java 9+ compatibility issues in the jidesoft code.
It looks like you may be using the JIDE Common Layer. There is version of this on GitHub in the jidesoft/jide-oss
There is a file in the repo called README JDK9.txt. It says the following:
--add-exports java.desktop/com.sun.java.swing.plaf.windows=ALL-UNNAMED
--add-exports java.desktop/javax.swing.plaf.synth=ALL-UNNAMED
--add-exports java.desktop/sun.swing=ALL-UNNAMED
--add-exports java.desktop/sun.awt=ALL-UNNAMED
--add-exports java.desktop/sun.awt.image=ALL-UNNAMED
--add-exports java.desktop/sun.awt.shell=ALL-UNNAMED
--add-exports java.desktop/sun.awt.dnd=ALL-UNNAMED
--add-exports java.desktop/sun.awt.windows=ALL-UNNAMED
--add-exports java.base/sun.security.action=ALL-UNNAMED
Remove xerces.jar from the classpath
These would appear to be instructions on how to use the dependency on Java 9 or later.
In the repo there also seem to be versions of the source code for Java 8 and Java 9.
I'm afraid, I can't tell you how to build and run the Java 9 version of the code. If it is too hard for you to figure it out, my advice is to run your application on Java 8.
Finally, there are things in the jide-oss issue tracker that suggest that this code is unlikely to get much "love" in the future. In particular, there doesn't appear to be any enthusiasm for addressing the various problems caused by the codebase's reliance on JDK internal APIs. This will be increasingly problematic as the Java team close off access to those APIs. So I would advise:
Start looking for alternatives for the functionality that the jidesoft code is providing you.
Don't develop new applications that rely on jide-oss.
For an existing application, either plan to rework the code to use the alternative, or resolve to make Java 8 (and no higher!) the required platform for your application.

How should I compile my java project targeting Java SE 8?

I have a Java Project (an application to play connect 4) and I want to turn it into an executable file. I created this project in VsCode, and I am using the Java Language Server (see details below). I extracted the .jar file, and used Launch4J to turn it into an executable, and when I run it, I get an error message (see below).
I researched the problem, and it seems that I need to compile my code targeting Java SE 8 rather than 17 (I have 17 currently installed). Could anyone explain to me how I should do this, or is there anything else I'm doing wrong?
The project has multiple files. I'm not sure if this is relevant, but the project has no external dependencies, although it does use javax.swing, javax.sound, and java.awt (as well as java.io.File, java.io.IOException, and java.util.Random, but I'm pretty sure those are irrelevant).
I have eclipse installed if it's necessary, but I only installed it today, and have no experience using it at all. The JDK I am using is (I believe) version 1.8.0_321. (At least this is what I get when I type in java -version.)
The Java compiler version is javac 17.0.2
When I try to run the executable generated by Launch4J, I this is the error I get:
Exception in thread "main" java.lang.UnsupportedClassVersionError: Main has been compiled by a more recent version of the Java Runtime (class file version 61.65535), this version of the Java Runtime only recognizes class file versions up to 52.0
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.launcher.LauncherHelper.checkAndLoadMain(Unknown Source)
And the popup error:
Java Virtual Machine Launcher
Error: A JNI error has occurred, please check your installation and try again.
Here are the Settings I used in Launch4J:
Output File: C:\Users\username\OneDrive\Coding\Java Connect 4 v.2\Connect 4.exe
Jar: C:\Users\username\OneDrive\Coding\Java\Java Connect 4 v.2\Java Connect 4 v.2.jar
Don't wrap the jar, launch only: NOT ticked
Wrapper Manifest: none
Change dir: .
Command Line args: none
Process priority: Normal
Both Options NOT ticked
Min JRE version: 1.2.0, Prefer public JRE, but use JDK runtime if newer
Max JRE version: none, First 64-bit, then 32-bit. (This was the default.)
All other settings are default.
Download the latest Java JDK version as .exe file (“x64 Installer”) and install by clicking on the .jar file.
Now the server should start again
#Holger has answered this question. The answer to the problem was to ship a custom JRE image with the application with the help of JLink. That way it can be used regardless of the local version of JRE.

java.lang.ClassNotFoundException: java.lang.constant.Constable after upgrading libraries

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.

NoSuchMethodError: <init> in com.sun.glass.ui.win.WinApplication.staticScreen_getScreens

Since upgrading to install4j 7.0.5 and Java 10, users that run our application on Windows more and more often report that the application throws
java.lang.NoSuchMethodError: <init>
at javafx.graphics/com.sun.glass.ui.win.WinApplication.staticScreen_getScreens(Native Method)
at javafx.graphics/com.sun.glass.ui.Screen.initScreens(Unknown Source)
at javafx.graphics/com.sun.glass.ui.Application.lambda$run$1(Unknown Source)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(Unknown Source)
at java.base/java.lang.Thread.run(Unknown Source)
UiLauncher (WAITING)
at java.base#10.0.1/jdk.internal.misc.Unsafe.park(Native Method)
at java.base#10.0.1/java.util.concurrent.locks.LockSupport.park(Unknown Source)
at java.base#10.0.1/java.util.concurrent.locks.AbstractQueuedSynchronizer.parkAndCheckInterrupt(Unknown Source)
at java.base#10.0.1/java.util.concurrent.locks.AbstractQueuedSynchronizer.doAcquireSharedInterruptibly(Unknown Source)
at java.base#10.0.1/java.util.concurrent.locks.AbstractQueuedSynchronizer.acquireSharedInterruptibly(Unknown Source)
at java.base#10.0.1/java.util.concurrent.CountDownLatch.await(Unknown Source)
at platform/javafx.graphics#10.0.1/com.sun.javafx.tk.quantum.QuantumToolkit.startup(Unknown Source)
at platform/javafx.graphics#10.0.1/com.sun.javafx.application.PlatformImpl.startup(Unknown Source)
at platform/javafx.graphics#10.0.1/com.sun.javafx.application.PlatformImpl.startup(Unknown Source)
at platform/javafx.swing#10.0.1/javafx.embed.swing.JFXPanel.initFx(Unknown Source)
at platform/javafx.swing#10.0.1/javafx.embed.swing.JFXPanel.<init>(Unknown Source)
at java.base#10.0.1/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base#10.0.1/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at java.base#10.0.1/jdk.internal.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.base#10.0.1/java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.base#10.0.1/java.lang.Class.newInstance(Unknown Source)
at app//...
when starting the application though the install4j created exe file. The error is triggered by creating an instance of javafx.embed.swing.JFXPanel through reflection:
Class.forName("javafx.embed.swing.JFXPanel").newInstance();
We currently suspect that for some reason an incompatible DLL is loaded (glass.dll seems to contain the native method mentioned in the stacktrace).
Does anyone know how to prevent this error? E.g. is there are way to restrict the java.library.path used when executing the application through the install4j-generated exe to the Java runtime environment that was embedded in the installer and installed locally with the application?
According to one user, the error does not occur if the application is started "manually" using the
java -jar app.jar
command. So it seems the problem lies with the install4j created executable.
The workaround to this problem seems to be to remove all occurences of "glass.dll" from your system %PATH%.
I believe a fix must be implemented somewhere else, though; either in the Java runtime or in the Install4j code, but cannot be implemented in the Java code of the actual app:
For some reason the Java runtime version in Install4j checks the bundled JRE last when locating the libraries. In this case the problematic native library is glass.dll which should contain the requested <init> method but if anywhere in your %PATH% there is an older, incompatible version of glass.dll (e.g. from a previous Java 8 installation) that file will be loaded with a higher precedence and then the application will crash natively.
This is not a problem in the code of the application (the java code), nor a problem with the bundled JDK, this is a problem of how the install-4j-generated exe files (or maybe Java internally) tries to resolve native dlls. Instead of checking all path elements first, it should be checking the bundled JRE directory, first.
With Procmon you can see that it loads arbitrarily placed glass.dll files in the path, first: I added one from JDK 1.8 into one of my path elements and got this (plus the crash):

wildfly swarm deployment crash with java 9

Packaging a hello world application generated by the wildfly swarm generator and built with Java9 crashes when deploying the application.
It seems that the reason is the swarm/undertow dependency to the org.ow2.asm:asm-all:5.0.4 which is not Java9 ready.
Is there a known workaround, or a known date when swarm will be ready for Java9?
The stacktrace is:
Caused by: java.lang.IllegalArgumentException
at org.objectweb.asm.ClassReader.<init>(Unknown Source)
at org.objectweb.asm.ClassReader.<init>(Unknown Source)
at org.objectweb.asm.ClassReader.<init>(Unknown Source)
at org.wildfly.swarm.jaxrs.internal.JAXRSArchiveImpl.isJAXRS(JAXRSArchiveImpl.java:117)
at org.wildfly.swarm.jaxrs.internal.JAXRSArchiveImpl.isJAXRS(JAXRSArchiveImpl.java:96)
at org.wildfly.swarm.jaxrs.JAXRSArchive.isJAXRS(JAXRSArchive.java:55)
at org.wildfly.swarm.jaxrs.internal.DefaultJAXRSWarDeploymentFactory.create(DefaultJAXRSWarDeploymentFactory.java:46)
at org.wildfly.swarm.jaxrs.internal.DefaultJAXRSWarDeploymentFactory$Proxy$_$$_WeldClientProxy.create(Unknown Source)
org.wildfly.swarm.container.runtime.deployments.DefaultDeploymentCreator.createDefaultDeployment(DefaultDeploymentCreator.java:69)
The class files in JDK 9 are v53.0 so you need ASM 6. ASM has always thrown IAE when encountering class files that are newer that it supports.
The IllegalArgumentException can be possibly caused by different class version when scanning the bytecode which in your case which is done by org.ow2.asm:asm-all:5.0.4.
We faced similar issue faced in jetty.project#1758 which I'd to try and solve by building the jetty.project by myself but to eventually realize that org.ow2.asm would chain me back still.
The latest available version of asm on maven is :
<dependency>
<groupId>org.ow2.asm</groupId>
<artifactId>asm-all</artifactId>
<version>6.0_BETA</version>
</dependency>
In case of jetty (and probably swarm as well) they were not able to integrate this as 6.0_BETA is not a valid OSGI version number:
Caused by: java.lang.IllegalArgumentException: invalid range
"[6.0_BETA,6.0_BETA]": invalid version "6.0_BETA": non-numeric
"0_BETA"
Related to the above a read to how jetty tried solving it.
There is already a tracker to the ow2.asm invalid version bug which you can follow.

Categories

Resources