33

So far I've learned the following about the java.library.path property:

  • It's used when loading native libraries, as opposed to java classes
  • Its default value depends on the operating system:
    • On Windows, it maps to PATH
    • On Linux, it maps to LD_LIBRARY_PATH
    • On OS X, it maps to DYLD_LIBRARY_PATH

(Please correct me if I've misunderstood any of the above)

My motivation:

I want to modify the value of java.library.path seen by a Java application from the framework I've set up to invoke the Java application. I want to do this not by setting the java.library.path property directly, but instead by modifying the system path variable that it maps to. I'd like a clean way to do this that doesn't have ugly OS-specific code or leave out edge cases if possible.

My question:

Is there a way to ask the local Java implementation what environment variable java.library.path maps to?

Then, in a shell script, I'd be able to write something along the lines of:

path_var = get_library_path_variable  # the magic function I want to call
${path_var} = /my/custom/path:${${path_var}}
Charlie
  • 819
  • 3
  • 12
  • 17
  • Run a program that prints it out? – Dave Newton Mar 04 '12 at 15:52
  • My feeling about that is that firing up a JVM is a slow, expensive operation (though I don't know exactly how slow and expensive). Also, it requires writing and maintaining another program rather than just the few lines in a shell script I'm hoping for. – Charlie Mar 04 '12 at 16:30
  • On second thought, I don't know if that would work. What would be a Java program that would print that out? – Charlie Mar 04 '12 at 16:32
  • 8
    `S.o.p(System.getProperty("java.library.path"));` and yes, there's a JVM startup penalty. – Dave Newton Mar 04 '12 at 16:34
  • ...can Java do something akin to "ruby -e"? – Charlie Mar 04 '12 at 16:41
  • System.getProperty("java.library.path") gives the value of java.library.path (e.g. "/usr/lib:/lib"), not the name of the library path variable (e.g. "DYLD_LIBRARY_PATH"). – Charlie Mar 04 '12 at 16:42
  • 1
    There is no cross-platform environment property in user-space. No, Java has no immediate execution mode--wouldn't really make sense. – Dave Newton Mar 04 '12 at 16:44
  • “There is no cross-platform environment property in user-space.” What space other than user-space might we be working with? – Charlie Mar 04 '12 at 16:47
  • Don't know, and doesn't matter. What you're looking for (AFAICT) doesn't exist. There's nothing in user-space that defines internal Java loadpaths. – Dave Newton Mar 04 '12 at 16:59
  • Realize also that there's no guarantee that "java.library.path" maps to any environment variable *at all*, since it can be specified by a `-D` option when starting the JVM. – Ian McLaird Dec 10 '13 at 18:38

2 Answers2

26

This isn't a totally unreasonable question, but there's no good answer, so for posterity, I'll make an attempt at explaining why you got stuck, and why it won't work.

  1. java.library.path isn't guaranteed to be set from an environment variable at all. You can specify what you want it to be with -Djava.library.path=. More than likely, this is what you really want to do anyway. That's why the option exists.

  2. It turns out (on windows at least), that the environment variable you're looking for isn't just used unmolested. Try this code.

    package com.stackoverflow;
    
    import java.util.Map;
    
    public class LibPathFinder {
        public static void main(String[] args) {
            String javaLibPath = System.getProperty("java.library.path");
            Map<String, String> envVars = System.getenv();
            System.out.println(envVars.get("Path"));
            System.out.println(javaLibPath);
            for (String var : envVars.keySet()) {
                System.err.println("examining " + var);
                if (envVars.get(var).equals(javaLibPath)) {
                    System.out.println(var);
                }
            }
        }
    }
    

    You'll note that when it runs, the first two things it prints are different. If Java is using the windows PATH variable, it's fiddling with the value first. I gave up investigating what was going on. The point was, there wasn't an environment variable that exactly matched the java.library.path. I didn't try on Linux or OSX, your mileage may vary

  3. It's really not very nice to mess with somebody's environment variables like this. They're used for the entire shell, so you're committing your users to have your shared library on their environment, but only sometimes. The only real reason to change java.library.path is to add native libraries. If you're using native libraries, then you have OS-specific code already (it has to be compiled for the platform, right?), so you've really already given up the fight for "no platform-specific edge cases". The best thing to do is to put your native library in a place where the system path (whatever that may be) will already find it, or add your library's path to it permanently with an installer of some kind. If you don't want to do either of those things, then I'd suggest using a variation of @malat's code, printing the real java.library.path, and then appending your path to that result in your script, and then use the -D option to set it for the real program run.

Ian McLaird
  • 5,507
  • 2
  • 22
  • 31
15

On my linux box, here is what I would do:

$ cat GetSystemProperty.java
import java.util.Properties;
import java.util.Enumeration;

public class GetSystemProperty {
  public static void main(String args[]) {
    if( args.length == 0 ) {
      Properties p = System.getProperties();
      Enumeration keys = p.keys();
      while (keys.hasMoreElements()) {
        String key = (String)keys.nextElement();
        String value = (String)p.get(key);
        System.out.println(key + " : " + value);
      }
    }
    else {
      for (String key: args) {
        System.out.println(System.getProperty( key ));
      }
    }
  }
}
$ javac GetSystemProperty.java
$ java GetSystemProperty java.library.path
/usr/lib/jvm/java-6-openjdk/jre/lib/amd64/server:/usr/lib/jvm/java-6-openjdk/jre/lib/amd64:/usr/lib/jvm/java-6-openjdk/jre/../lib/amd64:/usr/java/packages/lib/amd64:/usr/lib/jni:/lib:/usr/lib
malat
  • 12,152
  • 13
  • 89
  • 158
  • 1
    This doesn't really do what he's asking for. He doesn't want the *value* of `java.library.path`, he wants the *name of the variable it was populated from*. – Ian McLaird Dec 13 '13 at 15:19
  • 2
    On the other hand, googling for this function (getting the value of `java.library.path`) got me to this answer. +1. – E.P. Aug 11 '14 at 15:25