Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/390.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 如何在linux上为JNI应用程序编译动态库?_Java_C++_Linux_Java Native Interface_Compilation - Fatal编程技术网

Java 如何在linux上为JNI应用程序编译动态库?

Java 如何在linux上为JNI应用程序编译动态库?,java,c++,linux,java-native-interface,compilation,Java,C++,Linux,Java Native Interface,Compilation,我正在使用Ubuntu 10.10 我就是这么做的 Hello.java: 然后我运行以下命令: dierre@cox:~/Scrivania/provajni$ javac Hello.java dierre@cox:~/Scrivania/provajni$ javah -jni Hello 我获得了Hello.class和Hello.h 你好,h: 生成文件hellolib.so 但是,当我尝试使用java Hello运行它时,出现了以下错误: Exception in thread

我正在使用Ubuntu 10.10

我就是这么做的

Hello.java:

然后我运行以下命令:

dierre@cox:~/Scrivania/provajni$ javac Hello.java

dierre@cox:~/Scrivania/provajni$ javah -jni Hello 
我获得了
Hello.class
Hello.h

你好,h:

生成文件
hellolib.so

但是,当我尝试使用
java Hello
运行它时,出现了以下错误:

Exception in thread "main" java.lang.UnsatisfiedLinkError: no hellolib in java.library.path
 at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1734)
 at java.lang.Runtime.loadLibrary0(Runtime.java:823)
 at java.lang.System.loadLibrary(System.java:1028)
 at Hello.<clinit>(Hello.java:4)
Could not find the main class: Hello.  Program will exit.
没有结果

我知道我在做一些非常愚蠢的事情,但我不知道那是什么。动态库是用-shared选项生成的,不是吗

更新#1

我尝试了
静态{System.load(“/home/dierre/Scrivania/provajni/hellolib.so”);}
以查看这是否有效,但现在:

Exception in thread "main" java.lang.UnsatisfiedLinkError: /home/dierre/Scrivania/provajni/hello.so: /home/dierre/Scrivania/provajni/hello.so: undefined symbol: _ZSt4cout
    at java.lang.ClassLoader$NativeLibrary.load(Native Method)
    at java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1803)
    at java.lang.ClassLoader.loadLibrary(ClassLoader.java:1699)
    at java.lang.Runtime.load0(Runtime.java:770)
    at java.lang.System.load(System.java:1003)
    at Hello.<clinit>(Hello.java:4)
线程“main”java.lang.unsatifiedlinkerror:/home/dierre/Scrivania/provajni/hello.so:/home/dierre/Scrivania/provajni/hello.so中的异常:未定义的符号:_ZSt4cout
位于java.lang.ClassLoader$NativeLibrary.load(本机方法)
位于java.lang.ClassLoader.loadLibrary0(ClassLoader.java:1803)
位于java.lang.ClassLoader.loadLibrary(ClassLoader.java:1699)
位于java.lang.Runtime.load0(Runtime.java:770)
位于java.lang.System.load(System.java:1003)
您好。(Hello.java:4)
更新#2
好的,为了解决更新1问题,我必须使用
g++
,而不是
gcc
。但是仍然无法使用
load
方法。我似乎无法告诉它正确的路径。

< P>这抱怨C++符号不可用。我似乎记得,当我一直使用JNI的时候,在C++库中有问题,我们总是坚持普通的C< 如果更改代码使其成为标准C(并重命名文件):

它起作用了

java -Djava.library.path=`pwd` Hello
Hello World

本机库可以由具有有效名称的loadLibrary加载。例如,libXXXX。因此对于linux系列,您的hellolib.so应该重命名为libhello.so。 顺便说一下,我使用jni开发java,我将分离实现和本机接口(.c或.cpp)

实现头(HelloImpl.h):

HelloImpl.cpp:

#include "HelloImpl.h"
#include  <iostream>

using namespace std;

