Skip to Main Content

Java HotSpot Virtual Machine

Announcement

For appeals, questions and feedback about Oracle Forums, please email oracle-forums-moderators_us@oracle.com. Technical questions should be asked in the appropriate category. Thank you!

AttachCurrentThread fails when several VMs running in different threads

843829Aug 25 2008 — edited Aug 25 2008
Hi,

I would like to build an application that runs several JVMs in parallel. I'm using Java6 and according to the JNI specs this should be possible as long as each VM instance is running in a separate thread.

In the below mentioned demo application two threads are created. Both instantiate a VM (which works well). But only one thread seems to be able to run AttachCurrentThread. When AttachCurrentThread is called for the second one I get the following error:
#
# An unexpected error has been detected by Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x080486ae, pid=1428, tid=3035118512
#
# Java VM: Java HotSpot(TM) Client VM (1.6.0_03-b05 mixed mode, sharing)
# Problematic frame:
# C  [jvmthreads+0x6ae]
But because one thread successfully instantiates a java class I think that the basic code structure is OK. It seems to be a threading issue. My application looks as follows:
#include <stdlib.h>
#include <jni.h>
#include <pthread.h>

#define USER_CLASSPATH "myclasses.jar"
#define CLASS_NAME "com.foobar/DummyRtbosFiller"


JavaVM* JavaThreads_createJVM(){
	JNIEnv *env;
    JavaVM *vm;
    jint res;

    setenv("JAVA_VM_VERSION", "1.5", 1);
//    setenv("JAVA_VM_VERSION", "1.5", 0);
    JavaVMInitArgs vm_args;
    JavaVMOption options[7];

    options[0].optionString = malloc(3000*sizeof(char));
    sprintf(options[0].optionString, "-Djava.class.path="USER_CLASSPATH);
    options[1].optionString = "-Xmx64m";

	int enableRemDebugging = 0;
	if(enableRemDebugging){
	    printf("enable remote debugging");

		// intellij remote debugging support
		options[2].optionString = "-Xdebug";
		options[3].optionString = "-Xnoagent";
		options[4].optionString = "-Djava.compiler=NONE";
		options[5].optionString = "-Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=34343";

		vm_args.nOptions = 6;
	}else{
		vm_args.nOptions = 2;
	}

	vm_args.options = options;
    vm_args.version = JNI_VERSION_1_4;

    vm_args.ignoreUnrecognized = JNI_TRUE;
    /* Create the Java VM */

    res = JNI_CreateJavaVM(&vm, (void**)&env, &vm_args);
    printf("java started.\n");

	return vm;
}

/*!
 * \brief Shuts down an existing java virtual machine.
 * \param jvm Pointer to the jvm to be destroyed.
 *
 * This method is used to shut down an existing java virtual machine.
 */
int JavaThreads_destroyJVM(JavaVM *jvm){
//	JNIEnv *env = getAttachedEnv(self, jvm);
//
//	if ((*env)->ExceptionOccurred(env)) {
//        (*env)->ExceptionDescribe(env);
//    }

	 // detach the current thread from the vm
    (*jvm)->DetachCurrentThread(jvm);

    (*jvm)->DestroyJavaVM(jvm);

	return 0;
}


/*!
 * \brief Attaches the current thread to a given vm instance
 * \param self Pointer to bbcm-instance
 * \param jvm Pointer to the jvm use for attachment
 *
 * This method is used to attach the current thread to a given vm instance
 */
JNIEnv* getAttachedEnv(JavaVM *jvm){
	JNIEnv *localEnv = NULL;
	int envErr = 0;

	/* get a local java env */
	envErr = (*jvm)->AttachCurrentThread( jvm, (void**)&localEnv, NULL );

	if ( envErr != 0 ){
		if ( (*localEnv)->ExceptionCheck( localEnv ) == JNI_TRUE ){
		  (*localEnv)->ExceptionDescribe( localEnv );
		}
	}

	if((*localEnv)->ExceptionOccurred(localEnv)){
	    (*localEnv)->ExceptionDescribe(localEnv);
    }

	if (localEnv == NULL) {
        printf("ERROR: failed to get ENV pointer in pushContext");
		//  JavaThreads_destroyJVM(jvm);

        return (JNIEnv*) NULL;
    }

	return localEnv;
}


/*!
 * \brief Create a new instance of the transcriber application
 * \return Pointer to the java object
 *
 * This method is used to create a new instance transcriber application
 */
jobject startJavaSubSystem(JavaVM *jvm, char* argString){
    printf("attaching env pointer.\n");
	JNIEnv *env = getAttachedEnv(jvm);
    printf("thread attachment done.\n");

	jclass cls;
	jmethodID mid;
	jobject transcriber;

	cls = (*env)->FindClass(env, CLASS_NAME);
    if (cls == NULL) {
        JavaThreads_destroyJVM(jvm);
    }

	jstring jArgumentString = (*env)->NewStringUTF(env, argString);
    mid = (*env)->GetMethodID(env, cls, "<init>", "(ILjava/lang/String;)V");
	if (mid == NULL) {
        JavaThreads_destroyJVM(jvm);
    }

    printf("starting object instantiation\n");
    (*env)->NewObject(env, cls, mid, 1, jArgumentString);

	return transcriber;
}


void startJavaThread(char* arg){
	JavaVM *jvm;

    printf("create a jvm instance for component '%s'\n", arg);
	jvm = JavaThreads_createJVM();

    printf("attempting to start component '%s'\n", arg);
    startJavaSubSystem(jvm, arg);
    printf("component '%s' started !\n", arg);

    // sleep forever to keep the thread alive
    sleep(10000);
}


int main(int argc, char **argv) {

	 pthread_t thread1, thread2;

	 /* Create independent threads each of which will instantiate a java VM. */
     int iret1 = pthread_create( &thread1, NULL, startJavaThread,  (void*) "test47");
     sleep(1);
     int iret2 = pthread_create( &thread2, NULL, startJavaThread, (void*) "test48");

     pthread_join( thread1, NULL);
     pthread_join( thread2, NULL);

     printf("Thread 1 returns: %d\n",iret1);
     printf("Thread 2 returns: %d\n",iret2);

	return 0;
}
What could be my mistake?
Any help (links, docs, ideas) is welcome.

Best regards, Holger
Comments
Locked Post
New comments cannot be posted to this locked post.
Post Details
Locked on Sep 22 2008
Added on Aug 25 2008
2 comments
665 views