At my current task, I had to make sure a native library is able to be loaded. I didn’t want to adjust the parameters of the JVM for this, so I had to patch the java.library.path at runtime.
This post is inspired by this post
So, this code (in Scala, but its quite similar in Java) consists of two parts:
This is straightforward. We do a System.getProperty and then just retrieve it, check if the path we want to add is already there or not. If not, we add it and then set the property.
This is the tricky part. We have to use reflection to get access to the sys_path
field of the Classloader. This is usually set to the path where the RT.jar
file is located. We make the field accessible, get its current value, then set it to null and set it back to its previous value. Changing the fields value actually triggers the reloading of the paths’, so that the java.library.path
variable is read again and used from now on.
Compared to the inspiration post by Fahd Shariff, we make sure to set the sys_paths
field back to a reasonable value, else the JVM is unable to use other native-functions, e.g. `java.nio` and you would get errors like:
[info] java.lang.ExceptionInInitializerError
[info] at java.base/sun.nio.fs.UnixFileSystemProvider.copy(UnixFileSystemProvider.java:258)
[info] at java.base/java.nio.file.Files.copy(Files.java:1295)
[info] at com.acme.calculation.demo.GamsIntegrationSpec.$anonfun$new$52(GamsIntegrationSpec.scala:278)
[info] at zio.internal.FiberContext.evaluateNow(FiberContext.scala:361)
[info] at zio.internal.FiberContext.$anonfun$evaluateLater$1(FiberContext.scala:775)
[info] at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
[info] at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
[info] at java.base/java.lang.Thread.run(Thread.java:834)
Code language: PHP (php)