Click to See Complete Forum and Search --> : Stack overflow when constructing too many classes from c++


michal_l
September 23rd, 1999, 11:35 AM
Hi.
I have a problem with java-JNI.
(I'm using jdk1.2 on solaris).

I wrote a java application that calls a native (C++) method once.
This native method executes "forever" and perform callbacks to a java
constructor,and constructs new objects. It works ok for the ~3000 first
callbackes, and
then crashes with the exception:
Exception in thread "main" java.lang.stackOverflowError

I'll give you a simple example which,
I hope, will make my point clear:

This is the main java class:
====================
public class JavaLea extends Object
{
public native void init();

static
{
System.loadLibrary("leaclient");
}

public static void main(String argv[])
{
JavaLea javaLea=new JavaLea();
javaLea.init();
}//main
}


This is the native method "init"
It constructs new objects of the type "RecordRecievedEvent".
The constructor is an empty constructor which can't do any harm.
==================================================
JNIEXPORT void JNICALL Java_JavaLea_init
(JNIEnv *jenv, jobject jobj)
{
printf("begin\n");
jclass RecordRecievedEvent = jenv->FindClass("RecordRecievedEvent");
jmethodID resultConstructor
=jenv->GetMethodID(RecordRecievedEvent,"<init>","()V");
for (int i=1;true;i++)
{
jobject recordRecievedEvent
=jenv->NewObject(RecordRecievedEvent,resultConstructor);
if (jenv->ExceptionOccurred())
{
printf("!!!NewObject Exception:");
jenv->ExceptionDescribe();
jenv->ExceptionClear();
break;
}//if
delete recordRecievedEvent;
}//for
}

!!! I added the following lines to the RecordRecievedEvent's
constructor:
========================================================
System.gc();

Runtime runtime=Runtime.getRuntime();
System.out.println("totalMem:"+runtime.totalMemory()+
" freeMem:"+runtime.freeMemory());

And the free memory just go down and down till the application crashes.
Did I forget to free some memory?
I really want to know what is the right way to construct a java object
from c++.

Thanks,
Michal.

ddevienne
September 23rd, 1999, 02:23 PM
jobject resources are quite sparse (including the one derived from jobject like jclass, jarray, etc...). Your loop allocates new jobject resources in the JVM for each iteration, although you have only a single variable in your code. Once you create an object (and hand it out to someone in the Java side, which I didn't see you do in your code), you must release the jobject resource that was returned to you using DeleteLocalRef. Buy the excellent book "The Java Native Interface" from Liang for more info. Also, you can't do "delete obj;"!!! the jobject's type is a pointer, but it's value is not... it correspond to an element index in a JVM table!!! You cannot delete object in Java. You just stop referencing them (using DeleteLocalRef() for example), and the garbage collector will dispose of them. If your system has only one CPU, the GC thread may not be scheduled to run because of your tight loop. There's also a flag to Java to force GC (by default, the JVM is pretty lazy and doesn't do much GC).
I hope this helps. --DD

jaravind
November 23rd, 1999, 05:09 PM
Hi Michel,

I face the same problem.

My program is a trap processor with the Native code receiving
traps & passing them to Java.Every time a trap is received
a new Java object gets created.

It works fine for ~7000 objects & then starts throwing
StackOverflow exception.

In my JNI code after creating a Java object,I immediately
delete the local reference.
....
jobject jobj = (jenv)->NewObjectA(...);
(jenv)->DeleteLocalRef(jobj);
...

At the Java side ,after processing traps I explicitly
make these objects NULL,so that they are garbage collected.

Even after this error,My Java Server is able to create other
objects( non JNI created) & works fine.

I tried starting the JRE with -verbose option.After the
above stated problem occurs it starts printing:
...
[Signaling Error: error message pending]
...
for every trap received.

Thanks,
Aravind.