Could not load FFI provider when using module-info.java - java

my Linux Java application uses bluetooth devices. I use this library in order to communicate with bluez stack : https://github.com/hypfvieh/bluez-dbus.
It worked very well until I added module-info.java to my client code. Suddenly I got this error:
Exception in thread "main" java.lang.UnsatisfiedLinkError: could not load FFI provider jnr.ffi.provider.jffi.Provider
at jnr.ffi#2.1.15/jnr.ffi.provider.InvalidRuntime.newLoadError(InvalidRuntime.java:101)
at jnr.ffi#2.1.15/jnr.ffi.provider.InvalidRuntime.findType(InvalidRuntime.java:42)
at jnr.ffi#2.1.15/jnr.ffi.Struct$NumberField.(Struct.java:872)
at jnr.ffi#2.1.15/jnr.ffi.Struct$Unsigned16.(Struct.java:1240)
at jnr.unixsocket#0.33/jnr.unixsocket.SockAddrUnix$DefaultSockAddrUnix.(SockAddrUnix.java:209)
at jnr.unixsocket#0.33/jnr.unixsocket.SockAddrUnix.create(SockAddrUnix.java:174)
at jnr.unixsocket#0.33/jnr.unixsocket.UnixSocketAddress.(UnixSocketAddress.java:53)
at dbus.java#3.2.3/org.freedesktop.dbus.connections.transports.UnixSocketTransport.(UnixSocketTransport.java:32)
at dbus.java#3.2.3/org.freedesktop.dbus.connections.transports.TransportFactory.createTransport(TransportFactory.java:37)
at dbus.java#3.2.3/org.freedesktop.dbus.connections.AbstractConnection.(AbstractConnection.java:161)
at dbus.java#3.2.3/org.freedesktop.dbus.connections.impl.DBusConnection.(DBusConnection.java:334)
at dbus.java#3.2.3/org.freedesktop.dbus.connections.impl.DBusConnection.getConnection(DBusConnection.java:149)
at dbus.java#3.2.3/org.freedesktop.dbus.connections.impl.DBusConnection.getConnection(DBusConnection.java:169)
at dbus.java#3.2.3/org.freedesktop.dbus.connections.impl.DBusConnection.getConnection(DBusConnection.java:219)
at dbus.java#3.2.3/org.freedesktop.dbus.connections.impl.DBusConnection.getConnection(DBusConnection.java:184)
at bluez.dbus#0.1.3/com.github.hypfvieh.bluetooth.DeviceManager.createInstance(DeviceManager.java:74)
at ...
Caused by: java.lang.UnsatisfiedLinkError: could not get native definition for type POINTER, original error message follows: java.lang.UnsatisfiedLinkError: could not locate stub library in jar file. Tried [jni/x86_64-Linux/libjffi-1.2.so, /jni/x86_64-Linux/libjffi-1.2.so]
at jffi#1.2.23/com.kenai.jffi.internal.StubLoader.getStubLibraryStream(StubLoader.java:450)
at jffi#1.2.23/com.kenai.jffi.internal.StubLoader.loadFromJar(StubLoader.java:375)
at jffi#1.2.23/com.kenai.jffi.internal.StubLoader.load(StubLoader.java:278)
at jffi#1.2.23/com.kenai.jffi.internal.StubLoader.(StubLoader.java:487)
at java.base/java.lang.Class.forName0(Native Method)
at java.base/java.lang.Class.forName(Class.java:427)
at jffi#1.2.23/com.kenai.jffi.Init.load(Init.java:68)
at jffi#1.2.23/com.kenai.jffi.Foreign$InstanceHolder.getInstanceHolder(Foreign.java:49)
at jffi#1.2.23/com.kenai.jffi.Foreign$InstanceHolder.(Foreign.java:45)
at jffi#1.2.23/com.kenai.jffi.Foreign.getInstance(Foreign.java:103)
at jffi#1.2.23/com.kenai.jffi.Type$Builtin.lookupTypeInfo(Type.java:242)
at jffi#1.2.23/com.kenai.jffi.Type$Builtin.getTypeInfo(Type.java:237)
at jffi#1.2.23/com.kenai.jffi.Type.resolveSize(Type.java:155)
at jffi#1.2.23/com.kenai.jffi.Type.size(Type.java:138)
at jnr.ffi#2.1.15/jnr.ffi.provider.jffi.NativeRuntime$TypeDelegate.size(NativeRuntime.java:178)
at jnr.ffi#2.1.15/jnr.ffi.provider.AbstractRuntime.(AbstractRuntime.java:48)
at jnr.ffi#2.1.15/jnr.ffi.provider.jffi.NativeRuntime.(NativeRuntime.java:57)
at jnr.ffi#2.1.15/jnr.ffi.provider.jffi.NativeRuntime.(NativeRuntime.java:41)
at jnr.ffi#2.1.15/jnr.ffi.provider.jffi.NativeRuntime$SingletonHolder.(NativeRuntime.java:53)
at jnr.ffi#2.1.15/jnr.ffi.provider.jffi.NativeRuntime.getInstance(NativeRuntime.java:49)
at jnr.ffi#2.1.15/jnr.ffi.provider.jffi.Provider.(Provider.java:29)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at java.base/jdk.internal.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
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.ReflectAccess.newInstance(ReflectAccess.java:124)
at java.base/jdk.internal.reflect.ReflectionFactory.newInstance(ReflectionFactory.java:346)
at java.base/java.lang.Class.newInstance(Class.java:604)
at jnr.ffi#2.1.15/jnr.ffi.provider.FFIProvider$SystemProviderSingletonHolder.getInstance(FFIProvider.java:68)
at jnr.ffi#2.1.15/jnr.ffi.provider.FFIProvider$SystemProviderSingletonHolder.(FFIProvider.java:57)
at jnr.ffi#2.1.15/jnr.ffi.provider.FFIProvider.getSystemProvider(FFIProvider.java:35)
at jnr.ffi#2.1.15/jnr.ffi.Runtime$SingletonHolder.(Runtime.java:82)
at jnr.ffi#2.1.15/jnr.ffi.Runtime.getSystemRuntime(Runtime.java:67)
at jnr.unixsocket#0.33/jnr.unixsocket.SockAddrUnix.(SockAddrUnix.java:46)
at jnr.unixsocket#0.33/jnr.unixsocket.SockAddrUnix$DefaultSockAddrUnix.(SockAddrUnix.java:208)
at jnr.unixsocket#0.33/jnr.unixsocket.SockAddrUnix.create(SockAddrUnix.java:174)
at jnr.unixsocket#0.33/jnr.unixsocket.UnixSocketAddress.(UnixSocketAddress.java:53)
at dbus.java#3.2.3/org.freedesktop.dbus.connections.transports.UnixSocketTransport.(UnixSocketTransport.java:32)
at ...
I tried to require everything related to this error in the module-info.java without success:
module org.example {
requires dbus.java;
requires dbus.java.nativefd;
requires bluecove.linux.custom;
requires bluez.dbus;
requires jnr.ffi;
requires jnr.x86asm;
requires jnr.posix;
requires jnr.enxio;
requires jnr.unixsocket;
requires jnr.constants;
requires jnr.a64asm;
}
Thank you in advance.

