如果允许 JVM 在垃圾回收期间移动堆内存,那么垃圾回收如何不会导致 JNI 因移动指针而爆炸

If JVM is allowed to move heap memory during garbage collect then how does garbage collection not cause JNI to explode due to moving pointers?

本文关键字:移动 何不会 指针 JNI JVM 回收期 如果 内存      更新时间:2023-10-16
使用ByteBuffer就是

一个例子;将数据从Array或HeapByteBuffer复制到DirectByteBuffer中执行JNI调用。

基本上这个...

public static void copyFromByteArray(byte[] src, long srcPos, long dstAddr, long length)
{
    long offset = arrayBaseOffset + srcPos;
    while (length > 0)
    {
        long size = (length > UNSAFE_COPY_THRESHOLD) ? UNSAFE_COPY_THRESHOLD : length;
        unsafe.copyMemory(src, offset, null, dstAddr, size);
        length -= size;
        offset += size;
        dstAddr += size;
    }
}

它使用计算堆指针并直接从堆复制的魔术。 如果该指针在此例程中途可能变得无效,这怎么可能远程安全?

对于那些相关人员:UNSAFE_COPY_THRESHOLD是1GB

编辑:感谢您的回复。 我为任何寻找相同问题的答案的人添加了以下参考。 该过程利用了安全点(我不知道他们怎么称呼它,所以我不能只是谷歌它(。

引用:

  • http://blog.ragozin.info/2012/10/safepoints-in-hotspot-jvm.html
  • http://chriskirk.blogspot.com/2013/09/what-is-java-safepoint.html
GC

必须强制所有线程进入安全点才能移动对象。这意味着所有线程都以已知状态挂起,以便可以安全地更新所有引用。

在这种情况下,不安全操作是编译器固有的,这意味着您实际上不会进行调用,但 VM 会插入实现该功能的机器代码。由于此位置不是安全点,因此在该位置可能不会发生GC。如果需要 GC,GC 将被推迟,直到执行不安全操作的线程完成此操作并到达此类安全点。

所有传递给 JNI 方法、由 JNI 方法获取或由 JNI 方法创建的 Java 对象都将被冻结以进行 GC 处理,直到该方法返回。这就是为什么它们的数量有限。