Java JNI中dll文件的链接

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

我正在学习使用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.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