TL;DR
This worked for me…
java --patch-module jffi={{your.own.location}}/com/github/jnr/jffi/1.3.0/jffi-1.3.0-native.jar …
The long version
I downloaded this example project. It's not a JPMS project. But I added module-info.java files to each of the four sub-projects.
I updated the project's com.github.jnr:jnr-ffi dependency from 2.0.9 to 2.1.5 to match the version I see in your stack trace. And I added the following dependencies…
…
<dependency>
<groupId>com.github.hypfvieh</groupId>
<artifactId>dbus-java</artifactId>
<version>3.2.3</version>
</dependency>
<dependency>
<groupId>com.github.hypfvieh</groupId> <artifactId>bluez-dbus</artifactId>
<version>0.1.3</version>
</dependency>
<dependency>
<groupId>com.rm5248</groupId>
<artifactId>dbus-java-nativefd</artifactId>
<version>1.0</version>
</dependency>
…
Those were added so that I could then define each one of my four module-info.java descriptors to be pretty much exactly like yours…
module get.pid{
exports getpid;
requires dbus.java;
requires dbus.java.nativefd;
requires bluez.dbus;
requires jnr.ffi;
requires jffi;
requires jnr.x86asm;
requires jnr.posix;
requires jnr.enxio;
requires jnr.unixsocket;
requires jnr.constants;
requires jnr.a64asm;
}
Before I did the --patch-module, I ran one of the example projects and got the exact same error you got.
But with the following command, all the example applications ran perfectly fine as modules…
java --patch-module jffi={{your.own.location}}/com/github/jnr/jffi/1.3.0/jffi-1.3.0-native.jar --add-modules org.objectweb.asm --add-exports org.objectweb.asm/org.objectweb.asm=jnr.ffi --add-exports org.objectweb.asm/org.objectweb.asm.signature=jnr.ffi --module-path {{path.to.all.the.jars}} -m get.pid/getpid.Getpid
The add-modules and add-exports are crucial too. So don't leave those out.

