How to Set Ld_Library_Path for Java Process

Not able to set LD_LIBRARY_PATH for Java process

Dunes answer solves your problem, but I would strongly suggest a different approach in this particular case. Instead of relying on a shell to set the environment arguments, you should do this in your Java code. This way you don't need to know which shells exist on the system and what their language is, it will just work on all platforms.

To do this, you can use the Runtime.exec(String[] cmd, String[] environment) overload (javadoc). As the second parameter you can pass an array which contains all the environment variables the subprocess will see.

A little bit nicer even is the ProcessBuilder API:

ProcessBuilder pb = new ProcessBuilder("executable.so");
Map<String, String> env = pb.environment();
env.put("LD_LIBRARY_PATH", "/proj/something");
Process javap = pb.start();
javap.waitFor();

This way, the subprocess will inherit all environment variables from the Java process, and additionally have the LD_LIBRARY_PATH variable set.

How to set a unix dynamic library path (LD_LIBRARY_PATH) in Java?

See my answer to another question. The best way is to not use an external shell to set the environment variable (your code doesn't work because it will not set the variable globally, only for the bash process), but to set the variable from within Java. Much easier and it works (and on all platforms, regardless of which shell is installed).

Setting of the LD_LIBRARY_PATH within a Java application

LD_LIBRARY_PATH is an environment varable, not a system properety. As tehre is no System.setEnv method I doubt you can do what you seek for. Read here: How do I set environment variables from Java?

What is LD_LIBRARY_PATH and how to use it?

Typically you must set java.library.path on the JVM's command line:

java -Djava.library.path=/path/to/my/dll -cp /my/classpath/goes/here MainClass

Set LD_LIBRARY_PATH or java.library.path for YARN / Hadoop2 Jobs

Short Answer: in your mapred-site.xml put the following

<property>
<name>mapred.child.java.opts</name>
<value>-Djava.library.path=$PATH_TO_NATIVE_LIBS</value>
</property>

Explanation:
The Job/Applications aren't executed by yarn rather than by a mapred (map/reduce) container, whoose configuration is controlled by the mapred-site.xml file. Specifying custom java parameters there causes that actual workers to spin with the correct path

How to add .so file to the java.library.path in Linux

Add the containing directory to LD_LIBRARY_PATH before launching the application

        export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/some/pathOfContainingDirectory

Use java -XshowSettings:properties to show the java.library.path (and others) value.

LD_LIBRARY_PATH ignored on Android sometimes

Here is a simple wrapper I wrote about:

#include <android/log.h>
#include <dlfcn.h>
#include <stdio.h>
#include <string.h>

typedef int (*main_t)(int argc, char** argv);

static int help(const char* argv0)
{
printf("%s: simple wrapper to work around LD_LIBRARY_PATH\n\n", argv0);
printf("Args: executable, list all the libraries you need to load in dependency order, executable again, optional parameters\n");
printf("example: %s /data/local/ttte /data/data/app/com.testwrapper/lib/ttt.so /data/local/ttte 12345\n", argv0);
printf("Note: the executable should be built with CFLAGS=\"-fPIC -pie\", LDFLAGS=\"-rdynamic\"\n");

return -1;
}

int main(int argc, char** argv)
{
int rc, nlibs;
void *dl_handle;

if (argc < 2)
{
return help(argv[0]);
}

__android_log_print(ANDROID_LOG_DEBUG, "wrapper", "running '%s'", argv[1]);

for (nlibs = 2; ; nlibs++)
{
if (nlibs >= argc)
{
return help(argv[0]);
}

__android_log_print(ANDROID_LOG_DEBUG, "wrapper", "loading '%s'", argv[nlibs]);
dl_handle = dlopen(argv[nlibs], 0); // do not keep the handle, except for the last
__android_log_print(ANDROID_LOG_DEBUG, "wrapper", "loaded '%s' -> %p", argv[nlibs], dl_handle);
if (strcmp(argv[1], argv[nlibs]) == 0)
{
break;
}
}

main_t pmain = (main_t)dlsym(dl_handle, "main");
__android_log_print(ANDROID_LOG_DEBUG, "wrapper", "found '%s' -> %p", "main", pmain);
rc = pmain(argc - nlibs, argv + nlibs);

// we are exiting the process anyway, don't need to clean the handles actually

// __android_log_print(3, "wrapper", "closing '%s'", argv[1]);
// dlclose(dl_handle);

return 0;
}

To keep it readable, I drop most of error handling, unessential cleanup, and handling of special cases.

Android.mk for this executable:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := wrapper
LOCAL_SRC_FILES := wrapper/main.c
LOCAL_LDLIBS := -llog

include $(BUILD_EXECUTABLE)

Note that you must take care of deployment: packaging this wrapper into the APK, extraction to some local path (never to USB storage or to /sdcard!), marking it as executable (chmod 777).

These are the additional parameters you must supply when you build the executables you run through the wrapper. If you use ndk-build to build them, it looks as follows:

LOCAL_C_FLAGS   += -fPIC -pie
LOCAL_LDFLAGS += -rdynamic

Note that you don't need to chmod for these executables anymore. Another trick: you can build the secondary executables into shared libraries, and the same wrapper will continue to work! This saves the trouble of deployment of these binaries. NDK and Android build will deliver them safely through libs/armeabi of the APK to your app's lib directory automagically.

Update

There seems to be a much easier solution, using the ProcessBuilder with modified environment: https://stackoverflow.com/a/8962189/192373.



Related Topics



Leave a reply



Submit