2016-02-16 45 views
-1

使用ByteBuffer就是一個例子;將數據從Array和HeapByteBuffer複製到DirectByteBuffer中執行JNI調用。如果允許JVM在垃圾收集期間移動堆內存,那麼由於移動指針,垃圾收集不會導致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

編輯:感謝您的答覆。我爲任何正在尋找相同問題答案的人添加以下參考。這個過程使用安全點(我不知道他們叫什麼,所以我不能只是谷歌它)。

參考文獻:

回答

1

一個GC必須強制所有線程進入一個還原點來移動物體。這意味着所有線程都處於已知狀態,因此可以安全地更新所有引用。

在這種情況下,不安全的操作是編譯器內在的,這意味着你實際上並沒有進行調用,但是VM插入了實現該功能的機器代碼。由於這個位置不是一個安全點,所以在該位置不會發生GC。如果需要GC,GC將被推遲,直到進行不安全操作的線程完成此操作並達到此安全點。

+1

unsafe.copyMemory是一個JNI調用。 C代碼不安全並且無鎖。它通過將對象轉換爲(uintptr_t)並直接從本地內存地址進行復制來工作。 這是否意味着所有JNI命令=不安全狀態?我試圖更好地理解我可以逃避的事情。 – bond

+0

不回答問題。你可以強制一個JNI方法進入你喜歡的所有安全點,但它仍然會有直接的對象指針,其值不變。這個答案沒有認同正確的機制。 – EJP

1

傳遞給或由JNI方法創建或創建的所有Java對象都會凍結以實現GC目的,直到方法返回。這就是爲什麼它們的數量有限。

+0

我很關心java對象的內存地址,而不是指針。 (基本上你可以做的最不安全的事情) – bond