Related

BouncyCastleProvider not found by JAR on Lucee

We are successfully using the AmazonPay API for Java (amazon-pay-api-sdk-java-2.2.2.jar) in Adobe ColdFusion. We recently introduced Lucee (on Jetty, also running on OpenJDK 8) and attempted to run the same code (relevant excerpt):
payConfig = createObject("java", "com.amazon.pay.api.PayConfiguration").init();
payConfig.setPrivateKey("...");
However, upon calling setPrivateKey, which will arrive at Security.addProvider(new BouncyCastleProvider()); through PayConfiguration, we receive a java.lang.ClassNotFoundException:
lucee.runtime.exp.NativeException: org.bouncycastle.jce.provider.BouncyCastleProvider
at com.amazon.pay.api.PayConfiguration.setPrivateKey(PayConfiguration.java:77)
[...]
at java.lang.Thread.run(Thread.java:823)
Caused by: java.lang.NoClassDefFoundError: org.bouncycastle.jce.provider.BouncyCastleProvider
... 57 more
Caused by: java.lang.ClassNotFoundException: org.bouncycastle.jce.provider.BouncyCastleProvider not found by amazon.pay.api.sdk.java.2.2.2 [49]
at org.apache.felix.framework.BundleWiringImpl.findClassOrResourceByDelegation(BundleWiringImpl.java:1597)
at org.apache.felix.framework.BundleWiringImpl.access$300(BundleWiringImpl.java:79)
at org.apache.felix.framework.BundleWiringImpl$BundleClassLoader.loadClass(BundleWiringImpl.java:1982)
at java.lang.ClassLoader.loadClass(ClassLoader.java:881)
... 57 more
We have placed all dependencies (bcprov-jdk15on-1.65.jar being BouncyCastle) in /lucee-server/context/lib. Creating BouncyCastleProvider within a .cfm/.cfc does work as expected:
createObject("java", "org.bouncycastle.jce.provider.BouncyCastleProvider").init()
I don't understand what Lucee's classloader is doing here. What am I missing?
I don't know what Lucee's classloader is doing either to be honest, but this kind of error seems to be quite common when loading certain more complex jars via the Lucee /lib path. It's likely there are "class clashes" going on somewhere.
Lucee is now OSGi based which means the best way of avoiding this is to load third-party java libraries as OSGi bundles. Some libraries are already packaged for OSGi and others can be converted fairly easily. More details here.
The Amazon library doesn't seem to be OSGi friendly, although it could probably be converted without too much effort.
For now, I would look at JavaLoader as the simplest way of getting it working. I don't have any valid Amazon keys to test fully with, but using JavaLoader I was able to at least call the payConfig.setPrivateKey() method without getting a ClassNotFoundException error.

NoSuchMethodError in jna-platform

