在Linux上运行Java调用native.so时出现持久性的不满意链接错误 我试图得到一个小的/示例java应用程序,它使用JNI调用调用本地C++代码,在Linux上运行。

在Linux上运行Java调用native.so时出现持久性的不满意链接错误 我试图得到一个小的/示例java应用程序,它使用JNI调用调用本地C++代码,在Linux上运行。,java,c++,linux,java-native-interface,Java,C++,Linux,Java Native Interface,我使用Eclipse构建、配置环境和运行应用程序 我把“总体”项目分成2个单独的Eclipse项目:1 java项目和1 C++项目,包含本机代码。 Java部分包括: 1:一个“main”类,从中调用一个“adapter”类来加载.so库并调用本机接口/C++方法 2:一个“适配器”类,包含本机方法声明 public class Java_Main_For_So_Kickoff { public static void main(String[] args) { /

我使用Eclipse构建、配置环境和运行应用程序

我把“总体”项目分成2个单独的Eclipse项目:1 java项目和1 C++项目,包含本机代码。

Java部分包括: 1:一个“main”类,从中调用一个“adapter”类来加载.so库并调用本机接口/C++方法 2:一个“适配器”类,包含本机方法声明

public class Java_Main_For_So_Kickoff {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        System.out.println("Hello from Java main!");

        Native_Cpp_Adapter adapter = new Native_Cpp_Adapter();

        adapter.locSetProperty();
        adapter.locLoadLib();

        adapter.sayHello();

        adapter.test_Kickoff_So_For_Print();

    }

}


public class Native_Cpp_Adapter {   
    public native void test_Kickoff_So_For_Print();

    public void locSetProperty() {
        "/home/adminuser/workspace_Unit_Test_Java_Cpp/Unit_Test_Cpp/Debug");
        String libPathProp = System.getProperty("java.library.path");

        System.out.println("lib path set:" + libPathProp);
    }

    public void locLoadLib() {
        System.setProperty("java.library.path", 
        "//home//adminuser//workspace_Unit_Test_Java_Cpp//Unit_Test_Cpp//Debug//");
        String libPathProp = System.getProperty("java.library.path");
        String soLibName = "libUnit_Test_Cpp.so";
        String soLibWithPath = libPathProp.concat(soLibName);

        System.out.println("lib path set for loading:" + libPathProp);
        System.load(soLibWithPath);

        System.out.println("library loaded");
    }

    public void sayHello() {
        System.out.println("Hello from JNI Adapter (Java part)");
    }
}
<> > C++部分由以下部分组成: 1:javah生成的*.h文件,包含本机方法定义 2:A*.CPP文件,包含本机方法

的C++实现 两者都非常初级,只是为了测试JNI环境设置的健全性。在这个问题的原始帖子中添加了这个,省略了那个

.h文件:本机\u Cpp\u适配器.h

     /*
 * Native_Cpp_Adapter.h
 *
 *  Created on: Aug 23, 2017
 *      Author: adminuser
 */

#ifndef SRC_NATIVE_CPP_ADAPTER_H_
#define SRC_NATIVE_CPP_ADAPTER_H_

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

#ifndef _Included_Native_Cpp_Adapter
#define _Included_Native_Cpp_Adapter
#ifdef __cplusplus
extern "C" {
#endif

JNIEXPORT void JNICALL Java_Native_Cpp_Adapter_test_Kickoff_So_For_Print
  (JNIEnv *, jobject);


#ifdef __cplusplus
}
#endif
#endif





#endif /* SRC_NATIVE_CPP_ADAPTER_H_ */
/*
*本机Cpp适配器.h
*
*创建日期:2017年8月23日
*作者:adminuser
*/
#ifndef SRC_NATIVE_CPP_ADAPTER_H_
#定义SRC\u本机\u CPP\u适配器\u H_
/*不要编辑此文件-它是机器生成的*/
#包括
/*类本机\u Cpp\u适配器的标头*/
#ifndef包括本机Cpp适配器
#定义包含的本地Cpp适配器
#ifdef_uucplusplus
外部“C”{
#恩迪夫
JNIEXPORT void JNICALL Java\u本机\u Cpp\u适配器\u测试\u启动\u So\u打印
(JNIEnv*,jobject);
#ifdef_uucplusplus
}
#恩迪夫
#恩迪夫
#endif/*SRC_NATIVE_CPP_适配器_H_*/
.cpp文件:本机\u cpp\u适配器.cpp

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

using namespace std;

