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时自动去执行),程序运行一段时间后仍然出现了程序闪退的问题,好像错误代码也是跟上面一样,搞不懂为啥。
本文详细介绍了Java Native Access (JNA) 中Memory对象如何管理直接内存。解释了Memory对象的finalize()方法如何确保垃圾回收时释放内存,以及如何手动释放内存以避免内存泄漏。

3010

被折叠的 条评论
为什么被折叠?