I wanna make a new release of the application but when starting it it throws NoSuchMethodError
java.lang.NoSuchMethodError: com.sun.jna.Native.load(Ljava/lang/String;Ljava/lang/Class;Ljava/util/Map;)Lcom/sun/jna/Library;
at com.sun.jna.platform.win32.Shell32.<clinit>(Shell32.java:45)
at com.sun.jna.platform.win32.Shell32Util.getFolderPath(Shell32Util.java:54)
at com.sun.jna.platform.win32.Shell32Util.getFolderPath(Shell32Util.java:71)
at com.faforever.client.preferences.PreferencesService.<clinit>(PreferencesService.java:78)
at com.faforever.client.FafClientApplication.main(FafClientApplication.java:55)
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 com.exe4j.runtime.LauncherEngine.launch(LauncherEngine.java:85)
at com.exe4j.runtime.WinLauncher.main(WinLauncher.java:94)
at com.install4j.runtime.launcher.WinLauncher.main(WinLauncher.java:25)
Similar to
NoSuchMethodError using JNA User32 platform map
However I do have version 5.0.0 of both libaries.
It is about this project https://github.com/FAForever/downlords-faf-client it uses gradle as a build tool...
Also I decompiled the installed program and found the method that java claims is not present in the jna libary. Which I find super weird.
Also I check no other dependency has a dependency on jna.
But the thing that is the strangest is it work when I run it all from intelij (oracle jdk 10) but then if I build the installer(openjdk 10 on travis) it does not (same machine).
Also it worked before and we did not change anything about the code related to jna nor the library version. What might have changed is the openjdk version travis uses, but I can not see how that would be related.
Does anybody have an idea what might cause this....
This is the actual code that fails:
Paths.get(Shell32Util.getFolderPath(ShlObj.CSIDL_COMMON_APPDATA), "FAForever")
Even though I thik it is not the problem...
This is the jvm log https://drive.google.com/file/d/11RpxvFubYM7vCoAE-Kx_6EkIKADPQofE/view?usp=sharing
Of which this is probably the important part :
[3.689s][debug][class,resolve ] com.sun.jna.Native java.lang.Object (super)
[3.689s][debug][class,resolve ] com.sun.jna.Native com.sun.jna.Version (interface)
[3.689s][debug][class,resolve ] com.sun.jna.platform.win32.Shell32 com.sun.jna.Native Shell32.java:45 (explicit)
[3.689s][debug][protectiondomain ] Checking package access
[3.689s][debug][protectiondomain ] class loader: a 'jdk/internal/loader/ClassLoaders$AppClassLoader'{0x00000000ee70de08} protection domain: a 'java/security/ProtectionDomain'{0x00000000ef103908} loading: 'com/sun/jna/Native'
[3.689s][debug][protectiondomain ] granted
[3.689s][trace][protectiondomain ] pd set count = #1
[3.689s][debug][class,resolve ] com.sun.jna.platform.win32.Shell32 com.sun.jna.Native Shell32.java:45
[3.689s][info ][stacktrace ] java.lang.NoSuchMethodError, 12
[3.689s][info ][exceptions ] Exception <a 'java/lang/NoSuchMethodError'{0x00000000ef00dd70}: com.sun.jna.Native.load(Ljava/lang/String;Ljava/lang/Class;Ljava/util/Map;)Lcom/sun/jna/Library;> (0x00000000ef00dd70)
thrown [t:/workspace/open/src/hotspot/share/interpreter/linkResolver.cpp, line 741]
for thread 0x00000000031a5000
Probably the discord library I added also contains jna, see log from jvm:
[3.689s][info ][class,load ] com.sun.jna.Native source: file:/E:/DownlordClient%20RC/Downlord's%20FAF%20Client/lib/discord-rpc-1.6.2.jar
The NoSuchMethodError related to JNA is almost always related to having an older version of JNA somewhere in your dependency list, even if you also have the current version.
Your comment here gives the hint:
Probably the discord library I added also contains jna, see log from jvm
Looking at that library's POM we see:
<name>DiscordRPC</name>
<version>1.6.2</version>
...
<dependencies>
<dependency>
<groupId>net.java.dev.jna</groupId>
<artifactId>jna</artifactId>
<version>4.5.1</version>
<scope>compile</scope>
</dependency>
...
</dependencies>
So you are likely in a situation where Gradle's dependency resolution has chosen to use the older jna even though you have both available, and you likely have jna-platform version 5.0.0 and jna version 4.5.1.
You should update your build script to force use of version 5.0.0 (or more recent) for both jna and jna-platform.

How to fix 'IncompatibleClassChangeError: Implementing Class' when importing Cplex library in Maven project?

