java - undefined symbol : JNI_CreateJavaVM in Linux

标签 java c++ linux java-native-interface shared-libraries

我有 2 个项目。两者都是在 Ubuntu 64 位上的 Netbeans IDE 中创建的。

首先,我的.so项目实现了从其C++代码调用Java函数。 我的控制台应用程序尝试调用 .so 文件中的函数。

编译运行时出现如下错误:

/home/online0227/desktop/jvm run/dist/Debug/GNU-Linux-x86/jvm_run: symbol lookup error: ./libjvm_dll.so: undefined symbol: JNI_CreateJavaVM

如何解决这个问题?

我包含了 .so 项目的包含路径。以下是我编译 .so 项目时,netbeans 在其构建输出中显示的内容:

g++    -c -g -I/home/online0227/jdk1.7.0_25_x64/include/linux -I/home/online0227/jdk1.7.0_25_x64/include -fPIC  -MMD -MP -MF build/Debug/GNU-Linux-x86/_ext/1117207477/testlib.o.d -o build/Debug/GNU-Linux-x86/_ext/1117207477/testlib.o /home/online0227/desktop/jvm\ dll/testlib.cpp

g++     -o dist/Debug/GNU-Linux-x86/libjvm_dll.so build/Debug/GNU-Linux-x86/_ext/1117207477/testlib.o  -shared -fPIC

这个 .so 编译得很好并生成 .so 文件。

这是我编译主控制台应用程序时 Netbeans 显示的内容:

g++    -c -g -I/home/online0227/jdk1.7.0_25_x64/include/linux -I/home/online0227/jdk1.7.0_25_x64/include -MMD -MP -MF build/Debug/GNU-Linux-x86/main.o.d -o build/Debug/GNU-Linux-x86/main.o main.cpp

g++     -o dist/Debug/GNU-Linux-x86/jvm_run build/Debug/GNU-Linux-x86/main.o -L/home/online0227/jdk1.7.0_25_x64/jre/lib/amd64/server -ldl -ljvm

它的编译和运行也非常好。

但问题是,当我尝试创建 Java 虚拟机“JNI_CreateJavaVM(&jvm, reinterpret_cast(&env), &vm_args)”时收到错误消息。

以下是我的所有源代码,

对于.so项目的testLib.h:

#ifndef TESTLIB_H
#define TESTLIB_H

class TestLib : public TestVir
{
 public:
     void init();
     int createJVM();
};

#endif

对于.so项目的testVir.h:

#ifndef TESTVIR H
#define TESTVIR_H

class TestVir
{
public:
  virtual void init()=0;
  virtual int createJVM()=0;
};

#endif

对于.so项目的testLib.cpp:

#include <iostream>
#include <jni.h>
#include <cassert>
#include "testVir.h"
#include "testLib.h"

using namespace std;
void TestLib::init()
{
   cout<<"TestLib::init: Hello World!! "<<endl ;
}

int TestLib::createJVM() {
  const int kNumOptions = 3;
  JavaVMOption options[kNumOptions] = {
    { const_cast<char*>("-Xmx128m"), NULL },
    { const_cast<char*>("-verbose:gc"), NULL },
    { const_cast<char*>("-Djava.class.path=."), NULL }
  };

  JavaVMInitArgs vm_args;
  vm_args.version = JNI_VERSION_1_6;
  vm_args.options = options;
  vm_args.nOptions = sizeof(options) / sizeof(JavaVMOption);
  assert(vm_args.nOptions == kNumOptions);

  JNIEnv* env = NULL;
  JavaVM* jvm = NULL;
  int res = JNI_CreateJavaVM(&jvm, reinterpret_cast<void**>(&env), &vm_args);
  if (res != JNI_OK) {
    std::cerr << "FAILED: JNI_CreateJavaVM " << res << std::endl;
    return -1;
  }

      jclass cls;
    jmethodID mid;
    jobject obj;
    int staticresult = 0;
    int result = 0;
    long status;

    if (status != JNI_ERR) {
        cls = env->FindClass("PWNJavaGUI");

        if (cls != 0) {
            mid = env->GetStaticMethodID(cls, "main", "([Ljava/lang/String;)V");

            if (mid != 0) {
                env->CallStaticVoidMethod(cls, mid);

                mid = env->GetStaticMethodID(cls, "isPass", "()Z"); // public static int returnCheckBox()

                if (mid != 0) {

                    while (env->CallStaticBooleanMethod(cls, mid) == 0) {
                        // Do nothing but just wait until the user select game start button //
                    }

                } else {
                   // Log("Error : env->GetStaticMethodID for isLoop");
                    return 0;
                }

            } else {
              //  Log("Error : env->GetStaticMethodID for main");
                return 0;
            }

        } else {
          //  Log("Error : env->FindClass");
            return 0;
        }
    }

    return 1;

  jvm->DestroyJavaVM();

  return 0;
}

//Define functions with C symbols (create/destroy TestLib instance).
extern "C" TestLib* create()
{
    return new TestLib;
}
extern "C" void destroy(TestLib* Tl)
{
   delete Tl ;
}

最后,这是我的主控制台应用程序,ma​​in.cpp:

#include<iostream>
#include <stdio.h>
#include<dlfcn.h>
#include "testVir.h"

using namespace std;

int main()
{
    void *handle;
    handle = dlopen("./libjvm_dll.so", RTLD_LAZY);
    if (!handle)
    {
           printf("The error is %s", dlerror());
    }

    typedef TestVir* create_t();
    typedef void destroy_t(TestVir*);

    create_t* creat=(create_t*)dlsym(handle,"create");
    destroy_t* destroy=(destroy_t*)dlsym(handle,"destroy");
    if (!creat)
    {
           cout<<"The error is %s"<<dlerror();
    }
    if (!destroy)
    {
           cout<<"The error is %s"<<dlerror();
    }
    TestVir* tst = creat();
    tst->init();
    tst->createJVM();

    destroy(tst);
    return 0 ;
}

最佳答案

您的 libjvm_dll.so 使用 libjvm.so 中的符号,因此在构建它时应该将其链接到它。

g++     -o dist/Debug/GNU-Linux-x86/libjvm_dll.so build/Debug/GNU-Linux-x86/_ext/1117207477/testlib.o  -shared -fPIC \
-L/home/online0227/jdk1.7.0_25_x64/jre/lib/amd64/server -ljvm

整个构建过程:

# Build libjvm_dll.so
g++ -o libjvm_dll.so -I $JAVA_HOME/include testLib.cpp -shared -fPIC -L $JAVA_HOME/jre/lib/amd64/server -ljvm
# Build main executable 
g++ -o jvm_run main.cpp -ldl
# Run
LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/amd64/server ./jvm_run

关于java - undefined symbol : JNI_CreateJavaVM in Linux,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18459109/

相关文章:

java - 有条件地实现一个接口(interface)

java - 如何调用带参数的私有(private)方法

c++ - 将我的 DDiscMaster2Events 连接/链接到什么以进行驱动器更改事件。微软 COM 对象

linux - 如何制作假的 USB 设备或使设备显示为另一台设备

linux - 使用 getopts 传递给函数时,命令行参数不起作用

linux - FTDI 双 UART/FIFO : conflict with ftdi_sio

java - 对 Java 集合进行排序和分组

java - 如何在android中显示警报时检测搜索按钮

c++ - 使用xcode的c++应用程序中文件的相对路径

c++ - 如何在循环外重新输入变量