views:

180

answers:

2

Hi.

While I do my best to clean JNI objects to free native memory in the end of the usage, there are still some that hang around for a long time, wasting system native memory.

Is there any way to force the GC to give priority in collection of these JNI proxies?

I mean is there a way to cause GC to concentrate on a particular kind of object, namely the JNI proxies?

Thanks.

+1  A: 

If you are talking about memory (and, by extension, handles) allocated within native code, it is outside of the purview of the JVM's garbage collector - there is nothing it can do about it so you are on your own. If you don't release the memory in the native code when you are done, it will leak.

If you are referring to the Java objects through which you access the native code, they are perfectly normal objects which will be collected when they become unreachable.

If your native code must release resources before you let the Java object go, the Java object should have a dispose method of some sort which when called will release the native resources and invalidate the Java object from further use. Simply call the dispose method and let the object reference go.

Once last thing, I am aware of no way to unload a native library once loaded.

Software Monkey
Hi.I know this, just thought there is a way to force Java collect the pointers to native objects.
SyBer
I don't follow you - if you "know this", that memory allocated by native code is outside of the control of the Java garbage collector, why are you asking whether the garbage collector can do anything with pointer to natively allocated memory (which is what native objects are, and which it knows nothing about)?
Software Monkey
Hi.The question is whether there is a way to cause GC to concentrate on a particular kind of object, namely the JNI proxies.Regards.
SyBer
A: 

There's no way to make the GC "focus" on certain types of objects. I assume you clean up in the finalizer, and the finalizer is run when:

  • The object no longer reachable.
  • The GC decides to clean up the generation the JNI proxy is in.

This means that, in order to clean up the resources as fast as possible, you want to:

  • Reduce the scope of the references, so your program doesn't cling to them for an unnecessarily long time. Also, garbage collections are run more seldom for old objects, so there's a twofold reason to make sure they live as short a time as possible.
  • Add a manual clean-up method the client code can call once it's finished with a JNI proxy - don't just let the references dissipate and wait for the finalizer to be run.

Example:

class NativeResource {
    private static native long allocate();
    private static native void release(long handle);
    private final long handle;
    private boolean closed = false;
    public NativeResource(){
        handle = allocate();
    }
    /** Deallocates the native resources associated with this proxy. */
    public void close() { 
        if (closed) throw new IllegalStateException("Already closed");
        release(handle); 
        closed = true;
    }
    protected void finalize() throws Throwable {
        try { 
            if (!closed) release(handle);
        } finally {
            super.finalize();
        }
    }
}

// Usage:
NativeResource nr = new NativeResource();
try {
    // Use the resource for something
} finally {
    nr.close(); // Make sure resource is closed even after exceptions
}
gustafc