I'm trying to import Cplex on a Maven project (using Ubuntu 16.04).
So I added cplex.jar to maven repository with this command :
mvn install:install-file -DgroupId=cplex -DartifactId=cplex -Dversion=12.8 -Dpackaging=jar -Dfile=/cplex/install/dir/CPLEX_Studio128/cplex/lib/cplex.jar
I added the dependency to my pom.xml :
<dependency>
<groupId>cplex</groupId>
<artifactId>cplex</artifactId>
<version>12.8</version>
</dependency>
I added the link of the Cplex Native Library (.so files) to the LD_LIBRARY_PATH :
export LD_LIBRARY_PATH="/cplex/install/dir/CPLEX_Studio128/cplex/bin/x86-64_linux"
But when I'm running my maven project with :
mvn exec:java -Dexec.mainClass="main.main"
I got the following error : java.lang.IncompatibleClassChangeError: Implementing Class
I have already checked this question but I don't understand, in this case, what kind of incompatibles binary changes can be made.
Is it possible that there's some "incompatibles binary changes" ?
And if it's not, is there any other explanation than an "incompatibles binary changes" to this error ?
Edit
I also use OPL library (same installation than Cplex library) and I have only the 12.8 version of Cplex and Oplall on my system.
I tried to clean and build again but got the same error.
This is the code I try to run (in ModelFileEvaluator.java) :
IloOplFactory.setDebugMode(true);
IloOplFactory oplF = new IloOplFactory();
IloOplErrorHandler errHandler = oplF.createOplErrorHandler();
IloOplModelSource modelSource = oplF.createOplModelSource(fileName);
IloOplSettings settings = oplF.createOplSettings(errHandler);
IloOplModelDefinition def = oplF.createOplModelDefinition(modelSource,settings);
IloCplex cplex = oplF.createCplex();
And this is the full backtrace :
java.lang.IncompatibleClassChangeError: Implementing class
at java.lang.ClassLoader.defineClass1(java.base#9-internal/Native Method)
at java.lang.ClassLoader.defineClass(java.base#9-internal/ClassLoader.java:939)
at java.security.SecureClassLoader.defineClass(java.base#9-internal/SecureClassLoader.java:152)
at java.net.URLClassLoader.defineClass(java.base#9-internal/URLClassLoader.java:463)
at java.net.URLClassLoader.access$100(java.base#9-internal/URLClassLoader.java:76)
at java.net.URLClassLoader$1.run(java.base#9-internal/URLClassLoader.java:371)
at java.net.URLClassLoader$1.run(java.base#9-internal/URLClassLoader.java:365)
at java.security.AccessController.doPrivileged(java.base#9-internal/Native Method)
at java.net.URLClassLoader.findClass(java.base#9-internal/URLClassLoader.java:364)
at java.lang.ClassLoader.loadClass(java.base#9-internal/ClassLoader.java:486)
at java.lang.ClassLoader.loadClass(java.base#9-internal/ClassLoader.java:419)
at java.lang.ClassLoader.defineClass1(java.base#9-internal/Native Method)
at java.lang.ClassLoader.defineClass(java.base#9-internal/ClassLoader.java:939)
at java.security.SecureClassLoader.defineClass(java.base#9-internal/SecureClassLoader.java:152)
at java.net.URLClassLoader.defineClass(java.base#9-internal/URLClassLoader.java:463)
at java.net.URLClassLoader.access$100(java.base#9-internal/URLClassLoader.java:76)
at java.net.URLClassLoader$1.run(java.base#9-internal/URLClassLoader.java:371)
at java.net.URLClassLoader$1.run(java.base#9-internal/URLClassLoader.java:365)
at java.security.AccessController.doPrivileged(java.base#9-internal/Native Method)
at java.net.URLClassLoader.findClass(java.base#9-internal/URLClassLoader.java:364)
at java.lang.ClassLoader.loadClass(java.base#9-internal/ClassLoader.java:486)
at java.lang.ClassLoader.loadClass(java.base#9-internal/ClassLoader.java:419)
at ilog.opl.IloOplFactory.createCplex(IloOplFactory.java:227)
at main.ModelFileEvaluator.testFile(ModelFileEvaluator.java:86)
at main.ModelFileEvaluator.main(ModelFileEvaluator.java:53)
at sun.reflect.NativeMethodAccessorImpl.invoke0(java.base#9-internal/Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(java.base#9-internal/NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(java.base#9-internal/DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(java.base#9-internal/Method.java:531)
at org.codehaus.mojo.exec.ExecJavaMojo$1.run(ExecJavaMojo.java:282)
at java.lang.Thread.run(java.base#9-internal/Thread.java:804)
Using OPL requires using oplall.jar. That jar is not compatible with cplex.jar. You can use only one of the two at the same time. Removing cplex.jar from the class path should fix the issue.

Unable to use OverthereConnection through commandline

I have enabled overthereconnection's through Spring IDE, but when I try running my maven-built application via commandline, I get this error:
Exception in thread "main" java.util.ServiceConfigurationError: jar (Unknown file system scheme! May be the class path doesn't contain the respective driver module or it isn't set up correctly?)
at de.schlichtherle.truezip.fs.FsAbstractCompositeDriver.newController(FsAbstractCompositeDriver.java:33)
at de.schlichtherle.truezip.fs.FsDefaultManager.getController0(FsDefaultManager.java:95)
at de.schlichtherle.truezip.fs.FsDefaultManager.getController(FsDefaultManager.java:78)
at de.schlichtherle.truezip.file.TFile.getController(TFile.java:1497)
at de.schlichtherle.truezip.file.TFile.parse(TFile.java:687)
at de.schlichtherle.truezip.file.TFile.<init>(TFile.java:659)
at de.schlichtherle.truezip.file.TFile.<init>(TFile.java:601)
at nl.javadude.scannit.reader.TFiles.tFile(TFiles.java:23)
at nl.javadude.scannit.reader.ArchiveEntrySupplier.withArchiveEntries(ArchiveEntrySupplier.java:23)
at nl.javadude.scannit.Worker.scanFiles(Worker.java:59)
at nl.javadude.scannit.Worker.scanURI(Worker.java:53)
at nl.javadude.scannit.Worker.scan(Worker.java:46)
at nl.javadude.scannit.Scannit.<init>(Scannit.java:41)
at com.xebialabs.overthere.Overthere.boot(Overthere.java:74)
at com.xebialabs.overthere.Overthere.<clinit>(Overthere.java:69)
at com.emc.ondemand.agent.core.discovery.AnalyzeSelf.constructODEnvironmentForSingleHost(AnalyzeSelf.java:172)
at com.emc.ondemand.agent.core.discovery.DiscoverEnvironment.discoverEnvironment(DiscoverEnvironment.java:85)
at com.emc.ondemand.agent.core.discovery.DiscoverEnvironment.main(DiscoverEnvironment.java:48)
My code call looks like:
// establish winrm connection to target host
ConnectionOptions options = new ConnectionOptions();
options.set(ADDRESS, myHost.getIP());
options.set(USERNAME, user);
options.set(PASSWORD, pass);
options.set(OPERATING_SYSTEM, WINDOWS);
options.set(CONNECTION_TYPE, WINRM_NATIVE); // was not able to get WINRM_INTERNAL to work with processes
connection = Overthere.getConnection("cifs", options);
This is the only dependency I have:
<dependency>
<groupId>com.xebialabs.overthere</groupId>
<artifactId>overthere</artifactId>
<version>4.2.1</version>
</dependency>
It does pull in the correct Truezip classes so I'm at a loss as to what it means exactly.
I guess your dependency is an uber-JAR? Please check if there is a file named META-INF/services/de.schlichtherle.truezip.fs.spi.FsDriverService on the class path. Among others, it needs to contain the following entry:
de.schlichtherle.truezip.fs.archive.zip.ZipDriverService
If that's not the case, then please contact the creator of the overthere artifact and tell them that they appear to have incorrectly assembled their artifact from the TrueZIP dependencies.
In all cases, you should be able to fix this problem by adding another dependency to your class path:
<dependency>
<groupId>de.schlichtherle.truezip</groupId>
<artifactId>truezip-driver-zip</artifactId>
<version>7.7.9</version>
</dependency>

Javassist failure in hibernate: invalid constant type: 60

I'm creating a cli tool to manage an existing application. Both the application and the tests build fine and run fine but despite that I receive a javassist failure when running my cli tool that exists within the jar:
INFO: Bytecode provider name : javassist
...
INFO: Hibernate EntityManager 3.5.1-Final
Exception in thread "main" javax.persistence.PersistenceException: Unable to configure EntityManagerFactory
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:371)
at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:55)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
...
at com.sophware.flexipol.admin.AdminTool.<init>(AdminTool.java:40)
at com.sophware.flexipol.admin.AdminTool.main(AdminTool.java:69)
Caused by: java.lang.RuntimeException: Error while reading file:flexipol-jar-with-dependencies.jar
at org.hibernate.ejb.packaging.NativeScanner.getClassesInJar(NativeScanner.java:131)
at org.hibernate.ejb.Ejb3Configuration.addScannedEntries(Ejb3Configuration.java:467)
at org.hibernate.ejb.Ejb3Configuration.addMetadataFromScan(Ejb3Configuration.java:457)
at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:347)
... 11 more
Caused by: java.io.IOException: invalid constant type: 60
at javassist.bytecode.ConstPool.readOne(ConstPool.java:1027)
at javassist.bytecode.ConstPool.read(ConstPool.java:970)
at javassist.bytecode.ConstPool.<init>(ConstPool.java:127)
at javassist.bytecode.ClassFile.read(ClassFile.java:693)
at javassist.bytecode.ClassFile.<init>(ClassFile.java:85)
at org.hibernate.ejb.packaging.AbstractJarVisitor.checkAnnotationMatching(AbstractJarVisitor.java:243)
at org.hibernate.ejb.packaging.AbstractJarVisitor.executeJavaElementFilter(AbstractJarVisitor.java:209)
at org.hibernate.ejb.packaging.AbstractJarVisitor.addElement(AbstractJarVisitor.java:170)
at org.hibernate.ejb.packaging.FileZippedJarVisitor.doProcessElements(FileZippedJarVisitor.java:119)
at org.hibernate.ejb.packaging.AbstractJarVisitor.getMatchingEntries(AbstractJarVisitor.java:146)
at org.hibernate.ejb.packaging.NativeScanner.getClassesInJar(NativeScanner.java:128)
... 14 more
Since I know the jar is fine as the unit and integration tests run against it, I thought it might be a problem with javassist, so I tried cglib. The bytecode provider then shows as cglib but I still get the exact same stack trace with javassist present in it.
cglib is definitely in the classpath:
$ unzip -l flexipol-jar-with-dependencies.jar | grep cglib | wc -l
383
I've tried with both hibernate 3.4 and 3.5 and get the exact same error. Is this a problem with javassist?
UPDATE: I can run the application successfully within Eclipse (Right click->Run As->Java Application), but using the maven-generated jar-with-dependencies fails. I presume the difference is that with Eclipse javassist isn't inspecting the containing jar, rather, it's inspecting all of the class files (and perhaps a few dependent 3rd-party jars).
The problem is ultimately caused by an invalid class in icu4j-2.6.1 as can be seen in this post. Specifically, this file is invalid:
com/ibm/icu/impl/data/LocaleElements_zh__PINYIN.class
Here's a simple way to identify a corrupt file:
for x in PATH_TO_EXTRACTED_JAR/**/*.class; do
java -cp PATH_TO/javassist.jar javassist.tools.Dump $x >/dev/null 2>&1 || echo "$x is invalid"
done
This file is being included by indirectly by maven through its transitive dependencies which is why I didn't recognize that page as referencing the error and a file contained within the jar as being the culprit and cause of the problem. Here's how it ended up included in my jar-with-dependencies bundle:
jaxen-1.1.1 -> xom-1.0 -> icu4j-2.6.1
After adding the following exclusion to the jaxen dependency, everything worked correctly for me (but be careful if you need its localization pieces):
<exclusions>
<exclusion>
<groupId>com.ibm.icu</groupId>
<artifactId>icu4j</artifactId>
</exclusion>
</exclusions>
Another option would be to remove the offending file(s) from the jar file:
#!/bin/sh
shopt -s extglob
shopt -s globstar
for x in **/*.jar ; do
zip -d $x 'com/ibm/icu/impl/data/*_zh*' >/dev/null 2>&1 && echo "Removed corrupted files from $x"
done

Categories