2015-12-03 14 views
17

Nel documentation ho trovato:Chi crea in primo luogo l'oggetto Classe <?> durante il caricamento della classe?

oggetti classe vengono costruiti automaticamente dal Java virtuale Macchina come classi vengono caricate e chiamate al metodo defineClass nel caricatore di classe.

Ho controllato the source code, ma non ho trovato il posto defineClass da chiamare ad es. dal metodo loadClass. Potrebbe mostrare me, per favore, chi e quando chiamata di metodo defineClass secondo questo schema:

scheme

Immagine source

+1

Quando si ha a che fare con interni JVM (magia!), Un buon sospetto è che le cose stiano accadendo nel codice nativo (C/C++/asm). – Nayuki

+0

Certo che potrebbe essere, ma la domanda è: quando accade (appare l'oggetto Class)? Il linguaggio di implementazione non è importante –

risposta

10

Il metodo defineClass() viene chiamato durante l'invocazione di ClassLoader#loadClass(). Tuttavia, questo non viene eseguito direttamente all'interno della classe java.lang.ClassLoader ma in una delle sue sottoclassi, ad es. in URLClassLoader#findClass().

La chiamata a ClassLoader#defineClass() finisce in una chiamata a uno dei nativi metodi defineClass1() o defineClass2(). Le implementazioni C di questi metodi sono disponibili in OpenJDK in src/share/native/java/lang/ClassLoader.c.

5

java.lang.ClassLoader è una classe così grande. Utilizzando il tuo link GrepCode (, che è per la versione java 6-b14) puoi trovare alla riga 267 il metodo pubblico loadClass.

Questo metodo, chiama un loadClass metodo protetto alla linea 308 e questo metodo tenta di caricare una classe previosly caricata mediante:

  • findLoadedClass che nelle estremità chiama i metodi nativi,
  • Calling parent.loadClass,
  • findBootstrapClass0 (un metodo nativo anche) se non c'è parent,
  • E infine findClass se non viene trovata alcuna classe.

Questo è importante per dire, perché ClassLoader tenta di riutilizzare le clases già caricate, tenere presente.

Ma, dove viene richiamato defineClass? Nessun posto da questa classe astratta, ma se si utilizza lo strumento di riferimento di GrepCode e si cerca dove viene utilizzato defineClass (see here results), troverete molte classi concrete che alla fine chiamano definClass.

Non è semplice, alcune di queste classi, override defineClass mentre altri chiama la propria loadClass che poi chiama ... e così via, ma alla fine si chiama defineClass.

Non dimenticate che defineClass di ClassLoader finisce in uno dei tre metodi nativi che sono responsabili di JVM magia: defineClass0, defineClass1 e/o defineClass2

Modifica

funzione nativa defineClass0 chiamate Java_java_lang_ClassLoader_defineClass0 da ClassLoader.c e lo stesso per 1 e 2 funzioni.

Questa funzione crea la classe richiesta utilizzando JVM_DefineClassWithSource definita in jvm.h e implementata in openjdk\hotspot\src\share\vm\prims\jvm.cpp.

Questo ultimo file definisce la funzione jvm_define_class_common che alla fine è la funzione che crea la classe richiesta. Infine, questa funzione chiama JNIHandles::make_local per allocare la classe. Puoi vedere il codice di questa ultima funzione in openjdk\hotspot\src\share\vm\runtime\jniHandles.cpp

Spero che risponda alla tua domanda.

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

Questo è l'estratto da Oracle dosumentation.defineClass è un metodo di ClassLoader che converte una matrice di byte in un'istanza di classe Class. Spero che aiuti – Hiren