|
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)
======================================================================
|
|
Comments
|
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
|