_Ndugu_
asked on
How do i make multiple sequential calls to jvm from same process
Hi I have 2 questions
1. I have tried to make multiple calls to jni_CreateJavaJVM and DestroyJVM within a C function.
This only works when I call the C function several times from a shellscript.
I want to call the function several times from a C process though, but the CreateJVM fails with the error:
the Java HotSpot Server VM does not support Signal-chaining. (I believe there's a known problem unloading the JVM when DestroyJVM is called) so...
I have now made the JNIEnv var static and initialised it to NULL. I test to see if it's null now before creating the JVM - it gets past this step now but fails at NewStringUTF.... any ideas? see attached code. (I have commented and uncommented DestroyJVM but it's made no difference)
here's the backtrace:
( 0) 0xd6951894 report_and_die__7VMErrorFv + 0x17c [/opt/java1.4/jre/lib/PA_R ISC2.0/ser ver/libjvm .sl]
( 1) 0xd6852614 JVM_handle_hpux_signal__Q2 _2os4HpuxS FiP9__sigi nfoPvT1 + 0x2bc [/opt/java1.4/jre/lib/PA_R ISC2.0/ser ver/libjvm .sl]
( 2) 0xd684dad4 signalHandler__Q2_2os4Hpux SFiP9__sig infoPv + 0x4c [/opt/java1.4/jre/lib/PA_R ISC2.0/ser ver/libjvm .sl]
( 3) 0xc020bfe0 _sigreturn [/usr/lib/libc.2]
( 4) 0xd66fbe34 jni_NewStringUTF__FP7JNIEn v_PCc + 0x64 [/opt/java1.4/jre/lib/PA_R ISC2.0/ser ver/libjvm .sl]
( 5) 0xc960c7b4 callStaticInvokeMethod__11 CJavaLoade rFPcN41 + 0xaac [/oo_dgfqausr2/JavaCAPI/CA PI_svnJVM/ lib/libjar .sl]
( 6) 0xc9609344 invoke + 0x1ae0 [/oo_dgfqausr2/JavaCAPI/CA PI_svnJVM/ lib/libjar .sl]
( 7) 0xc374b020 getBundlePlans + 0x4cc [../libvc.sl]
( 8) 0x00006710 call_getBundlePlans__Fv + 0xd0 [./testVCCAPI]
( 9) 0x00009bd0 main + 0x2a4 [./testVCCAPI]
(10) 0xc01434d0 _start + 0xc0 [/usr/lib/libc.2]
(11) 0x000052f0 $START$ + 0x178 [./testVCCAPI]
runVCTests.sh[21]: 1756 Abort(coredump)
2. - my second question is ... how can I catch the JVM errors?... my catch(...) doesn't seem to catch any of them and the jvm crashes
Thanks in advance
Ndugu
1. I have tried to make multiple calls to jni_CreateJavaJVM and DestroyJVM within a C function.
This only works when I call the C function several times from a shellscript.
I want to call the function several times from a C process though, but the CreateJVM fails with the error:
the Java HotSpot Server VM does not support Signal-chaining. (I believe there's a known problem unloading the JVM when DestroyJVM is called) so...
I have now made the JNIEnv var static and initialised it to NULL. I test to see if it's null now before creating the JVM - it gets past this step now but fails at NewStringUTF.... any ideas? see attached code. (I have commented and uncommented DestroyJVM but it's made no difference)
here's the backtrace:
( 0) 0xd6951894 report_and_die__7VMErrorFv
( 1) 0xd6852614 JVM_handle_hpux_signal__Q2
( 2) 0xd684dad4 signalHandler__Q2_2os4Hpux
( 3) 0xc020bfe0 _sigreturn [/usr/lib/libc.2]
( 4) 0xd66fbe34 jni_NewStringUTF__FP7JNIEn
( 5) 0xc960c7b4 callStaticInvokeMethod__11
( 6) 0xc9609344 invoke + 0x1ae0 [/oo_dgfqausr2/JavaCAPI/CA
( 7) 0xc374b020 getBundlePlans + 0x4cc [../libvc.sl]
( 8) 0x00006710 call_getBundlePlans__Fv + 0xd0 [./testVCCAPI]
( 9) 0x00009bd0 main + 0x2a4 [./testVCCAPI]
(10) 0xc01434d0 _start + 0xc0 [/usr/lib/libc.2]
(11) 0x000052f0 $START$ + 0x178 [./testVCCAPI]
runVCTests.sh[21]: 1756 Abort(coredump)
2. - my second question is ... how can I catch the JVM errors?... my catch(...) doesn't seem to catch any of them and the jvm crashes
Thanks in advance
Ndugu
char* callStaticJavaMethod(char* className, char* callMethodName, char * in_classpath, char *jvmOptions, char* xmlArg)
throw(JavaException)
{
char* response = NULL;
const char *resultCStr;
char* newString = NULL;
char classpath[_MAX_CLASSPATH_LEN_+1];
bool argStrAllocated = false;
jstring argStr; //Defined here so it can be freed by the catch if required.
bool jvmLoaded = false;
cout << endl
<< endl
<< ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" << endl
<< endl
<< "[" << getDateTime() << "] CJavaLoader::callStaticInvokeMethod(\""
<< className << "\", \"" << callMethodName << "\", \"" << xmlArg << "\") - Started"
<< endl;
char methodName[] = "callStaticInvokeMethod(char*, char*, char*, char *, char*)";
/******** JNI specific *************/
static JNIEnv *jniEnv = NULL; //pointer to native method interface
JavaVM *jvm = NULL; // denotes a Java VM
JavaVMInitArgs vm_args;
JavaVMOption *options = NULL;
jint res;
vm_args.version = JNI_VERSION_1_4;
/******** JNI specific *************/
char* umclasspath = NULL;
try {
int inumOptions =0;
if (xmlArg == NULL || strlen(xmlArg) < 1){
throw JavaException(_JVM_NOT_INITIALISED_, (char*)"");
}
if ( jniEnv == NULL){
cout << "jniEnv is NULL"<< endl << endl;
cout.flush();
if (!(jvmOptions && in_classpath && *jvmOptions && *in_classpath)){
cerr << "jvm.runtime.options and jvm.classpath must be set in properties file " << endl;
throw JavaException(_JVM_NOT_INITIALISED_, (char*)"ERROR creating JVM. xmlArg is null");
}
// intialise jvm
char *copy = new char[strlen(jvmOptions) + 1];
memset(copy, '\0', strlen(jvmOptions) + 1);
strncpy(copy, jvmOptions, strlen(jvmOptions));
inumOptions =getNumJVMOptions(copy)+1; // for the classpath
if (copy) delete[] copy;
copy = NULL;
cout << "==================creating options===================="<< endl << endl;
options = new JavaVMOption[inumOptions];
int optionCount = 0;
options[optionCount].optionString = in_classpath;
char *token;
copy = new char[strlen(jvmOptions) + 1];
memset(copy, '\0', strlen(jvmOptions) + 1);
strncpy(copy, jvmOptions, strlen(jvmOptions));
token = strtok(copy, " "); //Assumes ' ' as delimiter
while (token && *token) {
options[++optionCount].optionString = token;
token = strtok(NULL, " ");
}
if (copy) delete [] copy;
copy = NULL;
token = NULL;
vm_args.options = options;
vm_args.nOptions = inumOptions;
vm_args.ignoreUnrecognized = JNI_TRUE;
cout << "vm_args.nOptions = " << vm_args.nOptions << endl;
for (int i = 0; i < vm_args.nOptions ; i++){
cout << "option["<<i << "] = [" << vm_args.options[i].optionString << "]" << endl ;
}
/******************** CREATE JVM ********************/
res = JNI_CreateJavaVM(&jvm, (void **) &jniEnv,&vm_args);
if (ExceptionRaised(jniEnv) || res != 0){
// if (res != 0) {
cerr << "JNI_CreateJavaVM failed %d\n" << res << "." << endl;
delete [] options;
throw JavaException(_JVM_NOT_INITIALISED_, (char*)"ERROR creating JVM");
}
cout << "==================deleting options===================="<< endl << endl;
cout.flush();
if (options) delete [] options;
jvmLoaded = true;
}
argStrAllocated = false;
cout << "NewStringUTF"<< endl << endl;
cout.flush();
argStr = jniEnv->NewStringUTF(xmlArg);
if (argStr == NULL)
throw JavaException(_JVM_NOT_INITIALISED_, (char*)"ERROR creating UTF String");
if (ExceptionRaised(jniEnv)){
//if (argStr == 0){
LOG_OUT << "ERROR creating JVM, OUT OF MEMORY"<< endl;
throw JavaException(_JVM_NOT_INITIALISED_, (char*)"ERROR creating JVM, OUT OF MEMORY");
}
argStrAllocated = true;
cout << "FindClass"<< endl << endl;
cout.flush();
jclass callingClass = jniEnv->FindClass(className);
if (ExceptionRaised(jniEnv)){
//if (callingClass == 0) { //Unable to find the class
LOG_OUT << "Unable to find the class [" << className
<< "] along the classpath [" << classpath << "]" << endl;
throw JavaException(_CLASS_NOT_FOUND_, (char*)"Class not found");
}
cout << "GetStaticMethodID"<< endl << endl;
cout.flush();
jmethodID methodID = jniEnv->GetStaticMethodID(callingClass, callMethodName, "(Ljava/lang/String;)Ljava/lang/String;");
if (ExceptionRaised(jniEnv)){
//if (methodID == 0) { //Method does not exist in the specified class
LOG_OUT << "The method [" << callMethodName << "] does not exist in class ["
<< className << "]" << endl;
throw JavaException(_METHOD_NOT_FOUND_, (char*)"Method not found");
}
cout << "CallStaticObjectMethod"<< endl << endl;
cout.flush();
jstring resultJStr = (jstring)jniEnv->CallStaticObjectMethod(callingClass, methodID, argStr);
cout << "after CallStaticObjectMethod" << endl;
if (ExceptionRaised(jniEnv)){
LOG_OUT << "ERROR invoking java method " << callMethodName << " in JVM " << endl;
throw JavaException(_GENERIC_ERROR, (char*)"ERROR invoking java method in JVM");
}
//Deallocate the argument string
jniEnv->DeleteLocalRef(argStr);
if (ExceptionRaised(jniEnv))
{
LOG_OUT << "ERROR deleting jstring in JVM " << endl;
throw JavaException(_GENERIC_ERROR, (char*)"ERROR deleting jstring in JVM");
}
jboolean isCopy;
resultCStr = jniEnv->GetStringUTFChars(resultJStr, &isCopy);
if (isCopy == JNI_TRUE){
cout <<" resultJStr [" << resultJStr << "]" << endl;
cout <<" resultCStr [" << resultCStr << "]" << endl;
response = new char[strlen(resultCStr)+1];
memset(response, '\0', strlen(resultCStr)+1);
strncpy(response, resultCStr, strlen(resultCStr));
jniEnv->ReleaseStringUTFChars(resultJStr, resultCStr);
resultCStr = NULL;
}
else{
LOG_OUT <<"ERROR. No xmlString returned from service" << endl;
throw JavaException(_GENERIC_ERROR, (char*)"ERROR. No xmlString returned from service");
}
jniEnv->DeleteLocalRef(resultJStr);
if (ExceptionRaised(jniEnv)){
LOG_OUT << "ERROR deleting jstring in JVM " << endl;
throw JavaException(_GENERIC_ERROR, (char*)"ERROR deleting jstring in JVM");
}
}
/* catch(JavaException e){
}*/
catch (...) {
LOG_OUT << endl << endl
<< "XXXXXXXXXXXXXXXXXX" << endl
<< "\tException caught" << endl << "XXXXXXXXXXXXXXXXXX"
<< endl << endl;
if (!response)
response = new char[strlen(_ERROR_IN_JAVA_CALL_)+1];
memset(response, '\0', strlen(_ERROR_IN_JAVA_CALL_)+1);
strncpy(response, _ERROR_IN_JAVA_CALL_, strlen(_ERROR_IN_JAVA_CALL_));
LOG_OUT << "Java call finished." << endl
<< "\tResult was [" << _ERROR_IN_JAVA_CALL_ << "]" << endl
<< endl
<< "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl
<< endl;
if (resultCStr)
resultCStr = NULL;
if (argStrAllocated)
jniEnv->DeleteLocalRef(argStr);
if (jvmLoaded){
if (jvm->DestroyJavaVM() != 0){
LOG_OUT << "DestroyJVM method did not unload the JVM. Contact Development" << endl;
throw JavaException(_GENERIC_ERROR, (char*)"ERROR deleting JVM ");
}
}
}
/******************** DESTROY JVM ********************/
if (jvmLoaded){
if (jvm->DestroyJavaVM() != 0){
LOG_OUT << "DestroyJVM method did not unload the JVM. Contact Development" << endl;
throw JavaException(_GENERIC_ERROR, (char*)"ERROR deleting JVM ");
}
}
LOG_OUT << "Java call finished." << endl
<< "\tResult was [" << response << "]" << endl
<< endl
<< "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" << endl
<< endl;
return response;
}
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Here's what I've done... put JNIEnv, JavaVM etc.. into a C++ class ClassLoader
I declare this class as static and intialise it to null from my C function.
static ClassLoader classLoader = NULL;
if (classLoader== NULL)
classLoader = new ClassLoader();
Then for all processes (not just the one that grabbed ClassLoader first):
AttachCurrentThread
--call findClass, callstaticMethod etc
DetachCurrentThread after callstaticMethod.
The DestroyJVM call is in the ClassLoader destructor.
---
This now creates the JVM and I can trace through the java calls, but now I'm having problems with the java methods parsing some xml ........ this is the error:
Exception [java.lang.Exception: javax.xml.parsers.Document
I can see this class in a weblogic.jar file that's in the same location as the jar that's calling it?
should I post this elsewhere now the previous problem is sorted or is it somewhat related?
thanks