什么是libJvm.so,什么时候构建?

时间:2018-02-01 09:52:48

标签: java c++ jvm java-native-interface shared-libraries

我有点惊讶,我必须发布一个看起来相当微不足道且易于查找的问题....但显然不是。

因为它看起来我的jni.hlibJvm.so库不同步(或者我怀疑),这显示尝试将我的Java应用程序作为库加载到Linux上的C ++环境中(JNI_CreateJVM()以及所有这些),我想知道哪个可能是罪魁祸首。 jni.h只是标准的,包含所有正常模块.... libJvm.so然而......我看不出内容是什么......我甚至不知道它到底是什么如何/在何处建造。

有人可以给我解释/回答这个问题吗?

P.S。问题与库路径和相关问题无关......可以找到libJvm.so。只要我没有完全知道我正在使用的所有组件,就很难理解出了什么问题....

下面是一个更新,关注我的问题的反应中的评论(这是一个非常长的更新,因为我认为包含我正在使用的代码可能很有见地)......

我正在使用的代码(并遇到问题),在代码之后我还说了一些关于环境/设置和情况......:

#include <jni.h>
#include "jvm.h"
#include <iostream>
#include <stdlib.h>
#include <dlfcn.h>

using namespace std;

//Create type for pointer to the JNI_CreateJavaVM function
typedef jint (*CreateJvmFuncPtr) (JavaVM**, void**, JavaVMInitArgs*); 

//New method returns pointer to the JNI_CreateJavaVM function
CreateJvmFuncPtr findCreateJvm() { 
CreateJvmFuncPtr createJvm = NULL;

void* jvmLib = dlopen("/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.71.x86_64/jre/lib/amd64/server/libjvm.so", RTLD_LAZY); //Get handle to jvm shared library
char* error = dlerror(); //Check for errors on dlopen

if(jvmLib == NULL || error != NULL) {
    printf("FailedToLoadJVM\n");
}

//Load pointer to the function within the shared library
createJvm = (CreateJvmFuncPtr) dlsym(jvmLib, "JNI_CreateJavaVM");

error = dlerror();
if(error != NULL) {
    printf("Success\n");
}

return createJvm;

}