void sayHello () {
    cout << "Hello World!" << endl;
    return;
}
有一个标记为T的Java_Hello_sayHello。它实际上应该等于您的本机方法名。如果一切都好的话。您可以运行它:

$ java -Djava.library.path=. Hello
Hello World!
最后,我的代码工作了。 这是hello.java

public class hello {
  public native void sayHello(int length) ;
  public static void main (String args[]) {
    String str = "I am a good boy" ;
    hello h = new hello () ;
    h.sayHello (str.length() ) ;
  }
  static {
    System.loadLibrary ( "hello" ) ;
  }
}
您应将其编译为:

$ javac hello.java 
要创建.h文件,应运行以下命令:

$ javah -jni hello
这是
你好.h

JNIEXPORT void JNICALL Java_hello_sayHello
(JNIEnv *, jobject, jint);
这里是hello.c:

#include<stdio.h>
#include<jni.h>
#include "hello.h" 

JNIEXPORT void JNICALL Java_hello_sayHello
  (JNIEnv *env, jobject object, jint len) {
  printf ( "\nLength is %d", len ); }
然后最后运行这个:

$ java -Djava.library.path=. hello

dierre@cox:~/Scrivania/provajni$ldd hello.so linux gate.so.1=>(0x00b46000)libc.so.6=>/lib/libc.so.6(0x0018d000)/lib/ld linux.so.2(0x00b16000)它是gcc而不是g++。但是我仍然不能使用
loadLibrary
,只有
load
如果我在最后一个编译步骤中省略“-static”选项,这对我来说是有效的。如果我没有,我会得到这个错误:/usr/bin/ld:/usr/lib/gcc/x86\u 64-linux-gnu/4.6.1/crtbeginT.o:remocation R\u x86\u 64\u 32对`\uu数据或\u END\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu;用-fPIC重新编译我发现了这个问题的解决方案:它起作用了。谢谢你能解释一下这是什么吗-Djava.library.path=。您好,Djava.library.path=。指定java在编译时查找libXXX.so文件的位置(表示当前目录),编译时它会工作:
gcc-I/usr/local/jdk1.8.091/include/usr/local/jdk1.8.091/include/linux-o libhello.so-shared-fPIC hello.c
@tidy您的命令行对我有用,否则Sandipan的示例很好。
#ifndef _HELLO_IMPL_H
#define _HELLO_IMPL_H

#ifdef __cplusplus
        extern "C" {
#endif

        void sayHello ();

#ifdef __cplusplus
        }
#endif

#endif
#include "HelloImpl.h"
#include  <iostream>

using namespace std;

void sayHello () {
    cout << "Hello World!" << endl;
    return;
}
#include <jni.h>
#include "Hello.h"
#include "HelloImpl.h"

JNIEXPORT void JNICALL Java_Hello_sayHello (JNIEnv *env, jobject obj) {
    sayHello();
    return;
}
$ nm libhello.so |grep say
00000708 T Java_Hello_sayHello
00000784 t _GLOBAL__I_sayHello
00000718 T sayHello
$ java -Djava.library.path=. Hello
Hello World!
public class hello {
  public native void sayHello(int length) ;
  public static void main (String args[]) {
    String str = "I am a good boy" ;
    hello h = new hello () ;
    h.sayHello (str.length() ) ;
  }
  static {
    System.loadLibrary ( "hello" ) ;
  }
}
$ javac hello.java 
$ javah -jni hello
JNIEXPORT void JNICALL Java_hello_sayHello
(JNIEnv *, jobject, jint);
#include<stdio.h>
#include<jni.h>
#include "hello.h" 

JNIEXPORT void JNICALL Java_hello_sayHello
  (JNIEnv *env, jobject object, jint len) {
  printf ( "\nLength is %d", len ); }
$ gcc -I/usr/lib/jvm/java-6-openjdk/include -o libhello.so -shared hello.c
$ java -Djava.library.path=. hello