File APIs for Java Developers
Manipulate DOC, XLS, PPT, PDF and many others from your application.
http://aspose.com/file-tools
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic

Problem with ReleaseStringUTFChars (Crash )

 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi I am using the below stated code in JNI:

It fails if any of the values in pParams is large... And it doesn't crashes always but in most of the cases when the large value is passed.


**************

for (int i = 0; i < paramCount; i++) {s
jobjectArray param = (jobjectArray)pEnv->GetObjectArrayElement(pParams, i);
jstring str1 = (jstring)pEnv->GetObjectArrayElement(param, 0);
jstring str2 = (jstring)pEnv->GetObjectArrayElement(param, 1);
const char *name = pEnv->GetStringUTFChars(str1, 0);
const char *value = pEnv->GetStringUTFChars(str2, 0);

cout <<name <<"=" <<value <<endl;

returnVal = PSMsgSetField(hContext, name, value);

if (returnVal != PSMSG_OK) {
cout << "Error in SetField: " << returnVal << endl;
}

pEnv->ReleaseStringUTFChars(str1, name);

pEnv->ReleaseStringUTFChars(str2, value);
}

returnVal = PSMsgProcessMessage(hContext, &replyOption);
pEnv->ReleaseStringUTFChars(pTopic, topic);

pEnv->ReleaseStringUTFChars(pMsgName, msgName);

pEnv->ReleaseStringUTFChars(pActivity, activity);

***************
[ May 14, 2006: Message edited by: Andy Smith ]
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24204
34
Chrome Eclipse IDE Mac OS X
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're not checking for NULL or for exceptions after calling GetStringUTFChars; it can throw OutOfMemoryError and return NULL. Probably that's what's happening.
[ May 12, 2006: Message edited by: Ernest Friedman-Hill ]
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank For ur reply.

I noticed one thing..

"param" is not released using "ReleaseStringUTFChars" in the loop...

Could that be the reason ?

Should I add something like "pEnv->ReleaseStringUTFChars(param, pParams);"

I am not much aware of the JNI ...
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24204
34
Chrome Eclipse IDE Mac OS X
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Originally posted by Andy Smith:
T
Could that be the reason ?


No.

Please check the return value of getStringUTFChars for NULL -- I'm telling you, that's the problem. Then later, you're trying to release NULL and it's crashing.
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi I got ur point...

U want to say that some exception is occuring (OutOfMemmory) and thats y the variable is null

OK by adding null check, I would be able to avoid this prob..But still the main problem is why the exception OutOfmemry to wat ever...

This fail 90 % of times...
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24204
34
Chrome Eclipse IDE Mac OS X
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
You're getting OutOfMemoryErrors because you're running out of memory. This really doesn't seem to me to be so difficult to understand. Remember that you can increase the size of the Java heap with command-line switches, and that may be necessary here.
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I am sorry for askin u a bad question.. but I really have never worked on C++.. and I need to send this file to some one to compile ang give me back so I just want to be sure of How to add the Null Check u r talking abt...


Could you please help talking the example of codeI ahve posted in my earlier message
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24204
34
Chrome Eclipse IDE Mac OS X
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
If a JNI routine wants to throw an exception, it can't really throw it in C, of course, since C has no exceptions. It just stores the exception object in a special place where you can check for it. Many JNI routines will also return a special value (often NULL, or 0) to indicate that there was an exception. If you see a NULL return, you know there was an exception; you should clean up as best you can, freeing memory as needed, and then return; Java will see that stored exception and throw it.

So, for example, you can just do something like



This kind of error checking adds a lot of code, but unfortunately it's necessary.
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank You Sir...

I will change my code to this :

*****************************************
for (int i = 0; i < paramCount; i++) {
jobjectArray param = (jobjectArray)pEnv->GetObjectArrayElement(pParams, i);
jstring str1 = (jstring)pEnv->GetObjectArrayElement(param, 0);
jstring str2 = (jstring)pEnv->GetObjectArrayElement(param, 1);
const char *name = pEnv->GetStringUTFChars(str1, 0);
const char *value = pEnv->GetStringUTFChars(str2, 0);

cout <<name <<"=" <<value <<endl;

returnVal = PSMsgSetField(hContext, name, value);

if (returnVal != PSMSG_OK) {
cout << "Error in SetField: " << returnVal << endl;
}

if (name == 0){
pEnv->ReleaseStringUTFChars(str1, name);
)

if (name == 0){
pEnv->ReleaseStringUTFChars(str2, value);
}
}

returnVal = PSMsgProcessMessage(hContext, &replyOption);

if (topic == 0) {
pEnv->ReleaseStringUTFChars(pTopic, topic);
}

if (msgName == 0) {
pEnv->ReleaseStringUTFChars(pMsgName, msgName);
}

