I am trying to call the following java method from C++
final String[] games = GameLoader.listGames();
where GameLoader
was imported with import player.GameLoader;
. The GameLoader
class exists within a jar file. I am trying to use JNI to load the jar file from C++ and then call the above method. The following is my C++ code which I have tried to extend from this SO post.
#include <iostream>
#include <string.h>
#include <jni.h>
#include <stdlib.h>
using namespace std;
#define PATH_SEPARATOR ';'
#define USER_CLASSPATH "Ludii-0.3.0.jar"
#define GAME_LOADER "player/GameLoader"
JNIEnv *env;
JavaVM *jvm;
jint res;
void initJVM() {
#ifdef JNI_VERSION_1_2
JavaVMInitArgs vm_args;
JavaVMOption options[1];
options[0].optionString =
"-Djava.class.path=" USER_CLASSPATH;
vm_args.version = 0x00010002;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_TRUE;
/* Create the Java VM */
res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args);
#else
JDK1_1InitArgs vm_args;
char classpath[1024];
vm_args.version = 0x00010001;
JNI_GetDefaultJavaVMInitArgs(&vm_args);
/* Append USER_CLASSPATH to the default system class path */
sprintf(classpath, "%s%c%s",
vm_args.classpath, PATH_SEPARATOR, USER_CLASSPATH);
vm_args.classpath = classpath;
/* Create the Java VM */
res = JNI_CreateJavaVM(&jvm, &env, &vm_args);
#endif /* JNI_VERSION_1_2 */
}
void closeJVM() {
jvm->DestroyJavaVM();
}
int main() {
initJVM();
jclass gameLoader = env->FindClass(GAME_LOADER);
//final String[] games = GameLoader.listGames();
jmethodID mid = env->GetMethodID(gameLoader,"listGames","()[Ljava/lang/String;");
jobjectArray stringArray = (jobjectArray) env->CallObjectMethod(gameLoader,mid);
closeJVM();
}
I am able to successfully create the JVM and the code compiles however at runtime I get the error
# A fatal error has been detected by the Java Runtime Environment:
#
# SIGSEGV (0xb) at pc=0x00007f0e835619d7, pid=3504, tid=0x00007f0e84028740
#
# JRE version: OpenJDK Runtime Environment (8.0_222-b10) (build 1.8.0_222-8u222-b10-1ubuntu1~16.04.1-b10)
# Java VM: OpenJDK 64-Bit Server VM (25.222-b10 mixed mode linux-amd64 compressed oops)
# Problematic frame:
# V [libjvm.so+0x6849d7]
#
# Failed to write core dump. Core dumps have been disabled. To enable core dumping, try "ulimit -c unlimited" before starting Java again
#
# An error report file with more information is saved as:
# /home/alex/jni_examples/hs_err_pid3504.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
#
Aborted (core dumped)
I think that the error is related to the CallObjectMethod
call but I'm not sure.
Also I am using Java 8
EDIT:
It looks like mid
evaluated to 0 which means that the method was not found. I guess this is the problem however I'm not sure why it wasn't found. This was checked with
int main() {
initJVM();
jclass gameLoader = env->FindClass("player/GameLoader");
//final String[] games = GameLoader.listGames();
if(gameLoader == NULL)
{
cout << "Could not load class!" << endl;
return 1;
}
jmethodID mid = env->GetMethodID(gameLoader,"listGames","()[Ljava/lang/String;");
if(mid == NULL)
{
cout << "Could not load method!" << endl;
return 1;
}
jobjectArray stringArray = (jobjectArray) env->CallObjectMethod(gameLoader,mid);
if(stringArray == NULL)
{
cout << "Could not load object!" << endl;
return 1;
}
closeJVM();
}
ANOTHER EDIT:
So it looks like the problem was that listGames()
should be found with GetStaticMethodID
rather than GetMethodID
and it should be called with CallStaticObjectMethod
rather than CallObjectMethod
. Thank you.