該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 完成。
添加回答
舉報
0/150
提交
取消