Java JNI中dll文件的链接
我正在学习使用JNI,我遇到了一些麻烦 我使用java和C++两个Eclipse,我使用MaFag文件编译C++文件。 <> >所有问题都是在我尝试使用C++中的多个类时开始的。 错误代码:Java JNI中dll文件的链接,java,c++,makefile,java-native-interface,Java,C++,Makefile,Java Native Interface,我正在学习使用JNI,我遇到了一些麻烦 我使用java和C++两个Eclipse,我使用MaFag文件编译C++文件。 >所有问题都是在我尝试使用C++中的多个类时开始的。 错误代码: Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\Balinator\workspace\HelloJNI\jni\hello.dll: Can't find dependent libraries at java.l
Exception in thread "main" java.lang.UnsatisfiedLinkError: C:\Users\Balinator\workspace\HelloJNI\jni\hello.dll: Can't find dependent libraries
at java.lang.ClassLoader$NativeLibrary.load(Native Method)
at java.lang.ClassLoader.loadLibrary0(Unknown Source)
at java.lang.ClassLoader.loadLibrary(Unknown Source)
at java.lang.Runtime.loadLibrary0(Unknown Source)
at java.lang.System.loadLibrary(Unknown Source)
at HelloJNI.<clinit>(HelloJNI.java:5)
资料来源如下:
Java代码:
HelloJNI.java:
public class HelloJNI {
static {
// hello.dll on Windows or libhello.so on Linux
System.loadLibrary("hello");
}
private native int sayHello(int num);
public native int intMethod(int num);
public native boolean booleanMethod(boolean booleanb);
public native String stringMethod(String s);
public native int intArrayMethod(int[] array);
private void runSimple() {
System.out.println("intMethod: " + intMethod(5));
System.out.println("booleanMethod: " + booleanMethod(true));
System.out.println("stringMethod: " + stringMethod("str"));
System.out.println("intArrayMethod: " + intArrayMethod(new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }));
}
public native int getAgeC(Employee emp);
public native Employee createWithAge(int age);
private void runComplex() {
Employee emp = new Employee(32);
System.out.println("Pass employee to C and get age back: " + getAgeC(emp));
Employee emp2 = createWithAge(23);
System.out.println("Get employee object from C: " + emp2.getAge());
}
public native void speedTest(int num);
private void speedTest() {
long time;
Employee e;
int num = 1000000;
System.out.println("Java call!");
time = System.currentTimeMillis();
e = new Employee(20);
for (int i = 0; i < num; ++i) {
e.getAge();
}
System.out.println("Time = " + (System.currentTimeMillis() - time));
System.out.println("Mixed call!");
time = System.currentTimeMillis();
e = createWithAge(20);
for (int i = 0; i < num; ++i) {
getAgeC(e);
}
System.out.println("Time = " + (System.currentTimeMillis() - time));
System.out.println("C++ call!");
time = System.currentTimeMillis();
speedTest(num);
System.out.println("Time = " + (System.currentTimeMillis() - time));
}
public static void main(String[] args) {
// invoke the native method
HelloJNI h = new HelloJNI();
for (int i = 0; i < 10; ++i) {
System.out.println("From java = " + h.sayHello(i));
}
h.runSimple();
h.runComplex();
h.speedTest();
}
}
c++代码:
HelloJNI.h:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class HelloJNI */
#ifndef _Included_HelloJNI
#define _Included_HelloJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: HelloJNI
* Method: sayHello
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_HelloJNI_sayHello
(JNIEnv *, jobject, jint);
/*
* Class: HelloJNI
* Method: intMethod
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_HelloJNI_intMethod
(JNIEnv *, jobject, jint);
/*
* Class: HelloJNI
* Method: booleanMethod
* Signature: (Z)Z
*/
JNIEXPORT jboolean JNICALL Java_HelloJNI_booleanMethod
(JNIEnv *, jobject, jboolean);
/*
* Class: HelloJNI
* Method: stringMethod
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_HelloJNI_stringMethod
(JNIEnv *, jobject, jstring);
/*
* Class: HelloJNI
* Method: intArrayMethod
* Signature: ([I)I
*/
JNIEXPORT jint JNICALL Java_HelloJNI_intArrayMethod
(JNIEnv *, jobject, jintArray);
/*
* Class: HelloJNI
* Method: getAgeC
* Signature: (LEmployee;)I
*/
JNIEXPORT jint JNICALL Java_HelloJNI_getAgeC
(JNIEnv *, jobject, jobject);
/*
* Class: HelloJNI
* Method: createWithAge
* Signature: (I)LEmployee;
*/
JNIEXPORT jobject JNICALL Java_HelloJNI_createWithAge
(JNIEnv *, jobject, jint);
/*
* Class: HelloJNI
* Method: speedTest
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_HelloJNI_speedTest
(JNIEnv *, jobject, jint);
#ifdef __cplusplus
}
#endif
#endif
Employee.cpp:
/*
* Employee.cpp
*
* Created on: 2017. aug. 27.
* Author: Balinator
*/
#include "Employee.h"
Employee::Employee(int age):age(age) {}
Employee::~Employee() {}
int Employee::getAge(){
return age;
}
生成文件:
# Define a variable for classpath
CLASS_PATH = ../bin
# Define a virtual path for .class in the bin directory
vpath %.class $(CLASS_PATH)
cleanbuild: clean all
all : hello.dll
# $@ matches the target, $^ matches all dependancys
hello.dll : HelloJNI.o Employee.o
g++ -m64 -fpic -shared -o $@ $^
# $@ matches the target, $< matches the first dependancy
HelloJNI.o : HelloJNI.cpp HelloJNI.h
g++ -m64 -I"C:\Program Files\Java\jdk1.8.0_121\include" -c $< -o $@
# $* matches the target filename without the extension
HelloJNI.h : HelloJNI.class
javah -classpath $(CLASS_PATH) $*
Employee.o: Employee.cpp Employee.h
g++ -m64 -c $< -o $@
clean :
rm HelloJNI.h HelloJNI.o hello.dll Employee.o
#为类路径定义一个变量
类路径=../bin
#在bin目录中为.class定义虚拟路径
vpath%.class$(类路径)
cleanbuild:清除所有
全部:hello.dll
#$@匹配目标,$^匹配所有依赖项
hello.dll:HelloJNI.o Employee.o
g++-m64-fpic-shared-o$@$^
#$@匹配目标,$<匹配第一个依赖项
HelloJNI.o:HelloJNI.cpp HelloJNI.h
g++-m64-I“C:\ProgramFiles\Java\jdk1.8.0\U 121\include“-C$<-o$@
#$*匹配不带扩展名的目标文件名
HelloJNI.h:HelloJNI.class
javah-classpath$(类路径)$*
Employee.o:Employee.cpp Employee.h
g++-m64-c$<-o$@
清洁:
rm HelloJNI.h HelloJNI.o hello.dll Employee.o
您看过了吗?我也找了很多这样的主题,但我找不到一个能解决我问题的方法……我想,你的hello.dll依赖于一些dll,它们既不在%SystemRoot%\system32
中(对不起,我不知道Windows在amd64上的系统范围dll存储在哪里),也不在java.library.path
中。你必须找到答案。我认为违法者是LISSTDC + +从事实中出来的,你使用G+ +,你实际上编译C++源。你可能想试试<代码> G++-M64 -FPIC-共享-O$@ $^ -静态LBGCC -静态LBSTDC + +<代码>。你看过了吗?我也找了很多这样的主题,但我找不到一个能解决我问题的方法……我想,你的hello.dll依赖于一些dll,它们既不在%SystemRoot%\system32
中(对不起,我不知道Windows在amd64上的系统范围dll存储在哪里),也不在java.library.path
中。你必须找到答案。我认为违法者是LISSTDC + +从事实中出来的,你使用G++,你实际上编译C++源。你可能想试试<代码> G++-M64 -FPIC-共享-O$@ $^ -静态LBGCC静态静态LBSTDC ++<代码>。
/*
* HelloJNI.cpp
*
* Created on: 2017. aug. 26.
* Author: Balinator
*/
#include <jni.h>
#include <cstdio>
#include <string.h>
#include "HelloJNI.h"
#include "Employee.h"
JNIEXPORT jint JNICALL Java_HelloJNI_sayHello(JNIEnv *env, jobject thisObj,
jint num) {
printf("Hello World! %d\n", num);
return num;
}
JNIEXPORT jint JNICALL Java_HelloJNI_intMethod(JNIEnv *env, jobject obj,
jint num) {
return num * num;
}
JNIEXPORT jboolean JNICALL Java_HelloJNI_booleanMethod(JNIEnv *env, jobject obj,
jboolean boolean) {
return !boolean;
}
JNIEXPORT jstring JNICALL Java_HelloJNI_stringMethod(JNIEnv *env, jobject obj,
jstring string) {
const char *str = env->GetStringUTFChars(string, 0);
char cap[128];
strcpy(cap, str);
env->ReleaseStringUTFChars(string, str);
return env->NewStringUTF(strupr(cap));
}
JNIEXPORT jint JNICALL Java_HelloJNI_intArrayMethod(JNIEnv *env, jobject obj,
jintArray array) {
int i, sum = 0;
jsize len = env->GetArrayLength(array);
jint *body = env->GetIntArrayElements(array, 0);
for (i = 0; i < len; i++) {
sum += body[i];
}
env->ReleaseIntArrayElements(array, body, 0);
return sum;
}
JNIEXPORT jint JNICALL Java_HelloJNI_getAgeC(JNIEnv *env, jobject callingObject,
jobject employeeObject) {
jclass employeeClass = env->GetObjectClass(employeeObject);
jmethodID midGetAge = env->GetMethodID(employeeClass, "getAge", "()I");
int age = env->CallIntMethod(employeeObject, midGetAge);
return age;
}
JNIEXPORT jobject JNICALL Java_HelloJNI_createWithAge(JNIEnv *env,
jobject callingObject, jint age) {
jclass employeeClass = env->FindClass("LEmployee;");
jmethodID midConstructor = env->GetMethodID(employeeClass, "<init>",
"(I)V");
jobject employeeObject = env->NewObject(employeeClass, midConstructor, age);
return employeeObject;
}
JNIEXPORT void JNICALL Java_HelloJNI_SpeedTest(JNIEnv *env,
jobject callingObject, jint num) {
Employee e(20);
for(int i = 0; i < num; ++i){
e.getAge();
}
}
/*
* Employee.h
*
* Created on: 2017. aug. 27.
* Author: Balinator
*/
#ifndef JNI_EMPLOYEE_H_
#define JNI_EMPLOYEE_H_
class Employee {
private:
int age;
public:
Employee(int age);
virtual ~Employee();
int getAge();
};
#endif /* JNI_EMPLOYEE_H_ */
/*
* Employee.cpp
*
* Created on: 2017. aug. 27.
* Author: Balinator
*/
#include "Employee.h"
Employee::Employee(int age):age(age) {}
Employee::~Employee() {}
int Employee::getAge(){
return age;
}
# Define a variable for classpath
CLASS_PATH = ../bin
# Define a virtual path for .class in the bin directory
vpath %.class $(CLASS_PATH)
cleanbuild: clean all
all : hello.dll
# $@ matches the target, $^ matches all dependancys
hello.dll : HelloJNI.o Employee.o
g++ -m64 -fpic -shared -o $@ $^
# $@ matches the target, $< matches the first dependancy
HelloJNI.o : HelloJNI.cpp HelloJNI.h
g++ -m64 -I"C:\Program Files\Java\jdk1.8.0_121\include" -c $< -o $@
# $* matches the target filename without the extension
HelloJNI.h : HelloJNI.class
javah -classpath $(CLASS_PATH) $*
Employee.o: Employee.cpp Employee.h
g++ -m64 -c $< -o $@
clean :
rm HelloJNI.h HelloJNI.o hello.dll Employee.o