Closed KaYOLii closed 7 months ago
I analysed it a bit more. What I found out: This misbehaviour was introduced in Version 2.9.2.
When I use Version 2.9.1 there is no classloading problem in Tomcat, when doing a redeployment (copy war to webapps, after deleting the old one before). The Native Lib shows up in Tomcat Temp Folder. As you can see in the pictures, with every new deployment, the native lib gets updated.
Deploy Number 1
Deploy Number 2
But in Version 2.9.2 this process is broken.
Deploy Number 1
Deploy Number 2 The result of the second deployment is an empty folder. I think, this is a result of the error.
When I see this discussion: https://stackoverflow.com/questions/53444627/java-lang-unsatisfiedlinkerror-native-library-already-loaded-in-another-classloa and see, what I found out, then I guess, that we run into this problem, because since Version 2.9.2 the name of the native lib does not change anymore. Like it did with Version 2.9.1 in every deployment.
Is there any Workaround possible?
I see an issue that might be causing your problem. Please test the following SNAPSHOT version and see if your problem is resolved:
SNAPSHOT Version: 2.10.5-SNAPSHOT SNAPSHOT Direct Download Link SNAPSHOT Instructions
Thank you very much for your response and the SNAPSHOT version!
I just tested it, but unfortunately the problem still exists.
2024-03-25 09:22:03 WARN AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'yodaApp': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'yodaSystemService' defined in file [/Users/xxx/Dev/apache-tomcat-9.0.74-OhneIntellij/webapps/display/WEB-INF/classes/de/yolii/yoda/services/YodaSystemService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serialDeviceConnectionService': Invocation of init method failed; nested exception is java.lang.UnsatisfiedLinkError: Cannot load native library. Errors as follows:
[1]: no jSerialComm in java.library.path
[2]: Native Library /Users/xxx/.jSerialComm/2.10.5-4d76b4c-SNAPSHOT/libjSerialComm.jnilib already loaded in another classloader
[3]: Loading for arch: aarch64
[4]: Native Library /Users/xxx/Dev/apache-tomcat-9.0.74-OhneIntellij/temp/jSerialComm/2.10.5-4d76b4c-SNAPSHOT/libjSerialComm.jnilib already loaded in another classloader
[5]: Loading for arch: x86_64
[6]: Native Library /Users/xxx/Dev/apache-tomcat-9.0.74-OhneIntellij/temp/jSerialComm/2.10.5-4d76b4c-SNAPSHOT/libjSerialComm.jnilib already loaded in another classloader
[7]: Loading for arch: x86
[8]: Native Library /Users/xxx/Dev/apache-tomcat-9.0.74-OhneIntellij/temp/jSerialComm/2.10.5-4d76b4c-SNAPSHOT/libjSerialComm.jnilib already loaded in another classloader
[9]: Loading for arch: aarch64
[10]: Native Library /Users/xxx/.jSerialComm/2.10.5-4d76b4c-SNAPSHOT/libjSerialComm.jnilib already loaded in another classloader
[11]: Loading for arch: x86_64
[12]: Native Library /Users/xxx/.jSerialComm/2.10.5-4d76b4c-SNAPSHOT/libjSerialComm.jnilib already loaded in another classloader
[13]: Loading for arch: x86
[14]: Native Library /Users/xxx/.jSerialComm/2.10.5-4d76b4c-SNAPSHOT/libjSerialComm.jnilib already loaded in another classloader
Deploy Number 1
Deploy Number 2
The more I'm looking into this, the more it's looking like a Tomcat issue. From Googling other similar issues like this, it looks like Tomcat just doesn't like have native libraries that are extracted at runtime due to the way it handles loading those libraries (multiple times, which isn't allowed in Java). The solution seems to be to manually extract the native library and put it somewhere that Tomcat knows about (I've never used Tomcat, so I'm not much help here about how to configure it.) Once you do that, you may need to start up the app with the jSerialComm.library.path
flag set to let jSerialComm know where to expect to find its native library.
The only alternative I can think of would be to make jSerialComm try to extract its native library to a location with a randomized number in the file name (like it was doing many releases earlier) after failing in all other cases. I'd prefer not to do that as it has the potential to litter non-Tomcat user's temp directories with lots of jSerialComm files over time, but it's a potential option. Actually, maybe I could create another startup flag (like jSerialComm.library.randomizeNativeName
) that you could set to enable this behavior.
Thanks for the response!
What we did now: Use jSerialComm Version 2.9.1 (the last version with the randomized number in the file name). Use jSerialComm to get all serial Ports, for each port execute Linux command to get VendorId and based on that, execute the necessary code.
Another startup flag (like jSerialComm.library.randomizeNativeName
) would be great. Then we could use the newest version including getVendorId()
.
This has been added. Please test the most recent SNAPSHOT version of the library and see if this resolves the issue:
SNAPSHOT Version: 2.10.5-SNAPSHOT SNAPSHOT Direct Download Link SNAPSHOT Instructions
You will now need to either set the system property as a command-line flag
-DjSerialComm.library.randomizeNativeName="true"
or by calling the following within your own application before accessing any SerialPort functionality:
System.setProperty("jSerialComm.library.randomizeNativeName", "true")
Hey Will, thank you very much for adding the feature! I tested it, it works! No exceptions to see after redeploy and the native library is available with the new name.
Deploy Number 1
Deploy Number 2
Do you know already, when this feature will be available in the official version?
Available now with the release of v2.11.0.
Great! Thank you very much!
Hello,
we used Version 1.3.11 for some time without any problems.
Now we want to upgrade to Version 2.10.4, because we want to use this very helpful methods:
serialPort.getVendorID();
serialPort.getProductID();
But unfortunately we run into this error, when we deploy our war into tomcat 9 on production system (Ubuntu 16).
2024-03-13 16:39:35 ERROR SpringApplication - Application run failed org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'yodaApp': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'yodaSystemService' defined in file [/opt/tomcat/webapps/display/WEB-INF/classes/de/yolii/yoda/services/YodaSystemService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serialDeviceConnectionService': Invocation of init method failed; nested exception is java.lang.UnsatisfiedLinkError: com.fazecast.jSerialComm.SerialPort.getCommPortsNative()[Lcom/fazecast/jSerialComm/SerialPort;
I can reproduce this error on my local dev machine (MacBook with MacOS 14.1.1) with more output:
2024-03-14 12:26:54 WARN AnnotationConfigServletWebServerApplicationContext - Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'yodaApp': Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'yodaSystemService' defined in file [/Users/xxx/Dev/apache-tomcat-9.0.74-OhneIntellij/webapps/display/WEB-INF/classes/de/yolii/yoda/services/YodaSystemService.class]: Unsatisfied dependency expressed through constructor parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'serialDeviceConnectionService': Invocation of init method failed; nested exception is java.lang.UnsatisfiedLinkError: Cannot load native library. Errors as follows: [1]: no jSerialComm in java.library.path [2]: Native Library /Users/xxx/.jSerialComm/2.10.3/libjSerialComm.jnilib already loaded in another classloader
It happens on third autodeploy(delete war, copy war into webapps folder) in tomcat.We tried other versions. We see, the first version where
serialPort.getVendorID()
is available, is Version 2.10.0. With this version we also see this error.Do you have any tip for us?
Thanks in Advance