在Hadoop上运行Java本机库

在Hadoop上运行Java本机库,java,hadoop,java-native-interface,Java,Hadoop,Java Native Interface,我试图在本地运行的hadoop上运行Gurobi优化器。古罗比使用JNI。为了测试如何在hadoop上运行它,我编写了以下代码 public static void main(String[] args) throws Exception { try { GRBEnv env2 = new GRBEnv(); env2.set(GRB.IntParam.OutputFlag, 0); } catch (Exception e) { e.pr

我试图在本地运行的hadoop上运行Gurobi优化器。古罗比使用JNI。为了测试如何在hadoop上运行它,我编写了以下代码

  public static void main(String[] args) throws Exception {
    try {
      GRBEnv env2 = new GRBEnv();
      env2.set(GRB.IntParam.OutputFlag, 0);
    } catch (Exception e) {
      e.printStackTrace();
    }

    Configuration conf = new Configuration();
    int res = ToolRunner.run(conf, new GurobiTest(), args);
    System.exit(res);
}
在使用之前,Gurobi需要设置一些环境变量(其中LD_LIBRARY_PATH指向Gurobi本机库):

当我打包项目并使用jvm运行它时

java -cp ./target/GurobiOnHadoop-0.0.1-SNAPSHOT-jar-with-dependencies.jar mpi.de.test.GurobiTest
一切似乎都很好

但是当我试图在hadoop上运行它时

hadoop jar ./target/GurobiOnHadoop-0.0.1-SNAPSHOT-jar-with-dependencies.jar mpi.de.test.GurobiTest -libjars ./target/GurobiOnHadoop-0.0.1-SNAPSHOT-jar-with-dependencies.jar
我犯了一个错误

Exception in thread "main" java.lang.UnsatisfiedLinkError: no GurobiJni56 in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
    at java.lang.Runtime.loadLibrary0(Runtime.java:849)
    at java.lang.System.loadLibrary(System.java:1088)
    at gurobi.GurobiJni.<clinit>(GurobiJni.java:193)
    at gurobi.GRBEnv.<init>(GRBEnv.java:16)
    at gurobi.GRBEnv.<init>(GRBEnv.java:11)
    at mpi.de.test.GurobiTest.main(GurobiTest.java:89)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.hadoop.util.RunJar.main(RunJar.java:197)
线程“main”java.lang.UnsatisfiedLinkError中出现异常:java.library.path中没有GurobiJni56
位于java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
位于java.lang.Runtime.loadLibrary0(Runtime.java:849)
位于java.lang.System.loadLibrary(System.java:1088)
在GurobiJni.GurobiJni(GurobiJni.java:193)
在gurobi.GRBEnv.(GRBEnv.java:16)
在gurobi.GRBEnv.(GRBEnv.java:11)
位于mpi.de.test.GurobiTest.main(GurobiTest.java:89)
在sun.reflect.NativeMethodAccessorImpl.invoke0(本机方法)处
在sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)中
在sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)中
位于java.lang.reflect.Method.invoke(Method.java:606)
位于org.apache.hadoop.util.RunJar.main(RunJar.java:197)
我试过很多不同的方法。我已经在hadoop运行命令中添加了“-Djava.library.path=/home/username/System/gurobi563/linux64/lib”。我已经在hadoop env.sh中设置了所需的环境变量。我尝试从代码级别加载*.so文件(例如使用系统) .load(“/home/username/System/gurobi563/linux64/lib/libGurobiJni56.so”);)。我还尝试将这些库发送到hadoop分布式文件系统,从该位置加载文件或将环境变量指向该位置

我正在使用:

java版本“1.7.0_60”

hadoop-0.20.2-cdh3u6


Debian 7.5 wheezy

事实证明,我在hadoop-env.sh中设置的JAVA_库路径不正确。

很难说所提供的信息到底是怎么回事。首先,如果要指定路径或文件名,则应使用System.loadLibrary而不是.load。如果使用.load,则需要设置java.library.path,并且参数必须是不带lib前缀或文件扩展名的库名称。需要检查的其他事项:hadoop进程是否在/home/username/System/gurobi563/linux64/lib上有+r-x?您是否在hadoop配置中指定了JAVA_库路径和LD_库路径?JAVA_库路径和LD_库路径在hadoop-env.sh中设置。/home/username/System/gurobi563/linux64/lib中的文件具有-rwxrwx权限。System.loadLibrary(“libGurobiJni56”)返回java.lang.unsatifiedLinkError:java.library.path中没有libGurobiJni56.so(即使我在本地运行java时设置了LD_library_path)。System.loadLibrary(“/home/username/System/gurobi563/linux64/lib/libGurobiJni56.so”)或System.load(“GurobiJni56”);
Exception in thread "main" java.lang.UnsatisfiedLinkError: no GurobiJni56 in java.library.path
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1886)
    at java.lang.Runtime.loadLibrary0(Runtime.java:849)
    at java.lang.System.loadLibrary(System.java:1088)
    at gurobi.GurobiJni.<clinit>(GurobiJni.java:193)
    at gurobi.GRBEnv.<init>(GRBEnv.java:16)
    at gurobi.GRBEnv.<init>(GRBEnv.java:11)
    at mpi.de.test.GurobiTest.main(GurobiTest.java:89)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:606)
    at org.apache.hadoop.util.RunJar.main(RunJar.java:197)