Java JNA (五)—— 释放Memory对象分配的内存
Java进程的内存包括Java NonHeap空间
、Java Heap空间
和Native Heap空间
。
JNA中的Memory对象是从Native Heap中分配空间。但java的GC是针对Java Heap空间设计的,当Java Heap空间不足时会触发GC,但Native Heap空间不够却不会触发GC。
所以,当Java Heap占用空间不大时,并不会GC掉Memory对象,也就不会执行finalize()方法从而释放分配的Native Heap空间。
参考: http://ayufox.iteye.com/blog/723896
Memory中的finalize()方法:
/** Properly dispose of native memory when this object is GC'd. */
@Override
protected void finalize() {
dispose();
}
/** Free the native memory and set peer to zero */
protected synchronized void dispose() {
try {
free(peer);
} finally {
peer = 0;
allocatedMemory.remove(this);
}
}
protected static void free(long p) {
// free(0) is a no-op, so avoid the overhead of the call
if (p != 0) {
Native.free(p);
}
}
其中,Native.free()方法如下:
/**
* Call the real native free
* @param ptr native address to be freed; a value of zero has no effect,
* passing an already-freed pointer will cause pain.
*/
public static native void free(long ptr);
Pointer类中的方法:
/** Read the native peer value. Use with caution. */
public static long nativeValue(Pointer p) {
return p == null ? 0 : p.peer;
}
/** Set the native peer value. Use with caution. */
public static void nativeValue(Pointer p, long value) {
p.peer = value;
}
由上面的源码可知,当Memory被GC掉时,会自动去释放分配的直接内存(前提是要执行GC)。为了避免过多的使用Memory分配直接内存而导致直接内存空间不足,可以手动释放掉Memory分配的内存,方法如下:
Pointer p = new Memory(1024 * 1024);
long peer = Pointer.nativeValue(p);
Native.free(peer);//手动释放内存
Pointer.nativeValue(p, 0);//避免Memory对象被GC时重复执行Nativ.free()方法
如果不调用最后一行代码
Pointer.nativeValue(p, 0);
则在GC时,会报错,并且程序异常退出。