2017-10-10 20 views
1

當一個類首先被加載時,每個JVM只會初始化一個java類。我認爲不止一個線程可以嘗試同時加載同一個類。 JVM如何處理這個爭用?是否有任何機制來防止它發生,比如鎖定?Jave如何防止發生併發類初始化?

+0

'一個Java類,每一次初始化一個jvm' - 那是不正確的。正確的語句應該是'一個java類每個類加載器只初始化一次' – rkosegi

+1

http://docs.oracle.com/javase/specs/jls/se8/html/jls-12.html#jls-12.4.2 –

回答

4

首先,下面的語句是不準確的:

一個Java類初始化每JVM只有一次

一個Java類每類裝載器初始化一次。一個JVM實例很可能有幾個類加載器,每個加載器分別加載相同的類。

爲了回答這個問題 - 是的,類加載器在加載類時必須加鎖。如果,例如,你看看的OpenJDK 9的實施java.lang.ClassLoader,加載類最終將歸結爲以下方法(註釋添加到強調鎖定):

final Class<?> loadClass(Module module, String name) { 
    synchronized (getClassLoadingLock(name)) { // Note the locking here! 
     // First, check if the class has already been loaded 
     Class<?> c = findLoadedClass(name); 
     if (c == null) { 
      c = findClass(module.getName(), name); 
     } 
     if (c != null && c.getModule() == module) { 
      return c; 
     } else { 
      return null; 
     } 
    } 
} 
+1

從一個JVM的觀點是,「幾個類加載器,每一個都分別加載相同的類」只是幾個定義*不同類的類加載器,即使它們可能具有相同的名稱或甚至相同的字節代碼。因此,語句「一個java類每個jvm只初始化一次」是正確和準確的。除此之外,引用的代碼只是實現類的*加載,而不是*初始化*。確保初始化只發生一次仍留給JVM。 – Holger