473,325 Members | 2,342 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,325 software developers and data experts.

Proper termination of JVM

I'm not sure which section I should post this in, since the problem covers Java, C++ and .NET managed C++...

Anyway - I'm using some Java classes via JNI in unmanaged C++, then call the unmanaged C++ class from managed C++.

What I want to be able to do is create an object that uses JNI, then destroy it, then create and use another.

The problem is that the second time around funcCreateJavaVM returns -1 (unknown error). I figure I'm not disposing it properly the first time, but I'm not sure what I'm doing wrong. The call to DestroyJavaVM is in the destructor of the unmanaged class.

The unmanaged class looks something like this:

//Path to jvm.dll
#define JVMDLLPATH "C:\\Program Files\\Java\\jdk1.6.0_04\\jre\\bin\\client\\jvm.dl l"
//Function type for JNI_CreateJavaVM
typedef UINT (CALLBACK* CreateJavaVM)(JavaVM**,void**,JavaVMInitArgs*);

class edoc
{
JNIEnv *env;
JavaVM *jvm;

HINSTANCE jvmdll;
JavaVMInitArgs vmargs;

public:

void init()
{
env = (JNIEnv*)malloc(sizeof(JNIEnv));
jvm = (JavaVM*)malloc(sizeof(JavaVM));

//Load jvm.dll
jvmdll = LoadLibrary(JVMDLLPATH);

//Initialize function variable for JNI_CreateJavaVM
CreateJavaVM funcCreateJavaVM;
funcCreateJavaVM = (CreateJavaVM)GetProcAddress(jvmdll,"JNI_CreateJav aVM");

//Start JVM
JavaVMOption vmoptions[1];
vmargs.version=JNI_VERSION_1_6;
vmargs.nOptions=2;
vmoptions[0].optionString=VMOPTIONCLASSPATH; //capitalized are macros containing paths
vmoptions[1].optionString=VMOPTIONPATH;
vmargs.options = vmoptions;
vmargs.ignoreUnrecognized = JNI_FALSE;
funcCreateJavaVM(&jvm, (void**)&env, &vmargs);

//multiple calls to JVM via env go here - initialising jclass, jmethodID variables and the like
}
~edoc()
{
jvm->DestroyJavaVM();
FreeLibrary(jvmdll);
}
};

The managed class looks something like this:
public ref class clrEDOC
{
edoc* ed;

public: clrEDOC()
{
ed = new edoc();
ed->init();
}
~clrEDOC()
{
ed->~edoc(); //used to be "delete ed;"
}
};

And the code that calls it is as follows (edocjni is the namespace):
void main()
{
edocjni::clrEDOC^ clred = gcnew edocjni::clrEDOC(); //executes properly
clred->~clrEDOC(); //used to be "delete clred;"
edocjni::clrEDOC^ ed = gcnew edocjni::clrEDOC(); //unknown error while creating JVM
}
Feb 15 '08 #1
3 1328
r035198x
13,262 8TB
I've also copied this to the C++ forum.
Feb 15 '08 #2
I may have found a solution myself, but AFAIK its undocumented and I have no idea how good it will work, but the first tests are successful.

What I learned was - the call to DestroyJavaVM does not actually destroy JVM. Quoting from Sun "The VM waits until the main thread is the only user thread before it actually unloads." Why does it not happen immediately, if I have not attached any extra threads to it, I have no idea.

Anyway, until JVM is properly destroyed, another one cannot start in the same thread (hence the error I was getting).

So what I do now, is save the pointer to JNIEnv and submit it as an argument to the function initializing JVM. The beginning of the init method now looks like this:

