Name: krC82822 Date: 08/07/2001
7 Aug 2001, kevin.ryan@eng -- reproducible with 1.3.1 and 1.4 beta (build 65)
on Solaris 2.8 (please also see Comments section)
----------------
java version "1.3.1"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.3.1-b24)
Java HotSpot(TM) Client VM (build 1.3.1-b24, mixed mode)
When invoking methods through the invocation API, trying to obtain the context
ClassLoader for a Thread will return null
unless the Thread is the main Thread which was used to create the JVM.
In a simple example, I have Thread 1 which creates a JVM and invokes a method on
a class. I then launch a second Thread
which invokes the same method on the class. In Thread 1 is the context
classloader ok (it is the application classloader).
In Thread 2 though, the Thread.getContextClassLoader() returns null.
********* Java Code *********
public final class JVMInvoker
{
public static void invoke() {
Thread me = Thread.currentThread();
System.out.println(
"JAVA: Calling Thread : " + me
);
System.out.println(
"JAVA: ContextClassLoader: " + me.getContextClassLoader()
);
}
}
********* Invocation Code *********
#include <pthread.h>
#include <jni.h>
#include <malloc.h>
#include <stdlib.h>
//------------------------------------------------------
// Globals
static JavaVM* m_JVM;
static jmethodID m_JavaInvokerMID;
static jclass m_JavaInvokerClazz;
//------------------------------------------------------
// Function Decls
extern "C" {
void createJavaVM();
void invokeMethod();
void* launchThread(void*);
}
//------------------------------------------------------
// Main
static JavaVM* jvm = NULL;
int main(int, char**)
{
fprintf(stdout, "\n");
// creates the VM and calls invokeMethod
createJavaVM();
fprintf(stdout, "\n");
pthread_t tid;
pthread_create(&tid, NULL, launchThread, NULL);
fprintf(stdout, "\n");
}
//------------------------------------------------------
// createJavaVM
void createJavaVM()
{
JNIEnv* env = NULL;
JavaVMInitArgs vm_args;
JavaVMOption* options = (JavaVMOption*)malloc(sizeof(JavaVMOption));
options[0].optionString = (char*)"-Djava.class.path=.";
options[0].extraInfo = (void*)0;
vm_args.version = JNI_VERSION_1_2;
vm_args.options = options;
vm_args.nOptions = 1;
vm_args.ignoreUnrecognized = JNI_FALSE;
jint result = JNI_CreateJavaVM(&m_JVM, (void**)&env, &vm_args);
if ( result != JNI_OK ) {
fprintf(stderr, "\nCould not create JAVA VM\n");
exit(1);
}
const char* name = "JVMInvoker";
jclass clazz = env->FindClass(name);
if ( clazz == NULL ) {
fprintf(stderr, "\nCould not load 'JVMInvoker'\n");
exit(1);
}
m_JavaInvokerMID = env->GetStaticMethodID(clazz, "invoke", "()V");
if ( m_JavaInvokerMID == 0 ) {
fprintf(stderr, "\nCould not find method invoke()\n");
exit(1);
}
m_JavaInvokerClazz = (jclass)env->NewGlobalRef(clazz);
// now invoke method in same thread
fprintf(
stdout, "CPP : Thread (%d): Invoking JVMInvoker .... OK\n",
pthread_self()
);
invokeMethod();
}
//------------------------------------------------------
// invokeMethod
void invokeMethod()
{
JNIEnv* env = NULL;
jint result = m_JVM->AttachCurrentThread((void**)&env, 0);
if ( result != JNI_OK ) {
fprintf(
stderr,
"\nCould not attach current thread to JVM: Thread = %d",
pthread_self()
);
exit(1);
}
fprintf(stdout, "CPP : Calling Thread = %d\n", pthread_self());
env->CallStaticVoidMethod(
m_JavaInvokerClazz,
m_JavaInvokerMID
);
}
//------------------------------------------------------
// launchThread
void* launchThread(void*)
{
fprintf(
stdout, "CPP : Thread (%d): Invoking JVMInvoker .... NOK\n",
pthread_self()
);
invokeMethod();
return (void*)0;
}
********* Makefile *********
#-----------------------------------------------------------------
# Vars
CC = /opt/workshop6u1/bin/CC
JAVA_HOME=/opt/java/jdk/1.3.1
#JAVA_HOME=/opt/java/jdk/1.2.2_05a
FLAGS = -DDEBUG -g +w2 -KPIC -mt
INCLS = -I. -I$(JAVA_HOME)/include/solaris -I$(JAVA_HOME)/include
LIBS = -L$(JAVA_HOME)/jre/lib/sparc -ljvm
CPP_SOURCES = JVMInvoker.cpp
JAVA_SOURCES = JVMInvoker.java
EXENAME = jvminoker
#-----------------------------------------------------------------
# Rules
all: java_compile exe
java_compile:
$(JAVA_HOME)/bin/javac -g -d . $(JAVA_SOURCES)
exe:
$(CC) -o $(EXENAME) $(FLAGS) $(INCLS) $(CPP_SOURCES) $(LIBS)
run:
CLASSPATH=. LD_LIBRARY_PATH=$(JAVA_HOME)/jre/lib/sparc $(EXENAME)
clean:
\rm -fr *.o *~ $(EXENAME) *.class
(Review ID: 128509)
======================================================================
- duplicates
-
JDK-4335925 Remote method throws ClassCastException when jvm is attached to native thread
-
- Closed
-