Java Solaris Communities Sun Store Join SDN My Profile Why Join?
 
Bug Database
Bug Detail
Quick Lists
Top 25 Bugs
Top 25 RFE's
Recently Closed Bugs
Printable Page Printable Page


Bug Database
Bug ID: 4479303
Votes 0
Synopsis Cannot start more than one java virtual machine
Category java:native_interface
Reported Against merlin-beta
Release Fixed
State 11-Closed, Will Not Fix, bug
Priority: 4-Low
Related Bugs
Submit Date 12-JUL-2001
Description




java version "1.4.0-beta"

I'm trying to create 2 JVMS in a C++ program by using multiple threads. Each of
threads tries to start a java virtual machine by calling JNI_CreateJavaVM. Only
one of the threads can start java virtual machine successfully, the other one
gets return value -5 from calling JNI_CreateJavaVM. There are references to not
being able to create more than a single JVM from a single process with JDK 1.1
but I can not find anything about JDK 1.2.
The following are the code for the test.
/*_thread.h*/
#ifdef __cplusplus
extern "C" {
#endif

#include <stdio.h>

#ifndef _REENTRANT
#define _REENTRANT
#endif /* ifndef _REENTRANT */
#include <windows.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <process.h>
#define sleep(n) Sleep ( n * 1000 )
#define dtLARGE int


typedef void*  (*funcPtr) ( void*  ) ;
typedef funcPtr thrFuncPtr ;

typedef struct _threadStruct
{

  DWORD threadId ;
  HANDLE handle ;
  thrFuncPtr  func ;
  /* Argument pointer for func function */
  void* args ;
}
threadStruct , *threadPtr ;
typedef DWORD key ;
typedef void  (*destructorFn)( void *value) ;
dtLARGE KeyCrt ( key* k, destructorFn d ) ;
dtLARGE KeyGet ( key k, void** value ) ;
dtLARGE KeySet ( key k, void*  value ) ;


#ifdef __cplusplus
}
#endif
/*end of _thread.h*/

/*SqlJInterface.cpp*/
#include <jni.h>
#include <stdlib.h>
#include <string.h>
#include "_thread.h"

extern destructorFn destArray[];

extern "C" {
unsigned int WINAPI threadTestM(void * i);
}