JNIEXPORT void JNICALL Java_Native_Cpp_Adapter_test_Kickoff_So_For_Print
 (JNIEnv *, jobject)
{
    cout << "Correct kickoff of Native JNI method nr. 1";
    return;
}
#包括“jni.h”
#包括
使用名称空间std;
JNIEXPORT void JNICALL Java\u本机\u Cpp\u适配器\u测试\u启动\u So\u打印
(JNIEnv*,jobject)
{

cout您的本机方法的名称似乎无效。请确保正确转义\u\u用于分隔本机方法中的包。您需要遵循命名约定:

如果方法名中有“1”,则需要在本机代码中用“1”对其进行转义

例如,对于Java中的方法:

public static native void display_Message();
你需要:

JNIEXPORT void JNICALL Java_recipeNo001_HelloWorld_display_1Message
  (JNIEnv *, jclass);
注意“\u 1”在“显示”和“消息”之间

来源取自(并稍作修改)此处:

更新

您应注意的地方:

  • 如果其他所有操作都失败,请确保在运行Eclipse之前设置
    LD\u LIBRARY\u PATH
    。这将让您了解Eclipse是玩得很糟糕还是其他东西坏了
  • 确保在启动代码时使用“-D”传递
    java.library.path
    。您可以在调试配置中将其设置为JVM参数
  • 有时,这可能很棘手,结果可能是您的库根本不包含符号。您可以使用
    nm

    nm libSomeLibFile.so
    
  • 您还可以在Eclipse中设置项目的
    属性
    配置中的本机代码位置

  • 更新。我已经稍微简化了您的代码,以便更容易地检查错误。我建议您从类名中删除“\u1”,因为它们在本机代码中再次混淆

    请看这里:

    public class Main {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            System.out.println("Hello from Java main!");
            NativeCppAdapter adapter = new NativeCppAdapter();
            adapter.locLoadLib();
            adapter.testKickoffSoForPrint();
        }
    }
    
    本机适配器类

    public class NativeCppAdapter {
        public native void testKickoffSoForPrint();
    
        public void locLoadLib() {
            String soLibName = "/tmp/libNativeCppAdapter.so";
            System.load(soLibName);
        }
    }
    
    C++代码(注意C导出-它对函数名有影响!)

    再多说几句

    如果编译代码时没有

    #ifdef __cplusplus
    extern "C" {
    #endif
    ...
    #ifdef __cplusplus
    }
    #endif
    
    库中的符号将不正确(不是JVM所期望的)


    另一件事是。如果您使用“loadLibrary”,您必须确保文件名的格式为:libSomeName。因此,您可以通过
    System.loadLibrary(“SomeName”)加载文件
    -您必须确保
    java.library.path
    LD_library_path
    指向文件。另一方面,如果您使用
    System.load
    ,则不必对名称做任何假设。只需确保提供文件的完整路径。例如:
    /tmp/someFileWithMyLib
    用于在本机方法中分隔包。您需要遵循命名约定:

    如果方法名中有“1”,则需要在本机代码中用“1”对其进行转义

    例如,对于Java中的方法:

    public static native void display_Message();
    
    你需要:

    JNIEXPORT void JNICALL Java_recipeNo001_HelloWorld_display_1Message
      (JNIEnv *, jclass);
    
    注意“\u 1”在“显示”和“消息”之间

    来源取自(并稍作修改)此处:

    更新

    您应注意的地方:

  • 如果其他所有操作都失败,请确保在运行Eclipse之前设置
    LD\u LIBRARY\u PATH
    。这将让您了解Eclipse是玩得很糟糕还是其他东西坏了
  • 确保在启动代码时使用“-D”传递
    java.library.path
    。您可以在调试配置中将其设置为JVM参数
  • 有时,这可能很棘手,结果可能是您的库根本不包含符号。您可以使用
    nm

    nm libSomeLibFile.so
    
  • 您还可以在Eclipse中设置项目的
    属性
    配置中的本机代码位置

  • 更新。我已经稍微简化了您的代码,以便更容易地检查错误。我建议您从类名中删除“\u1”,因为它们在本机代码中再次混淆

    请看这里:

    public class Main {
    
        public static void main(String[] args) {
            // TODO Auto-generated method stub
            System.out.println("Hello from Java main!");
            NativeCppAdapter adapter = new NativeCppAdapter();
            adapter.locLoadLib();
            adapter.testKickoffSoForPrint();
        }
    }
    
    本机适配器类

    public class NativeCppAdapter {
        public native void testKickoffSoForPrint();
    
        public void locLoadLib() {
            String soLibName = "/tmp/libNativeCppAdapter.so";
            System.load(soLibName);
        }
    }
    
    C++代码(注意C导出-它对函数名有影响!)

    再多说几句

    如果编译代码时没有

    #ifdef __cplusplus
    extern "C" {
    #endif
    ...
    #ifdef __cplusplus
    }
    #endif
    
    库中的符号将不正确(不是JVM所期望的)

    另一件事是。如果您使用“loadLibrary”,您必须确保文件名的格式为:libSomeName。因此,您通过
    System.loadLibrary(“SomeName”);
    -加载文件,并且您必须确保
    java.library.path
    或<