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
コール。
また、アレイは、右後somwhere移動させることができるdst->Tag##_at_addr(start)
再び原因メモリ破損。
契約では、「重要な」方法が採用しますGC_locker::lock_critical(thread);
。
なぜあるSetArrayRegion
方法で安全ですか?私は何を取りこぼしたか?
あなたが見ることができるように、関数がに包まれているJNI_ENTRY
順番に実行され、マクロThreadInVMfromNative
状態遷移を。この手段は、Javaスレッドが実行SetByteArrayRegion
中であることが保証されている_thread_in_vm
状態。
非同時圧縮コレクタは唯一のグローバルセーフポイントでオブジェクトを移動することができます。セーフポイントは、すべてのJavaスレッドがいずれかのブロックまたはネイティブコード(実行されていることを意味する_thread_in_native
状態)。
一方、セーフポイントが要求されるのであれば、SetByteArrayRegion
実行されている、JVMは、すべてのスレッド完全な現在のVM操作するまで待機します。場合Сontrariwiseは、SetByteArrayRegion
GCが動作している間に実行され、スレッドは、GCが完了するまでの状態遷移でブロックします。