Как Написать (Игрушку) Jvm

Статья о KVM оказалась интересной для читателей, поэтому сегодня мы публикуем новый перевод статьи Сергея Зайцева: как работает виртуальная машина Java под капотом.

Нравится нам это или нет, но Java — один из самых распространенных и широко используемых языков программирования.

Однако не каждому Java-разработчику достаточно любопытно заглянуть под капот и увидеть, как работает JVM. Я попробую написать игрушечную (и неполную) JVM, чтобы показать основные принципы ее работы.

Надеюсь, эта статья вызовет у вас интерес и вдохновит на дальнейшее изучение JVM.

Наша скромная цель

Начнем с чего-то простого:
  
   

public class Add { public static int add(int a, int b) { return a + b; } }

Мы компилируем наш класс с помощью javacAdd.java , и результат Добавить.

класс .

Этот файл класса представляет собой двоичный файл, который может выполнять JVM. Все, что нам остается сделать, это создать JVM, которая бы корректно его выполняла.

Если мы заглянем внутрь Добавить.

класс используя шестнадцатеричный дамп — мы, вероятно, не будем слишком впечатлены:

00000000 ca fe ba be 00 00 00 34 00 0f 0a 00 03 00 0c 07 |.

4.| 00000010 00 0d 07 00 0e 01 00 06 3c 69 6e 69 74 3e 01 00 |.

<init>.

| 00000020 03 28 29 56 01 00 04 43 6f 64 65 01 00 0f 4c 69 |.

()V.Code.Li| 00000030 6e 65 4e 75 6d 62 65 72 54 61 62 6c 65 01 00 03 |neNumberTable.| 00000040 61 64 64 01 00 05 28 49 49 29 49 01 00 0a 53 6f |add.(II)I.So| 00000050 75 72 63 65 46 69 6c 65 01 00 08 41 64 64 2e 6a |urceFile.Add.j| 00000060 61 76 61 0c 00 04 00 05 01 00 03 41 64 64 01 00 |ava.Add.| 00000070 10 6a 61 76 61 2f 6c 61 6e 67 2f 4f 62 6a 65 63 |.

java/lang/Objec| 00000080 74 00 21 00 02 00 03 00 00 00 00 00 02 00 01 00 |t.!.

| 00000090 04 00 05 00 01 00 06 00 00 00 1d 00 01 00 01 00 |.

| 000000a0 00 00 05 2a b7 00 01 b1 00 00 00 01 00 07 00 00 |.

*.

| 000000b0 00 06 00 01 00 00 00 01 00 09 00 08 00 09 00 01 |.

| 000000c0 00 06 00 00 00 1c 00 02 00 02 00 00 00 04 1a 1b |.

| 000000d0 60 ac 00 00 00 01 00 07 00 00 00 06 00 01 00 00 |`.

| 000000e0 00 03 00 01 00 0a 00 00 00 02 00 0b |.

|

Хотя мы пока не видим здесь четкой структуры, нам нужно найти способ ее разобрать: что это значит ()В И (II)я , и почему файл начинается с "кафе, детка"? Вы, вероятно, знакомы с другим способом создания дампа файлов классов, который зачастую более полезен:

$ javap -c Add Compiled from "Add.java" public class Add { public Add(); Code: 0: aload_0 1: invokespecial #1 // Method java/lang/Object."<init>":()V 4: return public static int add(int, int); Code: 0: iload_0 1: iload_1 2: iadd 3: ireturn }

Теперь мы видим наш класс, его конструктор и метод. И конструктор, и метод содержат несколько операторов.

Становится более-менее понятно, что делает наш метод add(): он загружает два аргумента ( iload_0 И iload_1 ), суммирует их и возвращает результат. JVM — это стековая машина, поэтому в ней нет регистров, все аргументы инструкций хранятся во внутреннем стеке, а результаты также помещаются в стек.



Загрузчик классов

Как мы можем добиться того же результата, который показала программа javap? Как разобрать файл класса? Если вы обратитесь к Спецификации JVM , узнаем о строении файлы классов .

Он всегда начинается с 4-байтовой подписи (CAFEBABE), затем 2+2 байта для версии.

Звучит просто! Поскольку нам придется читать байты, шорты, целые числа и последовательности байтов из двоичного файла, мы начнем реализацию нашего загрузчика следующим образом:

type loader struct {

Теги: #Go #java #jvm #виртуальная машина
Вместе с данным постом часто просматривают:

Автор Статьи


Зарегистрирован: 2019-12-10 15:07:06
Баллов опыта: 0
Всего постов на сайте: 0
Всего комментарий на сайте: 0
Dima Manisha

Dima Manisha

Эксперт Wmlog. Профессиональный веб-мастер, SEO-специалист, дизайнер, маркетолог и интернет-предприниматель.