2009-11-19 2 views
6

Immagina una classe Java con la maggior parte delle funzioni che puoi trovare in una classe. Ad esempio: eredita da un'altra classe, implementa un paio di interfacce, include alcune costanti 'static final', alcune costanti finali, alcune variabili statiche, variabili di istanza, un blocco statico, un blocco di codice senza nome (solo codice in {}), costruttori, metodi, ecc.In che ordine sono le diverse parti di una classe inizializzate quando una classe viene caricata nella JVM?

Quando la classe in questione viene caricata nella JVM per la prima volta, in quale ordine le varie parti della classe vengono inizializzate o caricate nella JVM? Che aspetto ha lo stack di chiamate nella JVM per il caricamento? Supponiamo che solo un classloader sia al lavoro qui.

Questo sta per tornare alle basi/interni di Java, ma non sono riuscito a trovare un buon articolo che spiegasse la sequenza corretta.

risposta

1

E per quanto riguarda lo JLS, in particolare la sezione 12.4?

+0

real smooth ... :) vorrei avere il termine di ricerca google giusto per arrivare al JLS! mi ha anche colpito il fatto che avrei potuto essere in grado di farlo attraverso il debugger di eclissi ... :( – Thimmayya

3

Questo potrebbe essere descritto nella sezione 2.17.4 of the JVMS 5.0/6

2.17.4 Inizializzazione

inizializzazione di una classe composta da:

  • esecuzione sue inizializzatori statici (§2.11) e
  • gli inizializzatori per i campi statici (§2.9.2) dichiarati nella classe.

L'inizializzazione di un'interfaccia consiste nell'eseguire gli inizializzatori per i campi dichiarati nell'interfaccia (§2.13.3.1).

Prima di inizializzare una classe o un'interfaccia, è necessario inizializzare la superclasse diretta, ma le interfacce implementate dalla classe non devono essere inizializzate. Allo stesso modo, le superinterfacce di un'interfaccia non devono essere inizializzate prima che l'interfaccia sia inizializzata.

Una classe o interfaccia tipo T vengono inizializzati immediatamente prima una delle seguenti situazioni:

  • T è una classe e viene creata un'istanza di T.
  • T è una classe e viene invocato un metodo statico di T.
  • Un campo statico non costante di T viene utilizzato o assegnato. Un campo costante è uno che è (esplicitamente o implicitamente) sia finale che statico e che è inizializzato con il valore di un'espressione costante in fase di compilazione. Un riferimento a tale campo deve essere risolto al momento della compilazione su una copia del valore della costante in fase di compilazione, quindi gli usi di tale campo non causano mai l'inizializzazione.

L'invocazione di determinati metodi nelle classi di libreria (§3.12) causa anche l'inizializzazione della classe o dell'interfaccia. Consultare le specifiche della libreria di classi della piattaforma Java 2 (ad esempio, Class Class e package java.lang.reflect) per i dettagli.

L'intento qui è che un tipo ha un set di inizializzatori che lo mette in uno stato coerente e che questo stato è il primo stato che viene osservato da altre classi. Gli inizializzatori statici e gli inizializzatori delle variabili di classe sono eseguiti in ordine testuale e potrebbero non riferirsi alle variabili di classe dichiarate nella classe le cui dichiarazioni appaiono testuali dopo l'uso, anche se queste variabili di classe sono in ambito.Questa restrizione è progettata per rilevare, in fase di compilazione, la maggior parte delle inizializzazioni circolari o altrimenti malformate.

Prima di inizializzare una classe o un'interfaccia, la sua superclasse viene inizializzata, se non è stata inizializzata in precedenza.


La versione aggiornata di Initialization in JVMS 8 is in Chapter 5.5

inizializzazione di una classe o interfaccia consiste di eseguire il suo metodo di inizializzazione classe o interfaccia (§2.9).

Una classe o interfaccia può essere inizializzato solo a seguito di:

  • L'esecuzione di una qualsiasi delle istruzioni Java Virtual Machine new, getstatic, putstatic, o invokestatic che fa riferimento alla classe o interfaccia (§new , §getstatic, §putstatic, §invokestatic).
    Tutte queste istruzioni fanno riferimento a una classe direttamente o indirettamente tramite un riferimento di campo o un riferimento al metodo.
    All'esecuzione di una nuova istruzione, la classe o l'interfaccia di riferimento viene inizializzata se non è stata già inizializzata.
    All'esecuzione di un'istruzione getstatic, o invokestatic, la classe o l'interfaccia che ha dichiarato il campo o il metodo risolto viene inizializzata se non è stata già inizializzata.
  • che la prima chiamata di un'istanza java.lang.invoke.MethodHandle che era il risultato di risoluzione di una maniglia metodo della Java Virtual Machine (§5.4.3.5) e che presenta una sorta di 2 (REF_getStatic), 4 (REF_putStatic), 6 (REF_invokeStatic), oppure 8 (REF_newInvokeSpecial).
  • Invocazione di alcuni metodi di riflessione nella libreria di classi (§2.12), ad esempio, nella classe Class o nel pacchetto java.lang.reflect.
  • Inizializzazione di una delle sue sottoclassi.
  • La sua designazione come classe iniziale all'avvio di Java Virtual Machine (§5.2).

Prima di inizializzazione, una classe o interfaccia devono essere collegati, cioè verificata, preparati, e opzionalmente risolti.

Poiché la Java Virtual Machine è multithread, l'inizializzazione di una classe o di un'interfaccia richiede un'attenta sincronizzazione, poiché alcuni altri thread potrebbero tentare di inizializzare la stessa classe o interfaccia allo stesso tempo.
Esiste anche la possibilità che l'inizializzazione di una classe o di un'interfaccia possa essere richiesta in modo ricorsivo come parte dell'inizializzazione di tale classe o interfaccia.

L'implementazione della Java Virtual Machine è responsabile della gestione della sincronizzazione e dell'inizializzazione ricorsiva mediante la seguente procedura.
Si presuppone che l'oggetto Class è già stato verificato e preparato, e che l'oggetto Class contiene stato che indica una delle quattro situazioni:

  • Tale scopo Class viene verificato e preparato ma non inizializzato.
  • Questo oggetto Class viene inizializzato da un determinato thread.
  • Questo oggetto Class è completamente inizializzato e pronto per l'uso.
  • Questo oggetto Class è in uno stato errato, forse perché l'inizializzazione è stata tentata e non è riuscita.
+0

+1 per il tuo aggiornamento. – sunleo