30

これまで、java.library.pathプロパティについて次のことを学びました。

  • Javaクラスではなく、ネイティブライブラリをロードするときに使用されます
  • デフォルト値は、オペレーティングシステムによって異なります。
    • Windowsでは、PATHにマップされます
    • Linuxでは、LD_LIBRARY_PATHにマップされます
    • OS Xでは、DYLD_LIBRARY_PATHにマップされます

(上記のいずれかを誤解した場合は訂正してください)

私の動機:

Javaアプリケーションを呼び出すために設定したフレームワークからJavaアプリケーションに表示されるjava.library.pathの値を変更したいと思います。これを行うには、java.library.pathプロパティを直接設定するのではなく、マップ先のシステムパス変数を変更します。醜いOS固有のコードがない、または可能であればエッジケースを除外する、これを行うためのクリーンな方法が必要です。

私の質問:

ローカルJava実装に、どの環境変数java.library.pathがマップされるかを尋ねる方法はありますか?

次に、シェルスクリプトで、次の行に沿って何かを書くことができます。

path_var = get_library_path_variable  # the magic function I want to call
${path_var} = /my/custom/path:${${path_var}}
4

2 に答える 2

22

これは完全に不合理な質問ではありませんが、良い答えはありません。後世のために、なぜ行き詰まったのか、なぜうまくいかないのかを説明しようと思います。

  1. java.library.path環境変数からの設定は一切保証されません。で何をしたいかを指定できます-Djava.library.path=。おそらく、これはあなたがとにかく本当にやりたいことです。そのため、オプションが存在します。

  2. (少なくともWindowsでは)探している環境変数は、単に無秩序に使用されているだけではないことがわかります。このコードを試してください。

    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);
                }
            }
        }
    }
    

    実行すると、最初の2つの出力が異なることに注意してください。JavaがWindowsPATH変数を使用している場合は、最初に値をいじっています。私は何が起こっているのか調査するのをあきらめました。重要なのは、に正確に一致する環境変数がなかったということjava.library.pathです。LinuxやOSXでは試していません。マイレージは異なる場合があります

  3. このような誰かの環境変数をいじるのは本当にいいことではありません。これらはシェル全体で使用されるため、ユーザーが自分の環境に共有ライブラリを使用することを約束しますが、それはたまにしかありません。変更する唯一の本当の理由java.library.pathは、ネイティブライブラリを追加することです。ネイティブライブラリを使用している場合は、OS固有のコードがすでにあるので(プラットフォーム用にコンパイルする必要がありますよね?)、「プラットフォーム固有のエッジケースがない」という戦いはすでにあきらめています。最善の方法は、ネイティブライブラリを、システムパス(それが何であれ)がすでに検出している場所に配置するか、ライブラリのパスを永続的に追加することです。ある種のインストーラーで。これらのいずれも実行したくない場合は、@ malatのコードのバリエーションを使用し、実際のコードを出力java.library.pathしてから、その結果にパスを追加してスクリプトを作成し、-Dオプションを使用して設定することをお勧めします。実際のプログラム実行用。

于 2013-12-13T16:04:16.540 に答える
13

私のLinuxボックスでは、次のようにします。

$ 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
于 2013-12-10T15:12:27.720 に答える