I want to load my own native libraries in my java application. Those native libraries depend upon third-party libraries (which may or may not be present when my application is installed on the client computer).
Inside my java application, I ask the user to specify the location of dependent libs. Once I have this information, I am using it to update the "LD_LIBRARY_PATH" environment variable using JNI code. The following is the code snippet that I am using to change the "LD_LIBRARY_PATH" environment variable.
Java code
public static final int setEnv(String key, String value) { if (key == null) { throw new NullPointerException("key cannot be null"); } if (value == null) { throw new NullPointerException("value cannot be null"); } return nativeSetEnv(key, value); } public static final native int nativeSetEnv(String key, String value);
Jni code (C)
JNIEXPORT jint JNICALL Java_Test_nativeSetEnv(JNIEnv *env, jclass cls, jstring key, jstring value) { const char *nativeKey = NULL; const char *nativeValue = NULL; nativeKey = (*env)->GetStringUTFChars(env, key, NULL); nativeValue = (*env)->GetStringUTFChars(env, value, NULL); int result = setenv(nativeKey, nativeValue, 1); return (jint) result; }
I also have corresponding native methods to fetch the environment variable.
I can successfully update the LD_LIBRARY_PATH (this assertion is based on the output of C routine getenv()
.
I am still not able to load my native library. The dependent third-party libraries are still not detected.
Any help/pointers are appreciated. I am using Linux 64 bit.
Edit:
I wrote a SSCE (in C) to test if dynamic loader is working. Here is the SSCE
#include #include #include #include int main(int argc, const char* const argv[]) { const char* const dependentLibPath = "...:"; const char* const sharedLibrary = "..."; char *newLibPath = NULL; char *originalLibPath = NULL; int l1, l2, result; void* handle = NULL; originalLibPath = getenv("LD_LIBRARY_PATH"); fprintf(stdout,"\nOriginal library path =%s\n",originalLibPath); l1 = strlen(originalLibPath); l2 = strlen(dependentLibPath); newLibPath = (char *)malloc((l1+l2)*sizeof(char)); strcpy(newLibPath,dependentLibPath); strcat(newLibPath,originalLibPath); fprintf(stdout,"\nNew library path =%s\n",newLibPath); result = setenv("LD_LIBRARY_PATH", newLibPath, 1); if(result!=0) { fprintf(stderr,"\nEnvironment could not be updated\n"); exit(1); } newLibPath = getenv("LD_LIBRARY_PATH"); fprintf(stdout,"\nNew library path from the env =%s\n",newLibPath); handle = dlopen(sharedLibrary, RTLD_NOW); if(handle==NULL) { fprintf(stderr,"\nCould not load the shared library: %s\n",dlerror()); exit(1); } fprintf(stdout,"\n The shared library was successfully loaded.\n"); result = dlclose(handle); if(result!=0) { fprintf(stderr,"\nCould not unload the shared library: %s\n",dlerror()); exit(1); } return 0; }
The C code also does not work. Apparently, the dynamic loader is not rereading the LD_LIBRARY_PATH environment variable. I need to figure out how to force the dynamic loader to re-read the LD_LIBRARY_PATH environment variable.
See the accepted answer here:
Changing LD_LIBRARY_PATH at runtime for ctypes
In other words, what you're trying to do isn't possible. You'll need to launch a new process with an updated LD_LIBRARY_PATH (e.g., use ProcessBuilder and update environment() to concatenate the necessary directory)