2015-12-03 68 views
17

documentation我發現:作爲類被加載由Java虛擬機 自動構造在課程加載過程中,誰首先創建了類<?>對象?

類對象和通過調用的defineClass方法 在類加載器。

我查了the source code,但沒有找到defineClass的地方叫做例如來自loadClass方法。 你能告訴我,請誰,根據該方案呼籲defineClass方法時:

scheme

圖片source

+1

當你處理JVM內部事件(magic!)時,一個好的懷疑是事情正在本地代碼(C/C++/asm)中發生。 – Nayuki

+0

當然可以,但問題是:它什麼時候出現(Class對象出現)?實現語言並不重要 –

回答

10

defineClass()方法的ClassLoader#loadClass()調用期間調用。然而,這不是在java.lang.ClassLoader類中直接完成的,而是在它的一個子類中,例如,在URLClassLoader#findClass()

ClassLoader#defineClass()到該呼叫中的天然方法defineClass1()defineClass2()一個呼叫結束。這些方法的C實現可以在OpenJDK的src/share/native/java/lang/ClassLoader.c中找到。

5

java.lang.ClassLoader就是這麼大的一類。使用你的GrepCode鏈接(這是用於java 6-b14版本),你可以在267行找到公開的loadClass方法。

此方法中,在線308調用一個受保護的loadClass方法和該方法中嘗試使用加載一個previosly加載的類:

  • findLoadedClass這在端部調用本機方法,
  • 調用parent.loadClass
  • findBootstrapClass0本地方法也)如果沒有parent,
  • 最後findClass如果沒有找到課程。

這很重要,因爲ClassLoader試圖重新使用已加載的句柄,請記住。

但是,defineClass在哪裏被調用?這個抽象類沒有地方,但是如果你使用GrepCode的參考工具並搜索它的使用位置defineClasssee here results),你會發現很多具體的類,最後調用definClass

這並不簡單,其中一些類,覆蓋defineClass而其他調用它自己的loadClass然後調用...等,但最後它調用defineClass

不要忘記,ClassLoaderdefineClass結束在該負責JVM魔術的三種天然方法之一:defineClass0defineClass1和/或defineClass2

編輯

本地函數調用defineClass0Java_java_lang_ClassLoader_defineClass0ClassLoader.c和1和2功能相同。

該函數使用jvm.h中定義的JVM_DefineClassWithSource創建所需的類,並在openjdk\hotspot\src\share\vm\prims\jvm.cpp中實現。

這最後一個文件定義了jvm_define_class_common函數,它最終是創建所需類的函數。最後,這個函數調用JNIHandles::make_local來分配類。你可以看到openjdk\hotspot\src\share\vm\runtime\jniHandles.cpp

希望它回答你的問題。

1
class NetworkClassLoader extends ClassLoader { 
     String host; 
     int port; 

     public Class findClass(String name) { 
      byte[] b = loadClassData(name); 
      return defineClass(name, b, 0, b.length); 
     } 

     private byte[] loadClassData(String name) { 
      // load the class data from the connection 
       . . . 
     } 
    } 
+0

這是從Oracle的dosumentation.defineClass提取的方法,它是ClassLoader的一種方法,它將字節數組轉換爲類Class的實例。 我希望它有幫助 – Hiren

相關問題