dtLARGE ThrCrt ( threadPtr tPtr )
{

  if ( ! ( tPtr->handle = (HANDLE)_beginthreadex ( '\0', 0, &threadTestM,
tPtr,0,(unsigned int *)&tPtr->threadId ))) return 0 ;

  return 0 ;
}
void startM()
{
	JavaVM *jv;
	JNIEnv *env;
    jint res;
	JavaVMInitArgs	vm_args;

	
	JavaVMOption options[2];
	options[0].optionString = "-Djava.compiler=NONE";
	char const* clspath = getenv("CLASSPATH");

	if(clspath)
	{
		char* p1 = "-Djava.class.path=";
		options[1].optionString = new char[strlen(p1)+strlen(clspath)
+1];
		strcpy(options[1].optionString,p1);
		strcat(options[1].optionString,clspath);
	}
	else
	{
		printf( "Classpath may not be set up for java virtual
machine\n") ;
	}

	vm_args.nOptions = 2;

	vm_args.version = JNI_VERSION_1_2;
	vm_args.options = options;
	vm_args.ignoreUnrecognized = JNI_TRUE;
	
    /* Create the Java VM */
    res = JNI_CreateJavaVM(&jv,(void**)&env,&vm_args);
    if (res < 0) {
		printf( "Can not start java virtual machine. The return value
is: %d\n",res) ;
    }
	else
		printf( "java virtual machine is started\n") ;
}
void startD(int p)
{
	JavaVM *jv;
	JNIEnv *env;
    jint res;
	JavaVMInitArgs	vm_args;

	
	JavaVMOption options[5];
	options[0].optionString = "-Xdebug";
	options[1].optionString = "-Xnoagent";
	options[2].optionString = "-Djava.compiler=NONE";
	char const* clspath = getenv("CLASSPATH");
	if(clspath)
	{
		char* p1 = "-Djava.class.path=";
		options[3].optionString = new char[strlen(p1)+strlen(clspath)
+1];
		strcpy(options[3].optionString,p1);
		strcat(options[3].optionString,clspath);
	}
	else
	{
		printf( "Classpath may not be set up for java virtual
machine\n") ;
	}

	options[4].optionString = "-
Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=y";
	vm_args.nOptions = 5;

	vm_args.version = JNI_VERSION_1_2;
	vm_args.options = options;
	vm_args.ignoreUnrecognized = JNI_TRUE;
	
    /* Create the Java VM */
    res = JNI_CreateJavaVM(&jv,(void**)&env,&vm_args);
    if (res < 0) {
		printf( "can not start java virtual machine\n") ;
    }
	else
		printf( "java virtual machine get started\n") ;
}
unsigned int WINAPI threadTestM(void * i)
{
	int p = *((int*)i);

	printf( "Enter threadTestM with i = %d\n",p) ;

	startM();
	return 0;
}
main()
{

	int p = 10;

	threadStruct myThread;
	myThread.args = (void*)&p;

	ThrCrt(&myThread);
	Sleep(1000);

	int pp =20;
	myThread.args = (void*)&pp;
	ThrCrt(&myThread);
	Sleep(1000);

	return 0;
}
/*end of SqlJInterface.cpp*/
(Review ID: 127932) 
======================================================================
Work Around




No way. Our project is stuck here.
======================================================================
Evaluation
  xxxxx@xxxxx   2001-08-03
Allowing multipe JVMs in the same address space is much too difficult to 
consider.  There are numerous places where the VM and all of the native
methods would have to be changed to avoid collisions between the VM's
data areas.  Performance could be significantly reduced by the considerable
indirection needed to separate the global data.  Will not fix.
Comments
  
  Include a link with my name & email   

Submitted On 13-FEB-2002
dpc2
"Much too difficult to consider?"  What is the purpose of 
the JNI_GetCreatedJavaVMs() function in the JNI 
specification if the idea of multiple JVMs is not 
contemplated?


Submitted On 12-MAR-2002
janubande007
PROBLEM : I do not understand why this bug was closed & 
will not be fixed....this problem is compounded when the 
JVM is loaded from shared libraries(especially dynamically 
eg:dll on windows) . I have this problem....my application 
is a DLL on windows & a Dynamic Shared Library on Unix. It 
loads the JVM into the process space it was loaded into & 
Destroy's the JVM when it is unloaded from the 
process....but there are other dynamic shared libraries or 
DLLs that get loaded into the same process space, which may 
come from other vendors that may also load the JVM. Then 
the 1st one to get to laod the JVM gets to run. It is easy 
to invoke JNI_GetCreatedJavaVMs() before calling 
JNI_CreateJVM() & check to see if the JVM was loaded, but 
now what are the rules for Destorying the JVM ? We can code 
not to Destroy the JVM, but what if another Shared Library 
or DLL Destroyed the JVM ? In such a case we are hozed & 
will get an access violation when we try to execute any JNI 
calls ?

SOLUTION : The only right way to do this is to reference 
count calls JNI_CreateJavaVM() and DestroyJavaVM(). The 1st 
call to JNI_CreateJavaVM() creates a new JVM, while any 
following calls from the same process will lead to a 
reference to the already created JVM be returned to the 
caller. Also all calls to JNI_CreateJavaVM() will increment 
the Reference count. On the other hand the DestroyJavaVM() 
will end up decrementing the reference count & destroy the 
JVM only when the reference count becomes zero. This will 
allow a scenario like I have described above to execute 
cleanly.



PLEASE NOTE: JDK6 is formerly known as Project Mustang