if (activity == 0 ) {
pEnv->ReleaseStringUTFChars(pActivity, activity);
}

*********************************************

This should be ok now ?

One more thing, I have also used
***************************************
returnVal = PSMsgSetField(hContext, name, value);
**************************************

Do I need some sort of checking here also ?
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24204
34
Chrome Eclipse IDE Mac OS X
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
My goodness, no; I'm sorry, but this is all wrong!

The idea is that if a method fails, then you need to release all resources that you successfully allocated before the failure, and then return. And of course, you need to check for successful allocation before you use a resource. In the code you've shown, you allocate "name" and "value", then use them without checking if they're OK. Then you check if they're OK, and free them only if they're not; this is really all in all the exact opposite of what you need to do! Instead, you want to do what I showed in my example, all of it before calling PSMsgSetField. If name or value is 0, then you should not call PSMsgSetField, but instead clean up and return.

Note in my example that if we fail to allocate "name", then we just return. And if we fail to allocate "value", then we need to free "name", since if we got here then we successfully allocated "name" previously -- and then after cleaning up "name", we return.

If, on the other hand, "value" is nonzero, then everything is OK, and we can call PSMsgSetField. Then, continuing on, we need to check every other call to GetStringUTFChars for a zero return, and clean up any strings that we previously allocated, and abort the routine.

Remember never pass to a zero char* to ReleaseStringUTFChars!
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I really appreciate your really fast responses...

Ok let me try again, I hope it should be ok now

*****************************************
for (int i = 0; i < paramCount; i++) {
jobjectArray param = (jobjectArray)pEnv->GetObjectArrayElement(pParams, i);
jstring str1 = (jstring)pEnv->GetObjectArrayElement(param, 0);
jstring str2 = (jstring)pEnv->GetObjectArrayElement(param, 1);
const char *name = pEnv->GetStringUTFChars(str1, 0);
const char *value = pEnv->GetStringUTFChars(str2, 0);

cout <<name <<"=" <<value <<endl;

if ((name != 0) && (value != 0)) {
returnVal = PSMsgSetField(hContext, name, value);
}

if (returnVal != PSMSG_OK) {
cout << "Error in SetField: " << returnVal << endl;
}

if (name != 0) {
pEnv->ReleaseStringUTFChars(str1, name);
)

if (value != 0) {
pEnv->ReleaseStringUTFChars(str2, value);
}
}

returnVal = PSMsgProcessMessage(hContext, &replyOption);

if (topic != 0) {
pEnv->ReleaseStringUTFChars(pTopic, topic);
}

if (msgName != 0) {
pEnv->ReleaseStringUTFChars(pMsgName, msgName);
}

if (activity != 0 ) {
pEnv->ReleaseStringUTFChars(pActivity, activity);
}

*****************************************


Please provide your commnets
[ May 14, 2006: Message edited by: Andy Smith ]
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24204
34
Chrome Eclipse IDE Mac OS X
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is much closer, but you're still cutting corners. Whenever you make a single, individual JNI call that might fail by throwing an exception -- and the JNI documentation lists the exceptions that each method might throw -- you must check for an exception and deal with immediately. You have two choices: you can clean up and then return, or you can call env->ClearException() and continue. The JNI spec says that the result of calling many JNI routines while there is a pending exception is undefined; in practice, this often means that if you do it, you'll get a crash. So if you're going to continue, you must clear the exception.

I see now that all this code is in a loop, so you probably don't want to just return if there's a problem, but rather go ahead to the next iteration of the loop; you might use the "continue" statement, which is just like Java's; clean up and continue.
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thanx Again

How abt this ?

****************************************************************************
// set all input fields
for (int i = 0; i < paramCount; i++) {
jobjectArray param = (jobjectArray)pEnv->GetObjectArrayElement(pParams, i);
jstring str1 = (jstring)pEnv->GetObjectArrayElement(param, 0);
jstring str2 = (jstring)pEnv->GetObjectArrayElement(param, 1);
const char *name = pEnv->GetStringUTFChars(str1, 0);
jth = pEnv->ExceptionOccurred ();
if (jth) {
printf ("There was an exception Getting Name \n");
pEnv->ExceptionDescribe ();
pEnv->ExceptionClear ();
}

const char *value = pEnv->GetStringUTFChars(str2, 0);
jth = pEnv->ExceptionOccurred ();
if (jth) {
printf ("There was an exception Getting Value \n");
pEnv->ExceptionDescribe ();
pEnv->ExceptionClear ();
}

cout <<name <<"=" <<value <<endl;
cout << "Before PSMsgSetField..." << endl;

returnVal = PSMsgSetField(hContext, name, value);
if (returnVal != PSMSG_OK) {
cout << "Error in SetField: " << returnVal << endl;
}

// Name
cout << "Releasing Name..." << endl;
if (name != 0) {
cout << "Name..." << endl;
pEnv->ReleaseStringUTFChars(str1, name);
}

jth = pEnv->ExceptionOccurred ();
if (jth) {
printf ("Exception Releasing Name \n");
pEnv->ExceptionDescribe ();
pEnv->ExceptionClear ();
}

// Value
cout << "Releasing Value..." << endl;
if (value != 0) {
cout << "Value..." << endl;
pEnv->ReleaseStringUTFChars(str2, value);
}

jth = pEnv->ExceptionOccurred ();
if (jth) {
printf ("Exception Releasing Value \n");
pEnv->ExceptionDescribe ();
pEnv->ExceptionClear ();
}
}