int main() {

// load and initialize JVM and JNI interface, in a test setting where JVM is "passive"
// (called/loaded as .dll) and the JNI env is not available yet from a Java/JVM call
// (which would be the caste in the normal setup/configuration).
//int jniLoadJvmAsDll()
//{
   JavaVM *jvm;                      // Pointer to the JVM (Java Virtual Machine)
   JNIEnv *env;                      // Pointer to native interface
       //======== prepare loading of Java VM: assign init arguments for JVM init =========
   JavaVMInitArgs vm_args;                        // Initialization arguments
//       JavaVMOption* vmOptions = new JavaVMOption[1];   // JVM invocation options
   JavaVMOption vmOptions[4];

                                                        // (=> comparable to lib path for System.load(libPath/libName)

   vmOptions[0].optionString = "-Djava.compiler=NONE";           /* disable JIT */
   vmOptions[1].optionString = "-Djava.class.path=/home/adminuser/workspace_Unit_Test_Java_Cpp/Unit_Test_Jni_Java/bin"; // which Java class to load
   vmOptions[2].optionString = "-Djava.library.path=/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.71.x86_64/jre/lib/amd64/;/usr/lib/jvm/java-1.7.0-openjdk-1.7.0.71.x86_64/jre/lib/amd64/server";
   vmOptions[3].optionString = "-verbose:jni";                   /* print JNI-related messages */
   vm_args.version = JNI_VERSION_1_6;             // minimum Java version
   vm_args.nOptions = 1;                          // number of options
   vm_args.options = vmOptions;
   vm_args.ignoreUnrecognized = false;     // invalid options make the JVM init fail

       //=============== load and initialize Java VM and JNI interface =============
   // old code: jint retCrJvm = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);  // YES !!
   //New code:
   CreateJvmFuncPtr createJVM = findCreateJvm();
   printf("findCreateJVM() returned 0x%x\n", createJVM);

   jint retCrJvm = createJVM(&jvm, (void**)&env, &vm_args);
   //End new code
   delete vmOptions;    // we then no longer need the initialization options.
   if (retCrJvm != JNI_OK) {
          // TO DO: error processing...
         cin.get();
         exit(EXIT_FAILURE);
   }

       //====================handle multithread situatiation ========================
   JavaVM * curVM = NULL;           // JVM in current thread, should contain loaded VM
                                    // otherwise we're not in the main thread
   JNIEnv *curEnv;
   int jvmLoadFailed = 1;

   // handle situation that we're not in the main thread (current thread isnt't main thread)
   if (jvm == NULL) {
       env->GetJavaVM( &curVM ); // JVM should contain current/main thread JVM, otherwise
                                 // we're not in the main thread

       int vmStat = curVM->GetEnv((void **)&curEnv, JNI_VERSION_1_6);
       if (vmStat == JNI_EDETACHED)  //We are on a different thread, attach
           curVM->AttachCurrentThread((void **) &curVM, NULL);
       if( curVM == NULL )
           return jvmLoadFailed;  //Can't attach to java, bail out
   }

      //=============== Display JVM version =======================================
   cout << "JVM load (as .so/.dll) succeeded: Version ";
   jint ver = env->GetVersion();
   std::cout << ((ver>>16)&0x0f) << "."<<(ver&0x0f) << endl;

   // TO DO: add the code that will use JVM <============  (see next steps)

   // insert the JNITools separate methods here.... for each separate graphical structure
   // initially a test class is inserted.....
   jclass clsTestPrint = env->FindClass("TestPrint");  // try to find the class
   if(clsTestPrint == NULL) {
       cerr << "ERROR: class not found !";
   }
   jmethodID ctor = env->GetMethodID(clsTestPrint, "<init>", "()V");  // find an object constructor for this class
   if(ctor == NULL) {
       cerr << "ERROR: constructor not found !" << endl;
   }
   else {
       cout << "Object succesfully constructed !"<<endl;
       jobject prtObj = env->NewObject(clsTestPrint, ctor); // invoke the object constructor: create print object
       if (prtObj) {
            jmethodID show = env->GetMethodID(clsTestPrint, "showId", "()V");
            if(show == NULL)
                cerr << "No showId method !!" << endl;
            else env->CallVoidMethod(prtObj, show);
       }
   }


   jvm->DestroyJavaVM();
   cin.get();
   return 0;

//}

}

其中“dlopen”和“dlsym”当然会替换你在Windows上使用的“loadLibrary()”和“getProcaddress()”调用来加载.dll并获取相应JNI过程的句柄。但是我在Linux上这样做,因此是“等效翻译”....

“多线程”装饰在这里并不真正相关....添加它以备将来用途。

经过一些实验后,我成功地配置了构建设置,以便找到libjvm.so,并在其中找到API JNI方法JNI_CreateJavaVM().... 为此,我添加了(在Linux上,使用Eclipse)以下“GCC C ++链接器”设置: - =&gt; “图书馆”=&gt; “库(-l)”=&gt; “Jvm”和 =&GT; “库搜索路径(-L)”=&gt; “/usr/lib/jvm/java-1.7.0.openjdk-1.7.0.71.x86_64/jre/lib/amd64/server”

- =&gt; “共享库设置”=&gt; “共享对象名称”=&gt; “libjvm.so”

其他设置在编译/链接期间出错。

有了这个,就可以建立环境。调试器在main中启动并停止,我可以照常执行C ++代码直到....我到达JNI_CreateJavaVM()调用。那时发生以下错误。

重定位错误:/ home / adminuser / workspace_Unit_Test_Java_Cpp / Unit_Test_Jni_Cpp / Debug / Unit_Test_Jni_Cpp:符号JNI_CreateJavaVM,版本SUNWprivate_1.1未在文件libjvm.so中定义,带有链接时间参考

我特此怀疑:  1. jni头和库(libJvm.so)不同步,或  2.类路径或lib路径不包含正确的值 3.加载的Java .so(.dll)(带有“dlopen”)不应该是它应该是....

任何想法都使用哪个值?

这是我的问题的背景:确定jni和libJvm.so内容不同步,知道它是什么以及它的位置非常方便....

1 个答案:

答案 0 :(得分:0)

a)确保你的LD_LIBRARY_PATH

上有"$PORT"

b)切换回“旧代码”,隐式加载 libjvm.so ,不需要dlopen和东西。