waheed
waheed

Reputation: 164

How to set classpath of a running JVM in C++(JNI)?

In C++ (JNI), I get an already running JVM using the following JNI function:

JNI_GetCreatedJavaVMs(&jvm,1,&vmnb);

Then I attach the current thread using the following code:

jvm->AttachCurrentThread((void**)&env, NULL);

Question: How can I set classpath in that case? Thanks.

Note: Creating a new JVM and passing the classpath in vm_args to the new JVM is not an option for me.

Upvotes: 6

Views: 4581

Answers (2)

waheed
waheed

Reputation: 164

As it is possible to append the classpath inside Java, so I found an alternative way to set classpath inside C++ through Java. As I'm already running JVM, I use the append classpath method (void addPath(String path), that is posted in this answer), inside the Java program that is already running in the JVM. I access the addPath java method from C++ using JNI calls to append the classpath. The classpath passed to addPath method from C++ should not include "-Djava.class.path" and it should be just complete path to the .jar file, i.e. "C:\\folder\\abc.jar". So sequence is: 1) get already running JVM, attach current thread to the JVM, get JNI environment pointer and then call addPath java function (of another running thread) from C++ using JNI. I can now access the classes of new classpath (.jar file) successfully from C++.

Upvotes: 5

laht
laht

Reputation: 96

I ran into this issue, and I did not have the option to call back into the JVM, so I implemented the whole add_path busniess on the JNI side.

void add_path(JNIEnv* env, const std::string& path)
{
    const std::string urlPath = "file:/" + path;
    jclass classLoaderCls = env->FindClass("java/lang/ClassLoader");
    jmethodID getSystemClassLoaderMethod = env->GetStaticMethodID(classLoaderCls, "getSystemClassLoader", "()Ljava/lang/ClassLoader;");
    jobject classLoaderInstance = env->CallStaticObjectMethod(classLoaderCls, getSystemClassLoaderMethod);
    jclass urlClassLoaderCls = env->FindClass("java/net/URLClassLoader");
    jmethodID addUrlMethod = env->GetMethodID(urlClassLoaderCls, "addURL", "(Ljava/net/URL;)V");
    jclass urlCls = env->FindClass("java/net/URL");
    jmethodID urlConstructor = env->GetMethodID(urlCls, "<init>", "(Ljava/lang/String;)V");
    jobject urlInstance = env->NewObject(urlCls, urlConstructor, env->NewStringUTF(urlPath.c_str()));
    env->CallVoidMethod(classLoaderInstance, addUrlMethod, urlInstance);
    std::cout << "Added " << urlPath << " to the classpath." << std::endl;
}

Upvotes: 2

Related Questions