2

I got 2 projects. both are created in Netbeans IDE on Ubuntu 64 bit.

first, my .so project implements calling Java function from its c++ codes. and my console application try to call functions in .so file.

I got an error as following when I compiles and run:

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

How to resolve this?

I included include path to my .so project. Here is what my netbeans shows on its build output when I compile .so project:

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

this .so compiles very well and produces .so file.

And here is what my Netbeans shows when I compile my main console application:

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

It also compiles very well and run.

But the problem is I get an error message when I try to create Java Virtual Machine, "JNI_CreateJavaVM(&jvm, reinterpret_cast(&env), &vm_args)".

And following are all my source codes,

for .so project's testLib.h:

#ifndef TESTLIB_H
#define TESTLIB_H

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

#endif

for .so project's testVir.h:

#ifndef TESTVIR H
#define TESTVIR_H

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

#endif

for .so project's 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 ;
}

And Lastly, Here is my main console application, main.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 ;
}
online.0227
  • 640
  • 4
  • 15
  • 29

2 Answers2

4

Your libjvm_dll.so uses symbols from libjvm.so so it should be linked with it when you build it.

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

Entire build process:

# 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
Joni
  • 108,737
  • 14
  • 143
  • 193
  • if I do this when creating .so, then my main console applications's dlopen() cannot load this .so file. dlopen() returns nothing therefore my "void *handle" receives no address, keep pointing to 0x0 memory. – online.0227 Aug 27 '13 at 08:01
  • it says "libjvm.so: cannot open shared object file: No such file or directory", whether I put "-L/home/online0227/jdk1.7.0_25_x64/jre/lib/amd64/server -ljvm" into my console main application or not. It shows that error message in both cases. – online.0227 Aug 27 '13 at 09:40
  • Do you set LD_LIBRARY_PATH when running? – Joni Aug 27 '13 at 09:44
  • I am very new to Linux, but I think I set. Here is what I get for typing "echo $LD_LIBRARY_PATH" in terminal=> echo $LD_LIBRARY_PATH /home/online0227/jdk1.7.0_25_x64/jre/lib/amd64:/home/online0227/jdk1.7.0_25_x64/jre/lib/amd64/server – online.0227 Aug 27 '13 at 09:49
  • `libjvm.so` is in ​`jre/lib/amd64/server` so that should work. Have you made LD_LIBRARY_PATH into an environment variable with `export LD_LIBRARY_PATH`? – Joni Aug 27 '13 at 09:54
  • What I did all for setting java environment variable is that I put following 3 lines in .bashrc. 'export PATH="$PATH:/home/online0227/jdk1.7.0_25_x64/bin" export JAVA_HOME=/home/online0227/jdk1.7.0_25_x64 export LD_LIBRARY_PATH=$JAVA_HOME/jre/lib/amd64:$JAVA_HOME/jre/lib/amd64/server' That is all I did and I thought I set all path correctly, didn't I? – online.0227 Aug 27 '13 at 09:59
  • It looks correct and everything works, I tested it but used a simpler process (included in the answer). Verify that libjvm_dll.so is linked with libjvm.so using `ldd` and try running the main executable under `strace`, maybe that can reveal a problem – Joni Aug 27 '13 at 10:15
  • ok. I typed "ldd libjvm_dll.so" then it shows one of them which is.. "libjvm.so => /home/online0227/jdk1.7.0_25_x64/jre/lib/amd64/server/libjvm.so (0x00007f21a7efe000)". I think it is correct path, but anyways does not work.. well I found from random website that my JDK should be in /usr/lib/JVM folder otherwise libs including libjvm.so is not searchable.. is it true? About 'strace' I will try it because I have to study it first I am sorry – online.0227 Aug 27 '13 at 10:32
  • As you can see in the output of `ldd` the dynamic linker finds the libjvm.so just fine, the location doesn't matter. The problem has to be somewhere else, maybe `jvm_run` is picking up an old version of your `libjvm_dll.so` from an unexpected path. Have you tried the simplified build process? – Joni Aug 27 '13 at 12:56
  • Hello. I tried yours on terminal. It seems worked! nice, thank you very much! I am new to Linux system and I was always coding on graphical IDE like MSVS... every g++ commands I wrote above is what Netbeans IDE on ubuntu platform shows on its build output.. (I actually know only little of them) and I am going to try to compile and run them on Netbeans from now on. – online.0227 Aug 27 '13 at 13:49
  • Do you also try to run through NetBeans? It could be that Netbeans does not forward `LD_LIBRARY_PATH` when it starts the program, but you can probably set it up in project settings. – Joni Aug 27 '13 at 14:02
  • Yes. like I have done so far for other projects, I am a beginner always working on graphical IDE like visual studio lol.. yes therefore I have to. I will make another post because I have gotten a problem on netbean haha.. dlopen() does not load my .so file. here is downloadable address: http://cfile220.uf.daum.net/attach/252E5D4B521CB5B906E971 – online.0227 Aug 27 '13 at 14:21
0

Try to check out this website blog

Juniar
  • 1,269
  • 1
  • 15
  • 24