I am trying to follow this tutorial which calls a Java class from a C++ program. A Java virtual machine is instantiated but the call to FindClass fails. The code sample is directly from the tutorial:
MyTest.java
public class MyTest { private static int magic_counter=777; public static void mymain() { System.out.println("Hello, World in java from mymain"); System.out.println(magic_counter); }
}main.cpp
#include <jni.h>
#include <iostream>
using namespace std;
int main()
{ JavaVM *jvm; JNIEnv *env; JavaVMInitArgs vm_args; JavaVMOption* options = new JavaVMOption[1]; options[0].optionString = "-Djava.class.path=./"; vm_args.version = JNI_VERSION_1_6; vm_args.nOptions = 1; vm_args.options = options; vm_args.ignoreUnrecognized = false; jint rc = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); delete options; if (rc != JNI_OK) { std::cin.get(); exit(EXIT_FAILURE); } cout << "JVM load succeeded: Version "; jint ver = env->GetVersion(); cout << ((ver>>16)&0x0f) << "."<<(ver&0x0f) << endl; jclass cls2 = env->FindClass("MyTest"); if(cls2 == nullptr) { cerr << "ERROR: class not found !"; } else { cout << "Class MyTest found" << endl; jmethodID mid = env->GetStaticMethodID(cls2, "mymain", "()V"); if(mid == nullptr) cerr << "ERROR: method void mymain() not found !" << endl; else { env->CallStaticVoidMethod(cls2, mid); cout << endl; } } jvm->DestroyJavaVM(); cin.get();
}g++ command:
g++ -I/usr/lib/jvm/java-8-openjdk-amd64/include -I/usr/lib/jvm/java-8-openjdk-amd64/include/linux -L/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server main.cpp -o SearchEngineCpp -ljvmI run javac SearchEngine.java to create the class file.
What am I doing wrong?
91 Answer
This can occur if you have multiple versions of the JDK on your system, and the default Java version for the javac class compiler is different from the libjvm.so with which you are linking your executable.
For example, on my 18.04 system:
$ update-alternatives --list javac
/usr/lib/jvm/java-11-openjdk-amd64/bin/javac
/usr/lib/jvm/java-8-openjdk-amd64/bin/javacand
$ javac -version
javac 11.0.6then
$ javac MyTest.java
$
$ LD_LIBRARY_PATH=/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server ./SearchEngineCpp
JVM load succeeded: Version 1.8
ERROR: class not found !You can work around this by calling the appropriate java compiler explicitly ex.
$ /usr/lib/jvm/java-8-openjdk-amd64/bin/javac MyTest.java
$
$ LD_LIBRARY_PATH=/usr/lib/jvm/java-8-openjdk-amd64/jre/lib/amd64/server ./SearchEngineCpp
JVM load succeeded: Version 1.8
Class MyTest found
Hello, World in java from mymain
777For a persistent system-wide solution, use the update-alternatives mechanism to choose the appropriate Java version:
sudo update-alternatives --config java
sudo update-alternatives --config javac
sudo update-alternatives --config javap 3