Introduction to Using the Raw Native Interface
 In this topic

*Protecting Objects on the Stack

*Protecting Objects in Allocated Memory

*Calling Back To Java

 

Java & Native Code    PreviousRNINext
Introduction to Using the Raw Native Interface     Previous RNI Next

 


Garbage Collection Issues

These sections describe the issues associated with garbage collection.

Protecting Objects on the Stack

By default, garbage collection cannot occur while native code is executing (other threads that try to do any garbage collection will block until the thread in native code returns to Java). This is probably the most important issue as far as native code and garbage collection are concerned. The reason for this is so the VM can avoid conservative scanning of native stacks, which is often unreliable and can be a "bottleneck" to performance.

A lot of native code does some quick calculation and returns, so this isn't a problem. However, if the native code is going to perform some operation that takes some time, explicitly enable and disable garbage collection around the slow code.

Of course, enabling garbage collection means that any objects could move at any time, invalidating any pointers to those objects in native code. The simplest way to handle this is to inform the garbage collector of objects you're interested in before enabling garbage collection using a GCFrame() with GCFramePush(). Object pointers kept in a GCFrame will be automatically updated if the object gets moved. When you're done, you can inform the garbage collector using GCFramePop(). The following is a typical example.

    void some_java_method(HObject *phobj1Unsafe, HObject *phobj2Unsafe)
    {
        // Keep a structure with all the objects we're interested in.
        struct
        {
            HObject *phobj1Safe;
			HObject *phobj2Safe;
        } gc;
        
        // Declare a GCFrame;
        GCFrame gcf;         

        // Tell the garbage collector about our structure, it will initialize this
        // structure to null.
        GCFramePush(&gcf, &gc, sizeof(gc));

        // Set the object ptr.
        gc.phobj1Safe = phobj1Unsafe;
		gc.phobj2Safe = phobj2Unsafe;

        // It's now safe to enable garbage collection.
        GCEnable();

        // ...time passes...garbage collection occurs...objects move...

        // Disable gargbage collection so we can access objects safely.
        GCDisable();
         
        // If GC moved our object then gc.hobjSafe will have been automatically
        // updated.
        
        gc.phobj1Safe->x = 42;
		gc.phobj2Safe->y = 33;
         
        // We're done.
        GCFramePop(&gcf);
    }
        

Note

  • Garbage collection is disabled in between PrepareThreadForJava and UnprepareThreadForJava.
  • You must enable GC as many times as you disabled it.
  • Call GCFramePop() before returning from native code back in to Java.
  • GCFrames are "strong", in the sense that having an object in GCFrame is considered to be equivalent to having a reference to that object so it won't be released by the garbage collector.

Protecting Objects in Allocated Memory

GCFrames are ideal for protecting objects on the stack, but not in situations where you want to keep an object pointer longer than the lifetime of the function in global memory. For situations like this, use GCGetWeakPtr() and GCFreeWeakPtr() instead:

    HObject **pphobjSafe = NULL;
    
    void some_java_methodA(HObject *phobjUnsafe)
    {
        // Allocate a weak ptr that we want to use later.
        pphobjSafe = GCGetWeakPtr(phobjUnsafe);
    }

    void some_java_methodB()
    {
        // Use the weak ptr we saved previously.
        *pphobjSafe->x = 42;
        GCFreeWeakPtr(pphobjSafe);
    }

As their names imply, these APIs create "weak" pointers to objects so that they can be freed by the garbage collector if no more references exist. At this point, the weak pointer becomes automatically invalid: Do not call GCFreeWeakPtr() on it. If you know the object is not freed by the garbage collector, call GCFreeWeakPtr() when you no longer need to keep track of it.

Calling Back To Java

If you call back to Java from native code, garbage collection may automatically be enabled by the Virtual Machine if memory needs to be allocated. This means that any object pointers you want to use after the call must be protected, either in a GCFrame or tracked by a weak pointer.

Top © 1998 Microsoft Corporation. All rights reserved. Terms of use.