Infinite loop while calling JNI_CreateJavaVM (creating a JavaVM from C++)

P

proy

I have a beautiful (that's at least what I think) piece of code that
soft-links to jvm.dll so that a JavaVM instance is created from C++.
The problem is that JNI_CreateJavaVM never returns! Would anyone have
some pointers to let me know what may be wrong in my code?

While referring to the code bellow, dEntryPoint2 is obtained
successfuly from the Dll, it is called, but stays into an infinite loop
(never comes back).

#include <jni.h>

JavaVM *CJavascript::m_JavaVM = NULL;
jclass CJavascript::m_class;
vector<CJavascript*> g_allObjects;
int gProcessCount = 0;
HMODULE CJavascript::m_java_dll = NULL;

typedef jint (JNICALL JNI_GetCreatedJavaVMs_t)(JavaVM **, jsize,
jsize*);
typedef jint (JNICALL JNI_CreateJavaVM_t)(JavaVM **pvm, void **penv,
void *args);

#define MY_CLASSPATH "js.jar:JavaScriptExecution.jar:."

bool EnsureJavaLaunched(JNIEnv *&dEnv)
{
dEnv = NULL;
if (CJavascript::m_JavaVM == NULL)
{
jint ret;
jmethodID mid;
jsize nVMs = 0;
if (CJavascript::m_java_dll == NULL)
{
HKEY openkey = NULL;
DWORD type;
DWORD size;
string fullKeyName;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SOFTWARE\\JavaSoft\\Java
Runtime Environment", 0, KEY_READ, &openkey) == ERROR_SUCCESS)
{
char buffer[1024];
size = sizeof(buffer);
if (RegQueryValueEx(openkey, "CurrentVersion", NULL, &type,
(LPBYTE)&buffer[0], &size) == ERROR_SUCCESS)
{
fullKeyName = "SOFTWARE\\JavaSoft\\Java Runtime
Environment\\";
fullKeyName += buffer;
RegCloseKey(openkey);
openkey = NULL;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
fullKeyName.c_str(), 0, KEY_READ, &openkey) == ERROR_SUCCESS)
{
size = sizeof(buffer);
if (RegQueryValueEx(openkey, "RuntimeLib", NULL,
&type, (LPBYTE)&buffer[0], &size) == ERROR_SUCCESS)
{
CJavascript::m_java_dll = LoadLibraryEx(buffer,
NULL, 0);
}
}
}
if (openkey != NULL)
{
RegCloseKey(openkey);
}
}
}
if (CJavascript::m_java_dll != NULL)
{
JNI_GetCreatedJavaVMs_t *dEntryPoint =
(JNI_GetCreatedJavaVMs_t*)GetProcAddress(CJavascript::m_java_dll,
"JNI_GetCreatedJavaVMs");
if (dEntryPoint != NULL)
{
if (!((dEntryPoint(&CJavascript::m_JavaVM, 1, &nVMs) == 0)
&& (nVMs == 1)))
{
JavaVMInitArgs vm_args;
JavaVMOption options[3];
char buffer[1024];

options[0].optionString = "-Djava.compiler=NONE";
/* disable JIT */
strcpy(buffer, "-Djava.class.path=");
strcat(buffer, MY_CLASSPATH);
options[1].optionString = buffer;
/* user classes */
options[2].optionString = "-verbose:jni";
/* print JNI-related messages */

vm_args.version = JNI_VERSION_1_4;
vm_args.options = options;
vm_args.nOptions = 3;
vm_args.ignoreUnrecognized = FALSE;
JNI_CreateJavaVM_t *dEntryPoint2 =
(JNI_CreateJavaVM_t*)GetProcAddress(CJavascript::m_java_dll,
"JNI_CreateJavaVM");
if (dEntryPoint2 != NULL)
{
ret = dEntryPoint2(&CJavascript::m_JavaVM,
(void**)&dEnv, &vm_args);
if ((ret >= 0) && (CJavascript::m_JavaVM != 0) &&
(dEnv != 0))
{
jclass clazz =
dEnv->FindClass("JavaScriptExecution");
if (clazz != NULL)
{
mid = dEnv->GetStaticMethodID(clazz, "main",
"([Ljava/lang/String;)V");
if (mid != NULL)
{
dEnv->CallStaticVoidMethod(clazz, mid,
NULL);
}
}
}
}
}
}
}
}
if ((dEnv == NULL) && (CJavascript::m_JavaVM != NULL))
{
CJavascript::m_JavaVM->AttachCurrentThread((void**)&dEnv, NULL);
}
return (dEnv != NULL);
}

BOOL APIENTRY DllMain( HANDLE,
DWORD ul_reason_for_call,
LPVOID
)
{
switch (ul_reason_for_call)
{
case DLL_PROCESS_ATTACH:
case DLL_THREAD_ATTACH:
{
JNIEnv *dEnv;
gProcessCount++;
// Launch java daemon
EnsureJavaLaunched(dEnv);
}
break;
case DLL_THREAD_DETACH:
case DLL_PROCESS_DETACH:
{
gProcessCount--;
if ((gProcessCount == 0) && (CJavascript::m_JavaVM !=
NULL))
{
CJavascript::m_JavaVM->DestroyJavaVM();
}
}
break;
}
return TRUE;
}
 
C

Chris Uppal

I have a beautiful (that's at least what I think) piece of code that
soft-links to jvm.dll so that a JavaVM instance is created from C++.
The problem is that JNI_CreateJavaVM never returns! Would anyone have
some pointers to let me know what may be wrong in my code?

I found it impossible to follow the code, and eventually just gave up.
However, if you are still having problems then I suggest two avenues to check.

One is that -- as far as I can tell -- you are not doing anything /too/ odd in
the way you create and use your JMV, but it does look as if you are calling
JNI_GetCreatedJavaVMs() before you have ever called JNI_CreateJavaVM(). I
don't /think/ that's wrong, but it is unusual; it might be worth changing
things around so you don't do that, and see what happens. Similarly, I'm a
bit suspicious about that call to AttacchCurrentThread() right at the end of
EnsureJavaLaunched(). By the time we reach that call, I have completely lost
any sense of how we have got there, so it may actually be completely fine, but
it's something I'd double check too.

The other is that I have never tried using the JVM from a DLL. It's a long
shot, but I'd try converting this code into a standalone .EXE and see if it
still failed.

-- chris
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top