为了账号安全,请及时绑定邮箱和手机立即绑定

为什么 SetByteArrayRegion 不会破坏内存?

为什么 SetByteArrayRegion 不会破坏内存?

慕标5832272 2022-12-28 14:29:11
该SetByteArrayRegion功能实现为JNI_ENTRY(void, \jni_Set##Result##ArrayRegion(JNIEnv *env, ElementType##Array array, jsize start, \             jsize len, const ElementType *buf)) \  JNIWrapper("Set" XSTR(Result) "ArrayRegion"); \  DTRACE_PROBE5(hotspot_jni, Set##Result##ArrayRegion__entry, env, array, start, len, buf);\  DT_VOID_RETURN_MARK(Set##Result##ArrayRegion); \  typeArrayOop dst = typeArrayOop(JNIHandles::resolve_non_null(array)); \  if (start < 0 || len < 0 || ((unsigned int)start + (unsigned int)len > (unsigned int)dst->length())) { \    THROW(vmSymbols::java_lang_ArrayIndexOutOfBoundsException()); \  } else { \    if (len > 0) { \      int sc = TypeArrayKlass::cast(dst->klass())->log2_element_size(); \      memcpy((u_char*) dst->Tag##_at_addr(start), \             (u_char*) buf, \             len << sc);    \    } \  } \JNI_END可以看出,它调用memcpy了一个指向 java 堆数组的本机指针:dst->Tag##_at_addr(start)。memcpy本身不是原子的,所以我得出结论,没有什么能阻止 GC 在memcpy调用过程中移动数组。此外,数组可以在dst->Tag##_at_addr(start)再次导致内存损坏之后立即移动到某处。根据合同,“关键”方法使用GC_locker::lock_critical(thread);.那么为什么SetArrayRegion方法是安全的呢?我错过了什么?
查看完整描述

1 回答

?
郎朗坤

TA贡献1921条经验 获得超9个赞

正如您所看到的,该函数被包装在JNI_ENTRY宏中,宏依次执行ThreadInVMfromNative状态转换。SetByteArrayRegion这意味着,保证执行的 Java 线程处于_thread_in_vm状态。

非并发压缩收集器只能在全局安全点移动对象。安全点意味着所有 Java 线程都被阻塞或运行本机代码(_thread_in_native状态)。

因此,如果在SetByteArrayRegion运行时请求安全点,JVM 将等待所有线程完成当前 VM 操作。反之,如果SetByteArrayRegion在 GC 运行时执行,则线程将阻塞在状态转换中,直到 GC 完成。


查看完整回答
反对 回复 2022-12-28
  • 1 回答
  • 0 关注
  • 207 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信