2013-04-10 7 views
10

So che il nuova, dup, invokespecial e astore modello bytecode richiamerà il metodo di istanza di inizializzazione <init> quando esempio qualcuno una classe Java dal punto linguaggio Java di vista, ma non ho mai capire chi invocare il metodo speciale <clinit> e quando succede?Chi invoca il metodo di inizializzazione della classe <clinit> e quando?

La mia ipotesi è che <clinit> è stato invocato prima del metodo<init>. Qualcuno può darmi qualche informazione per dimostrarlo? Questo è documentato nella specifica JVM o nella specifica del linguaggio Java?

risposta

7

JVM spec §2.9. Special Methods:

Una classe o interfaccia ha al massimo un metodo di inizializzazione classe o interfaccia e viene inizializzato (§5.5) invocando tale metodo. Il metodo di inizializzazione di una classe o di un'interfaccia ha il nome speciale <clinit>, non accetta argomenti ed è nullo (§4.3.3).

Il nome <clinit> è fornito da un compilatore. Poiché il nome non è un identificatore valido, non può essere utilizzato direttamente in un programma scritto nel linguaggio di programmazione Java. I metodi di inizializzazione della classe e dell'interfaccia vengono richiamati implicitamente dalla Java Virtual Machine; non vengono mai richiamati direttamente da alcuna istruzione Java Virtual Machine, ma vengono richiamati solo indirettamente come parte del processo di inizializzazione della classe.

Vedere Chapter 5 per ulteriori dettagli sul processo di inizializzazione della classe.

1

<clinit> sono i blocchi di inizializzazione statici per la classe e l'inizializzazione del campo statico e il suo invocato da JVM.

Java Spec dice, http://java.sun.com/docs/books/jvms/second_edition/html/Overview.doc.html#12174

The initialization method of a class or interface is static and takes no arguments. It has the special name <clinit>. This name is supplied by a compiler. Because the name <clinit> is not a valid identifier, it cannot be used directly in a program written in the Java programming language. Class and interface initialization methods are invoked implicitly by the Java virtual machine 
6

<clinit> è un metodo statico inserito da javac e chiamato da JVM dopo il caricamento della classe. Possiamo vedere questo metodo in bytecode di classe con gli strumenti di contorno del bytecode. Si noti che <clinit> viene aggiunto solo se una classe deve initilization statico, per esempio

public class Test1 { 
    static int x = 1; 

    public static void main(String[] args) throws Exception { 
    } 
} 

public class Test2 { 
    static final int x = 1; 

    public static void main(String[] args) throws Exception { 
    } 
} 

Test1 ha <clinit> perché il suo campo x deve essere inizializzato con 1; mentre Test2 non ha il metodo <clinit> perché il suo x è una costante.

È anche interessante notare che Class.forName ha il parametro boolen intialize che determina se la classe deve essere inizializzata dopo il caricamento o meno.

+1

"Si noti che viene aggiunto solo se una classe ha bisogno di inizializzazione statica" - qualsiasi origine per quello? – siledh

+0

viene dalla pratica (test) per essere onesti, anche il senso comune suggerisce lo stesso, certo c'è un paragrafo in JLS a riguardo –

Problemi correlati