When someone is making bindings from a C library to Java (or any other garbage-collected language without destructors that are guaranteed to run), how do they deal with proper deallocation of non-garbage-collected memory?
EDIT: What I'm thinking of (I know this isn't explicitly state in my original question) is when a piece of non-gc'ed memory holds references to other non-gc'ed resources that need to be freed when that object is freed. For example, if you hav开发者_运维知识库e a non-gc'ed linked list node that is the head of a long list of such nodes and you want to have the gc system clean it up automatically eventually, how do you set that up?
In java, you have the finalize() concept. You can free the C-memory there.
However, probably a better way is to use PhantomReferences along with a ReferenceQueue. You can extend the PhantomReference class so that it holds some id or pointer or whatever to the C-side memory you need to free. When it is enqueued in the ReferenceQueue, you can then free the C-side memory that this id points to - the Java object is guaranteed to not be in existence "in Java" anymore.
They typically provide APIs to create and release a reference.
For example, Java's Native Interface provides global references that allow pinning an Java object in memory until the C program is done with it via NewGlobalRef
and DeleteGlobalRef
NewGlobalRef
Creates a new global reference to the object referred to by the obj argument. The obj argument may be a global or local reference. Global references must be explicitly disposed of by callingDeleteGlobalRef()
and it also provides local refs that only last as long as Java has handed over control to C for:
Local references are valid for the duration of a native method call. They are freed automatically after the native method returns.
The JVM embedding API provides a similar mechanism which allows pinning of an object in memory until the C program determines it is done with it.
Python's C extension API provides a similar API to the JNI.
A borrowed reference can be changed into an owned reference by calling
Py_INCREF()
.The owner of a reference is responsible for calling
Py_DECREF()
when the reference is no longer needed.
The python names reflect the fact that python uses reference counting* but the API is basically the same as that in JNI which is based on a non-ref counting garbage collector -- you have one function that pins a region of memory managed by the interpreter and one that releases a previously pinned region back to the interpreter.
* - python isn't a true ref-counting approach. From the same page "While Python uses the traditional reference counting implementation, it also offers a cycle detector that works to detect reference cycles."
When using bindings with languages such as Java, the other language machine holds reference counters for each allocated object. The API should give methods to increase or decrease theses counters to indicate the machine that your C program holds reference to the other machine objects. If C program does not have references to a given object, the reference counter may reach 0 and the other language machine will be free to garbage collect it. However, you may not be able to ask the machine to release a given object.
精彩评论