void init(void* _env)
{
if (_env == NULL) env = new JNIEnv; else env = (JNIEnv*)_env;

I also added a void* getenv() method to get the pointer before disposing the object and removed the DestroyJavaVM call.

Initialized another object and the calls to JVM via the submitted pointer are successful.

Any input on the matter is still appreciated.
Feb 15 '08 #3
For the record: the way I ultimately did that was like this:

Expand|Select|Wrap|Line Numbers
  1. int i = this->getCreatedJVMs();
  2.   if (i>0)
  3.     this->attachtoJVM();
  4.   else
  5.     this->launchJVM();
  6.  
where launchJVM() launches JVM as shown in my first post, attachtoJVM() looks like this:
Expand|Select|Wrap|Line Numbers
  1.     void attachtoJVM()
  2.     {
  3.         dllpath = JVMDLLPATH;
  4.         jvmdll = LoadLibrary(dllpath);
  5.         GetCreatedJavaVMs funcGetCreatedJavaVMs;
  6.         funcGetCreatedJavaVMs = (GetCreatedJavaVMs)GetProcAddress(jvmdll,"JNI_GetCreatedJavaVMs");
  7.         JavaVM **javm;
  8.         int buflen = 4;
  9.         int *nVMs;
  10.         int i = funcGetCreatedJavaVMs(javm, buflen, nVMs);
  11.         javm[0]->AttachCurrentThread((void**)&env,NULL);
  12.     }
  13.  
And getCreatedJVMs() looks like this:
Expand|Select|Wrap|Line Numbers
  1.     //Returns a positive value if at least one JVM is running. 
  2.     //This value can be either the number of JVMs running or the memory address of one of them
  3.     //Behaviour not fully documented.
  4.     int getCreatedJVMs()
  5.     {    dllpath = JVMDLLPATH;
  6.         jvmdll = LoadLibrary(dllpath);
  7.         GetCreatedJavaVMs funcGetCreatedJavaVMs;
  8.         funcGetCreatedJavaVMs = (GetCreatedJavaVMs)GetProcAddress(jvmdll,"JNI_GetCreatedJavaVMs");
  9.         JavaVM **javm;
  10.         int buflen = 4;
  11.         int *nVMs;
  12.         int i = funcGetCreatedJavaVMs(javm, buflen, nVMs);
  13.         if (nVMs==0) return 0; else return (*nVMs);
  14.     }
  15.  
This requires another typedef to work:
Expand|Select|Wrap|Line Numbers
  1. typedef UINT (CALLBACK* GetCreatedJavaVMs)( JavaVM**, int, int* );
Mar 7 '08 #4

Sign in to post your reply or Sign up for a free account.

Similar topics

0
by: Alexander Staubo | last post by:
Python does not seem to clean up gracefully on SIGTERM: The exit sequence is not invoked on termination, so the atexit module cannot be used to install shutdown logic. Further, while the signal...
2
by: Jim McGrail | last post by:
Background: I am investigating a problem involving a windows .NET application that is being developed in C# with Visual Studio 2003. It is a multi-threaded application that uses MSMQ to...
35
by: Felix Kater | last post by:
The C-faq says that "The malloc/free implementation remembers the size of each block allocated and returned, so it is not necessary to remind it of the size when freeing." Could that length...
2
by: Ian Sykes | last post by:
I have a C# program which terminates prematurely, with no error or exception being raised, the termination point varying with what diagnostic code is present. The termination point appears to be...
3
by: JezB | last post by:
I want to clear some specific Session variables when the user closes a page. On my page I have a "return to ..." button which navigates back to the parent page from which it was invoked - under the...
669
by: Xah Lee | last post by:
in March, i posted a essay “What is Expressiveness in a Computer Language”, archived at: http://xahlee.org/perl-python/what_is_expresiveness.html I was informed then that there is a academic...
8
by: aruna | last post by:
to write a c program to find the roots of the equation using bisection method that too using array or pointers
9
by: ehabaziz2001 | last post by:
I am facing that error message with no idea WHY the reason ? "Abnormal program termination" E:\programs\c_lang\iti01\tc201\ch06\ownarr01o01 Enter a number : 25 More numbers (y/n)? y...
9
by: uidzer0 | last post by:
Hey everyone, Taken the following code; is there a "proper" or dynamic way to allocate the length of line? #include <stdio.h> #include <errno.h> int main(int argc, char **argv) { FILE *fp;
0
by: vsankar9 | last post by:
It's an Service Contracts From CRM. I need termination amount for who's the customer is terminated . End date - 15-DEC-2007 Termination as of date - 15-MAR-2007 Rate - 1000 (monthly rate ) ...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
1
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: jfyes | last post by:
As a hardware engineer, after seeing that CEIWEI recently released a new tool for Modbus RTU Over TCP/UDP filtering and monitoring, I actively went to its official website to take a look. It turned...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shllpp 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.