felix-atomos icon indicating copy to clipboard operation
felix-atomos copied to clipboard

UnsupportedClassVersionError on startup with multi-release jars that contain higher JVM version

Open bosschaert opened this issue 1 year ago • 1 comments

When Atomos starts up it loads all the classes by introspecting Jars.

However it also loads classes from multi-release jars that are for a version that's higher than the currently running JVM.

An exception that shows this:

Caused by: java.lang.UnsupportedClassVersionError: META-INF/versions/19/com/fasterxml/jackson/core/io/doubleparser/FastDoubleSwar has been compiled by a more recent version of the Java Runtime (class file version 63.0), this version of the Java Runtime only recognizes class file versions up to 61.0
	at java.base/java.lang.ClassLoader.defineClass1(Native Method)
	at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1012)
	at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
	at java.base/java.net.URLClassLoader.defineClass(URLClassLoader.java:524)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:427)
	at java.base/java.net.URLClassLoader$1.run(URLClassLoader.java:421)
	at java.base/java.security.AccessController.doPrivileged(AccessController.java:712)
	at java.base/java.net.URLClassLoader.findClass(URLClassLoader.java:420)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:587)
	at java.base/java.net.FactoryURLClassLoader.loadClass(URLClassLoader.java:872)
	at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:520)
	at org.apache.felix.atomos.utils.core.LauncherImpl.lambda$loadClasses$5(LauncherImpl.java:82)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:179)
	at java.base/java.util.zip.ZipFile$EntrySpliterator.tryAdvance(ZipFile.java:567)
	at java.base/java.util.Spliterator.forEachRemaining(Spliterator.java:332)
	at java.base/java.util.stream.ReferencePipeline$Head.forEach(ReferencePipeline.java:762)
	at java.base/java.util.stream.ReferencePipeline$7$1.accept(ReferencePipeline.java:276)
	at java.base/java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:197)
	at java.base/java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1625)
	at java.base/java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:509)
	at java.base/java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:499)
	at java.base/java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:921)
	at java.base/java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.base/java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:682)
	at org.apache.felix.atomos.utils.core.LauncherImpl.loadClasses(LauncherImpl.java:89)
	at org.apache.felix.atomos.utils.core.LauncherImpl.execute(LauncherImpl.java:193)
	at org.apache.felix.atomos.utils.core.LauncherImpl.execute(LauncherImpl.java:152)
...

A naive fix for this can be seen here, where the META-INF version are being ignored: https://github.com/bosschaert/felix-atomos/commit/4a5683253e0ad7831c67821dbbbde636042eaa38#diff-8c0eef3cf462bc384fa77905eb1bf7fef2cca2177f046e5f6a0ad00e61d236fe

However, a real fix should be more sophisticated, probably taking the current JVM version and then walking back to pick the highest META-INF/versions directory that would still apply, but not trying to load classes from higher JVM versions.

bosschaert avatar Dec 21 '23 16:12 bosschaert