跨语言通信——GC

148 阅读1分钟

GC与native指针

在gc的时候释放native指针。有几个方案,基本是finalize和PhantomReference。

Bitmap

在8.0以后,Bitmap的真实数据是存在native的,所以要有一个绑定到java对象,监听gc并释放native内存的操作。 这里采用的是sun.misc中提供的一个PhantomReference的方式。代码路径如下:

  1. Bitmap.java#createBitmap
  2. Bitmap.cpp#Bitmap_creator
  3. Bitmap.cpp#createBitmap,这里主要是反掉回Bitmap.java的构造函数,用的是LocalRef,也就是说完全不影响gc
  4. Bitmap.java#<init>,关键代码是
NativeAllocationRegistry registry;
        if (fromMalloc) {
            registry = NativeAllocationRegistry.createMalloced(
                    Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);
        } else {
            registry = NativeAllocationRegistry.createNonmalloced(
                    Bitmap.class.getClassLoader(), nativeGetNativeFinalizer(), allocationByteCount);
        }
        registry.registerNativeAllocation(this, nativeBitmap);
  1. NativeAllocationRegistry.java#<init>
  2. NativeAllocationRegistry.java#registerNativeAllocation,几个关键点:sun.misc.Cleaner(hidden api)、registerNativeAllocation、Reference#reachabilityFence
  • registerNativeAllocation,会一层层通知到gc::Heap,看起来是通过native内存过大触发gc
  • Reference#reachabilityFence:docs.oracle.com/javase/9/do…
  • Cleaner: cleaner是PhantomReference的一个子类,只是多保存了一个static Cleaner队列,以及释放时的回调方法(thunk)。而真正调用点在Reference#tryHandlePending,在加入到referenceQueue(如果有)前会调用thunk以完成资源释放