e metodi nella JVM

1. Panoramica

La JVM utilizza due metodi distintivi per inizializzare istanze e classi di oggetti.

In questo rapido articolo, vedremo come il compilatore e il runtime utilizzano il e metodi per scopi di inizializzazione.

2. Metodi di inizializzazione delle istanze

Cominciamo con una semplice allocazione e assegnazione di oggetti:

Object obj = new Object();

Se compiliamo questo snippet e diamo un'occhiata al suo bytecode tramite javap -c , vedremo qualcosa di simile:

0: new #2 // class java/lang/Object 3: dup 4: invokespecial #1 // Method java/lang/Object."":()V 7: astore_1

Per inizializzare l'oggetto , la JVM chiama un metodo speciale denominato .Nel gergo JVM, questo metodo è un metodo di inizializzazione dell'istanza . Un metodo è un'inizializzazione dell'istanza se e solo se:

  • È definito in una classe
  • Il suo nome è < init>
  • Restituisce vuoto

Ogni classe può avere zero o più metodi di inizializzazione dell'istanza . Questi metodi di solito corrispondono ai costruttori nei linguaggi di programmazione basati su JVM come Java o Kotlin.

2.1. Costruttori e blocchi inizializzatori di istanze

Per capire meglio come il compilatore Java traduce i costruttori in , consideriamo un altro esempio:

public class Person { private String firstName = "Foo"; //  private String lastName = "Bar"; //  //  { System.out.println("Initializing..."); } //  public Person(String firstName, String lastName) { this.firstName = firstName; this.lastName = lastName; } //  public Person() { } }

Questo è il bytecode per questa classe:

public Person(java.lang.String, java.lang.String); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."":()V 4: aload_0 5: ldc #7 // String Foo 7: putfield #9 // Field firstName:Ljava/lang/String; 10: aload_0 11: ldc #15 // String Bar 13: putfield #17 // Field lastName:Ljava/lang/String; 16: getstatic #20 // Field java/lang/System.out:Ljava/io/PrintStream; 19: ldc #26 // String Initializing... 21: invokevirtual #28 // Method java/io/PrintStream.println:(Ljava/lang/String;)V 24: aload_0 25: aload_1 26: putfield #9 // Field firstName:Ljava/lang/String; 29: aload_0 30: aload_2 31: putfield #17 // Field lastName:Ljava/lang/String; 34: return

Anche se il costruttore e i blocchi di inizializzazione sono separati in Java, si trovano nello stesso metodo di inizializzazione dell'istanza a livello di bytecode. È un dato di fatto, questometodo:

  • Innanzitutto, inizializza i campi firstName e lastName (indice da 0 a 13)
  • Quindi, stampa qualcosa sulla console come parte del blocco di inizializzazione dell'istanza (indice da 16 a 21)
  • Infine, aggiorna le variabili di istanza con gli argomenti del costruttore

Se creiamo una persona come segue:

Person person = new Person("Brian", "Goetz");

Quindi questo si traduce nel seguente bytecode:

0: new #7 // class Person 3: dup 4: ldc #9 // String Brian 6: ldc #11 // String Goetz 8: invokespecial #13 // Method Person."":(Ljava/lang/String;Ljava/lang/String;)V 11: astore_1

Questa volta JVM ne chiama un altro metodo con una firma corrispondente al costruttore Java.

Il punto chiave qui è che i costruttori e altri inizializzatori di istanze sono equivalenti a metodo nel mondo JVM.

3. Metodi di inizializzazione della classe

In Java, i blocchi di inizializzazione statici sono utili quando inizializzeremo qualcosa a livello di classe:

public class Person { private static final Logger LOGGER = LoggerFactory.getLogger(Person.class); //  //  static { System.out.println("Static Initializing..."); } // omitted }

Quando compiliamo il codice precedente, il compilatore traduce il blocco statico in un metodo di inizializzazione della classe a livello di bytecode.

In parole povere, un metodo è un'inizializzazione di una classe se e solo se:

  • Il suo nome è
  • Restituisce vuoto

Pertanto, l'unico modo per generare un file Il metodo in Java consiste nell'utilizzare campi statici e inizializzatori di blocchi statici.

JVM richiama il la prima volta che usiamo la classe corrispondente. quindi, ill'invocazione avviene in fase di esecuzione e non possiamo vedere l'invocazione a livello di bytecode.

4. Conclusione

In questo breve articolo, abbiamo visto la differenza tra e metodi nella JVM. Ilviene utilizzato per inizializzare le istanze degli oggetti. Inoltre, la JVM richiama ilmetodo per inizializzare una classe ogni volta che è necessario.

Per comprendere meglio come funziona l'inizializzazione nella JVM, si consiglia vivamente di leggere la specifica JVM.