我正在学习使用JNI,但我遇到了一些麻烦...
我正在使用eclipse进行java和c ++,我正在使用makefile来编译c ++文件。
当我尝试在c ++中使用多个类时,所有问题都开始了。
错误代码:
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)
它说“找不到依赖库”,但hello.dll实际存在于路径“C:\ Users \ Balinator \ workspace \ HelloJNI \ jni \ hello.dll”下。 我试图修改makefile,认为存在问题,但没有成功。我对makefile-s不太满意,但我没有在代码本身中发现问题。
我定义了一个VM变量:
-Djava.library.path=jni
这是来源:
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();
}
}
Employee.java:
public class Employee {
private int age;
public Employee(int age) {
this.age = age;
}
public int getAge() {
return age;
}
}
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
HelloJNI.cpp:
/*
* 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:
/*
* 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:
/*
* 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