JNI java.lang.UnsatisfiedLinkError,无法链接方法

时间:2016-12-07 08:10:58

标签: java c++ java-native-interface

我看过很多关于UnsatisfiedLinkError的问题,我知道我的问题是什么。我得到了

线程中的异常" main" java.lang.UnsatisfiedLinkError:Test.initCamera(Ljava / lang / String; Ljava / lang / String; Ljava / lang / String; Ljava / lang / String;)J

这意味着已加载dll但无法找到该方法。但是,我已经检查了我的源代码和java代码。方法名称和参数都可以。我不知道我的代码有什么问题。

这是我的代码。

爪哇:

public class Test {
public native long initCamera(String ip,String port,String username,String pwd); 
public native int snapPic(long id,String savePath,int no);
static{
    System.loadLibrary("dhconfigsdk");
    System.loadLibrary("dhnetsdk");
    System.loadLibrary("dhplay");
    System.loadLibrary("CameraCatcher");
}
public static void main(String[] args) {
    // TODO Auto-generated method stub
    Test tNative = new Test();
    String ip="192.108.1.108";
    String port="37777";
    String username="admin";
    String pwd="123456";
    long cameraId=tNative.initCamera(ip,port,username,pwd);
    System.out.println(cameraId);
    String savePath="D:/";
    int number=tNative.snapPic(cameraId,savePath,0);
}
}

C ++:

JNIEXPORT jlong JNICALL Java_CameraCatcher_initCamera
(JNIEnv * env, jclass c, jstring arg_ip, jstring arg_port, jstring arg_username, jstring arg_pwd)
{
    ......
    return lLogin;
}


JNIEXPORT jint JNICALL Java_CameraCatcher_snapPic
(JNIEnv * env, jclass c, jlong arg_id, jstring arg_path, jint arg_no)
{
    .....
    return 12;
}

这真让我疯狂。

更新1: 感谢大家的回复。正如@Mr Tarik所示,我改变了我的代码。

爪哇:

public class CameraCatcher {
    static{
         System.loadLibrary("CameraCatcher");
    }
    public native long initCamera(String ip,String port,String username,String pwd);
    public native int snapPic(long id,String savePath,int no);
    public static void main(String[] args)
    {
        CameraCatcher tNative = new CameraCatcher();
        String ip="192.108.1.108";
        String port="37777";
        String username="admin";
        String pwd="123456";
        long cameraId=tNative.initCamera(ip,port,username,pwd);
        System.out.println(cameraId);
        String savePath="D:/project/j2ee/Example/result";
        int number=tNative.snapPic(cameraId,savePath,0);
    }
}

然后我使用javah生成头文件:

#include <jni.h>

#ifndef _Included_CameraCatcher
#define _Included_CameraCatcher
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     CameraCatcher
 * Method:    initCamera
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_CameraCatcher_initCamera
  (JNIEnv *, jobject, jstring, jstring, jstring, jstring);

/*
 * Class:     CameraCatcher
 * Method:    snapPic
 * Signature: (JLjava/lang/String;I)I
 */
JNIEXPORT jint JNICALL Java_CameraCatcher_snapPic
  (JNIEnv *, jobject, jlong, jstring, jint);

#ifdef __cplusplus
}
#endif
#endif

C ++代码:

JNIEXPORT jlong JNICALL Java_CameraCatcher_initCamera
(JNIEnv * env, jobject c, jstring arg_ip, jstring arg_port, jstring arg_username, jstring arg_pwd)
{
    return 1;
}
JNIEXPORT jint JNICALL Java_CameraCatcher_snapPic
(JNIEnv * env, jobject c, jlong arg_id, jstring arg_path, jint arg_no)
{
    return 2;
}

我编译此代码并获取新的dll。 但是它仍然有如前的错误.......

更新2: 是的。它有效。我不知道为什么函数定义代码在我的.cpp文件中发生了变化。我刚刚将jclass更改为jobject,因为EJP昨天告诉我这个问题。也许它从昨天开始就被改变了,我没有观察到。这是我的粗心大意。再次感谢大家。

问题正是EJP所说的。我使用静态函数生成了文件,但是以非静态方式工作。另一个问题是我在使用类Test时生成了CameraCatcher类。

3 个答案:

答案 0 :(得分:1)

我测试了你的代码。你需要在c ++中编辑函数名,你需要这样的东西

    #include "test.h"
    #include <jni.h>

JNIEXPORT jlong JNICALL Java_CameraCatcher_Test_initCamera
  (JNIEnv *env, jobject  obj, jstring ip, jstring port, jstring username, jstring pwd){

    return 1.0;
}
JNIEXPORT jint JNICALL Java_CameraCatcher_Test_snapPic
  (JNIEnv *env, jobject obj, jlong id, jstring savePath, jint no){
    return 5;
}

不要忘记您的类Test的名称,以便将其添加到Java_CameraCatcher_Test_snapPic

编辑1: 这就是我在标题中所拥有的:

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class CameraCatcher */

#ifndef _Included_CameraCatcher
#define _Included_CameraCatcher
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     CameraCatcher
 * Method:    initCamera
 * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
 */
JNIEXPORT jlong JNICALL Java_CameraCatcher_initCamera
  (JNIEnv *, jobject, jstring, jstring, jstring, jstring);

/*
 * Class:     CameraCatcher
 * Method:    snapPic
 * Signature: (JLjava/lang/String;I)I
 */
JNIEXPORT jint JNICALL Java_CameraCatcher_snapPic
  (JNIEnv *, jobject, jlong, jstring, jint);

#ifdef __cplusplus
}
#endif
#endif

C ++:

#include "cameracatcher.h"
#include <jni.h>
#include <stdio.h>
#include <iostream>
#include <unistd.h>
JNIEXPORT jlong JNICALL Java_CameraCatcher_initCamera
  (JNIEnv *env, jobject  obj, jstring ip, jstring port, jstring username, jstring pwd){

    return 1.0;
}
JNIEXPORT jint JNICALL Java_CameraCatcher_snapPic
  (JNIEnv *env, jobject obj, jlong id, jstring savePath, jint no){
    return 5.5;
}

爪哇:

public class CameraCatcher {

    public native long initCamera(String ip, String port, String username, String pwd);

    public native int snapPic(long id, String savePath, int no);

    static {
        System.load("/home/tarik/NetBeansProjects/Testc++/dist/test.so");
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        CameraCatcher tNative = new CameraCatcher();
        String ip = "192.108.1.108";
        String port = "37777";
        String username = "admin";
        String pwd = "123456";
        long cameraId = tNative.initCamera(ip, port, username, pwd);
        System.out.println(cameraId);
        String savePath = "D:/";
        int number = tNative.snapPic(cameraId, savePath, 0);
        System.out.println(number);
    }
}

一切正常。

答案 1 :(得分:1)

包含本机方法的Java类名为测试。但是您为名为 CameraCatcher 的类生成了C ++标头(在默认包中)。

您可以重命名Java类,也可以将C ++函数更改为Java_Test_initCameraJava_Test_snapPic。不要忘记将这些函数定义为extern "C"(我们通常在头文件中执行此操作,由 javah 生成)。

答案 2 :(得分:0)

JNI方法名称需要遵循惯例。 可以使用JDK附带的内置工具生成方法名称。

请参阅此链接了解更多详情。 https://www3.ntu.edu.sg/home/ehchua/programming/java/JavaNativeInterface.html