如果允许 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?
使用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 处理,直到该方法返回。这就是为什么它们的数量有限。
相关文章:
- std::vector::p ush_back() 不会在 MSVC 上编译具有已删除移动构造函数的对象
- 我什么时候会默认(而不是删除)基类中的复制和移动操作
- 移动构造函数永远不会被调用
- 通过基类接受方法转发派生 UniquePtr 的右值会移动引用而不是复制
- 如何在窗口之间移动 std::unique_ptr 而不会冒内存泄漏的风险?
- std::async 如何工作:为什么它会调用这么多次复制/移动?
- 控件不会在选择函数旁边移动
- OpenGL:当我移动相机时,它会向侧面倾斜
- 指针上的 For 循环:它会移动整个地址范围吗?
- 为什么定义移动构造函数会删除移动赋值运算符
- C++具有移动语义的可变参数工厂会导致运行时崩溃
- 如果没有带有函数签名的 rvalue 参数,是否会执行 C++ 11 中的移动语义?
- 删除复制构造函数是否也会删除默认的复制/移动运算符?
- 在C++中,我的主机游戏角色在游戏场数组内移动时不会停止
- 当我将构造函数显式调用为参数时,不会调用移动构造函数
- 为什么当我不移动任何东西时,clang 会抱怨删除移动 ctor?
- 在 3 点之间移动模型会导致模型偏离位置
- 移动鼠标会导致事件不更新
- 为什么包含std::字符串流的类的移动语义会导致编译器错误
- 在vector中的vector之间移动指针会导致vector迭代器不兼容