JNA释放Memory对象分配的内存

JNA释放Memory对象分配的内存

 

分类专栏: java开发 文章标签: JNA

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()方法:

 
  1. /** Properly dispose of native memory when this object is GC'd. */

  2. @Override

  3. protected void finalize() {

  4. dispose();

  5. }

  6.  
  7. /** Free the native memory and set peer to zero */

  8. protected synchronized void dispose() {

  9. try {

  10. free(peer);

  11. } finally {

  12. peer = 0;

  13. allocatedMemory.remove(this);

  14. }

  15. }

  16.  
  17. protected static void free(long p) {

  18. // free(0) is a no-op, so avoid the overhead of the call

  19. if (p != 0) {

  20. Native.free(p);

  21. }

  22. }

其中,Native.free()方法如下:

 

 
  1. /**

  2. * Call the real native free

  3. * @param ptr native address to be freed; a value of zero has no effect,

  4. * passing an already-freed pointer will cause pain.

  5. */

  6. public static native void free(long ptr);

大概意思应该是:如果调用Native.free()方法去释放一个已经被释放的内存,那么将会出错。

 

Pointer类中的方法:

 
  1. /** Read the native peer value. Use with caution. */

  2. public static long nativeValue(Pointer p) {

  3. return p == null ? 0 : p.peer;

  4. }

  5.  
  6. /** Set the native peer value. Use with caution. */

  7. public static void nativeValue(Pointer p, long value) {

  8. p.peer = value;

  9. }

 

由上面的源码可知,当Memory被GC掉时,会自动去释放分配的直接内存(前提是要执行GC)。为了避免过多的使用Memory分配直接内存而导致直接内存空间不足,可以手动释放掉Memory分配的内存,方法如下:

 

 
  1. Pointer p = new Memory(1024 * 1024);

  2. long peer = Pointer.nativeValue(p);

  3. Native.free(peer);//手动释放内存

  4. 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时自动去执行),程序运行一段时间后仍然出现了程序闪退的问题,好像错误代码也是跟上面一样,搞不懂为啥。

上一篇:译:npm 7已经可以使用了


下一篇:WIN10 Ubuntu20.04 Fabric 2.0安装部署