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时,会报错,并且程序异常退出。

原文地址:https://www.cnblogs.com/gmhappy/p/11864010.html