и методи в JVM

1. Общ преглед

JVM използва два отличителни метода за инициализиране на обектни екземпляри и класове.

В тази бърза статия ще видим как компилаторът и времето за изпълнение използват и методи за целите на инициализацията.

2. Методи за инициализиране на инстанция

Нека започнем с просто разпределение и присвояване на обекти:

Object obj = new Object();

Ако компилираме този фрагмент и погледнем байт кода му чрез javap -c , ще видим нещо като:

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

За да инициализира обекта , JVM извиква специален метод с име .В жаргона на JVM този метод е метод за инициализация на екземпляр . Методът е инициализация на екземпляр тогава и само ако:

  • Определя се в клас
  • Името му е < init>
  • Връща се празно

Всеки клас може да има нула или повече методи за инициализация на екземпляр . Тези методи обикновено съответстват на конструктори в базирани на JVM програмни езици като Java или Kotlin.

2.1. Конструктори и блокове за инициализация на екземпляри

За да разберем по-добре как Java компилаторът превежда конструктори в , нека разгледаме друг пример:

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() { } }

Това е байт кодът за този клас:

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

Въпреки че конструкторът и блоковете на инициализатора са отделни в Java, те са в един и същ метод за инициализация на инстанция на ниво байт код. В интерес на истината товаметод:

  • Първо инициализира полетата firstName и lastName (индекс от 0 до 13)
  • След това отпечатва нещо в конзолата като част от блока за инициализация на инстанция (индекс 16 до 21)
  • И накрая, той актуализира променливите на екземпляра с аргументите на конструктора

Ако създадем Личност, както следва:

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

След това това се превежда в следния байт код:

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

Този път JVM извиква друг метод с подпис, съответстващ на Java конструктора.

Ключовият извод тук е, че конструкторите и други инициализатори на екземпляри са еквивалентни на метод в света на JVM.

3. Методи за инициализиране на клас

В Java статичните блокове на инициализатора са полезни, когато ще инициализираме нещо на ниво клас:

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

Когато компилираме предходния код, компилаторът превежда статичния блок в метод за инициализация на клас на ниво байт код.

Казано по-просто, методът е инициализация на клас, ако и само ако:

  • Името му е
  • Връща се празно

Следователно, единственият начин за генериране на метод в Java е да се използват статични полета и инициализатори на статични блокове.

JVM извиква първият път, когато използваме съответния клас. Следователно,извикването се случва по време на изпълнение и не можем да видим извикването на ниво байт код.

4. Заключение

В тази бърза статия видяхме разликата между и методи в JVM. Theметод се използва за инициализиране на екземпляри на обекти. Също така JVM извикваметод за инициализиране на клас, когато е необходимо.

За да разберете по-добре как работи инициализацията в JVM, силно се препоръчва да прочетете спецификацията на JVM.