returnVal = PSMsgProcessMessage(hContext, &replyOption);

// Topic
cout << "Releasing Topic..." << endl;
if (topic != 0) {
cout << "Topic..." << endl;
pEnv->ReleaseStringUTFChars(pTopic, topic);
}

jth = pEnv->ExceptionOccurred ();
if (jth) {
printf ("Exception Releasing Topic \n");
pEnv->ExceptionDescribe ();
pEnv->ExceptionClear ();
}

// msgName
cout << "Releasing msgName" << endl;
if (msgName != 0) {
cout << "msgName..." << endl;
pEnv->ReleaseStringUTFChars(pMsgName, msgName);
}

jth = pEnv->ExceptionOccurred ();
if (jth) {
printf ("Exception Releasing msgName \n");
pEnv->ExceptionDescribe ();
pEnv->ExceptionClear ();
}

// activity
cout << "Releasing activity" << endl;
if (activity != 0) {
cout << "activity..." << endl;
pEnv->ReleaseStringUTFChars(pActivity, activity);
}
jth = pEnv->ExceptionOccurred ();
if (jth) {
printf ("Exception Releasing Activity \n");
pEnv->ExceptionDescribe ();
pEnv->ExceptionClear ();
}

****************************************************************************
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hi

I have executed the application with the changes, still facing the same problem..

It is while releasing the "Value" and the size of the value is more then 320 characters....


any idea ??
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have added this:-

// Value
cout << "Releasing Value..." << endl;
if ((str2!= NULL) && (str2 != 0) && (value != NULL) && (value != 0)) {
cout << "Value..." << endl;
pEnv->ReleaseStringUTFChars(str2, value);
}


It is going inside the loop, and fails i "Release..." when the length of the value is more then 350 Chars
[ May 15, 2006: Message edited by: Andy Smith ]
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24204
34
Chrome Eclipse IDE Mac OS X
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Fails in what way, and how do you know where in the code it is when it fails?
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have put some "Cout" statements, thats how I come to know where it fails...

I am using this in the form of dll.. I get a popup saying "Abnormal Program Termination" with the heading "VC++ Runtime Libratry Error"
 
Ernest Friedman-Hill
author and iconoclast
Marshal
Pie
Posts: 24204
34
Chrome Eclipse IDE Mac OS X
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Hmm. Well, what does PSMsgSetField do with "value"? Is the problem perhaps caused by the char* being freed without PSMsgSetField expecting it? Is PSMsgSetField expecting a shorter char*?
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
This is the signature of te method

MSGAPIFUNCTION PSMsgSetField(PSMSGHANDLE hContext,
LPCSTR lpcszFieldName,
LPCSTR lpcszValue);


Strange thing is that it works for the first time. Then Crashes the next time, and always works for the smaller size of the value.

It ONLY Runs for one time when the message length is > 320, May be this can give some idea
[ May 15, 2006: Message edited by: Andy Smith ]
 
Andy Smith
Ranch Hand
Posts: 239
  • 0
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I m using:-

const char *value = pEnv->GetStringUTFChars(str2, 0);

Should I try passing a jboolean as second parameter something like:

jboolean isCopy;
*value = (pEnv)->GetStringUTFChars(theString,&isCopy);

and releasing on the basis of isCopy...

What do u think ?


**************

jstring utf_str =
(jstring) env->GetObjectArrayElement(objArray, i);
const char* c = env->GetStringUTFChars(utf_str, &isCopy);
fprintf(stdout, "\t objArray[%d] = (%s)\n", i, c);
if (isCopy == JNI_TRUE) {
env->ReleaseStringUTFChars(utf_str, c);
}
env->DeleteLocalRef(utf_str);
*****************
Should I change code to look like this ?
1. Using isCopy .

2. Using DeleteLocalRef.


?
[ May 15, 2006: Message edited by: Andy Smith ]
  • Post Reply
  • Bookmark Topic Watch Topic
  • New Topic