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);
大概意思应该是:如果调用Native.free()方法去释放一个已经被释放的内存,那么将会出错。
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时,会报错,并且程序异常退出,错误代码如下(目前看不懂这东西):
#
# A fatal error has been detected by the Java Runtime Environment:
#
# EXCEPTION_ACCESS_VIOLATION (0xc0000005) at pc=0x0000000076daa12f, pid=10008, tid=0x00000000000009e8
#
# JRE version: Java(TM) SE Runtime Environment (8.0_102-b14) (build 1.8.0_102-b14)
# Java VM: Java HotSpot(TM) 64-Bit Server VM (25.102-b14 mixed mode windows-amd64 compressed oops)
# Problematic frame:
# C [ntdll.dll+0x5a12f]
#
# Failed to write core dump. Minidumps are not enabled by default on client versions of Windows
#
# An error report file with more information is saved as:
# F:\java development\Eclipse workspace\test\hs_err_pid10008.log
#
# If you would like to submit a bug report, please visit:
# http://bugreport.java.com/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
但目前还有个问题:我之前写的一个程序,只是用Memory对象分配了内存,但是并没有用本文说的方法去手动释放内存(等GC时自动去执行),程序运行一段时间后仍然出现了程序闪退的问题,好像错误代码也是跟上面一样,搞不懂为啥。