Java JNI call FindClass fails from a C++ program

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 -ljvm

I run javac SearchEngine.java to create the class file.

What am I doing wrong?

9

1 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/javac

and

$ javac -version
javac 11.0.6

then

$ 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
777

For 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

Your Answer

Sign up or log in

Sign up using Google Sign up using Facebook Sign up using Email and Password

Post as a guest

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

You Might Also Like