Adjust java.library.path at Runtime

13 Mar

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

object AdjustJavaLibraryPathAtRuntime {
def addJavaLibraryPath(pathToAdd: String): Unit = {
val oldPath = Option(System.getProperty("java.library.path"))
// only add path if its not already included
val newPath = => if(!currentPath.contains(pathToAdd))
pathToAdd + ":" + currentPath
// set the system property
System.setProperty("java.library.path", newPath)
// force the refresh
val field = classOf[ClassLoader].getDeclaredField("sys_paths")
val oldRtPath = field.get(null)
field.set(null, null) // this makes sure the pathes are refreshed
field.set(null, oldRtPath) // make sure to do this, else java.nio will not work anymore!

So, this code (in Scala, but its quite similar in Java) consists of two parts:

  1. Getting the current value of the java.library.path system property
  2. Making sure its actually used by the JVM by doing some reflection hacky stuff.

Getting the current value of the java.library.path system property L7-16

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.

Making sure its actually used by the JVM L18-23

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( [info] at java.base/java.nio.file.Files.copy( [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( [info] at java.base/java.util.concurrent.ThreadPoolExecutor$ [info] at java.base/
Code language: PHP (php)

Comment Form