CNI and garbage collection

Bryce McKinlay
Thu Jul 19 19:30:00 GMT 2001

"Marcus G. Daniels" wrote:

> I've got a Java class from which I generate headers using gcjh.  I'm
> using the -prepend and -add features to insert declarations for ivars
> types, and then the ivars themselves.  In a CNI native method I have
> some initialization code for setting up the C++ side of things.  The
> problem seems to be that garbage collection is moving my Java object,
> but the ivars aren't following.  I.e. if I disable garbage collection
> the program runs fine.

So, you're adding extra fields in the CNI header for a Java class? You can't do
that. The size of the object as seen by the java compiler vs C++ will not match.
"new" will be allocating space which is smaller than the real size of the object
and C++ will be overwriting memory which does not belong to the object. It is
probably just luck that it seems to work with the null GC.

The Boehm GC never moves objects.

> In the CNI documentation,
> it says that "The C++ compiler is smart enough to realize the class is
> a Java class, and hence it needs to allocate memory from the garbage
> collector."
> But what about the C++ objects inside of the Java object?  Is there a special
> way to allocate them?

Using "new" in C++ will use Java GC allocation (_Jv_AllocObject) if the class in
question is a Java type (declared within an `extern "java"' block). For all
other types, the regular C++ new implementation  is used, which means you have
to deallocate explicitly if you dont want memory leaks.

So how to keep a pointer, associated with a given class or object, to your
native object? One solution is to declare a field (in Java) of the type
gnu.gcj.RawData. This class is treated specially by the garbage collector, and
can be used for storing a pointer to some native, non-Java object. RawData
fields will not be marked by the GC, so you need to dealocate them explicitly
(perhaps from a finalizer).

Alternatively, if you dont want to have to do the explicit dealocation, you can
just create a special java.lang.Object field, and allocate your object using
_Jv_AllocBytes. This way the GC will still mark your native data but will know
not to expect a regular Java object.

Note however that the memory allocated with _Jv_AllocBytes is not itself scanned
for pointers, so you generally should not keep references to GC allocated
objects in there.


  [ bryce ]

More information about the Java mailing list