Slide 1

Slide 1 text

Байткод для любознательных @antonarhipov JPoint 2016

Slide 2

Slide 2 text

Антон Архипов • ZeroTurnaround • Product Manager • Таллин, Эстония • Инструменты для Java-разработчиков • Программирую на Java с 2001 года

Slide 3

Slide 3 text

No content

Slide 4

Slide 4 text

Зачем? • Стоит знать свою платформу! • Может быть вы хотите написать свой компилятор? • Фреймворки (AOP, ORM) • Всевозможные инструменты, например JRebel :) • … ну или может просто скучно?

Slide 5

Slide 5 text

INTRO

Slide 6

Slide 6 text

1 + 2

Slide 7

Slide 7 text

1 + 2 1 2 +

Slide 8

Slide 8 text

1 + 2 1 2 +

Slide 9

Slide 9 text

1 + 2 1 2 + PUSH 1 1

Slide 10

Slide 10 text

1 + 2 1 2 + PUSH 1 PUSH 2 2 1

Slide 11

Slide 11 text

1 + 2 1 2 + PUSH 1 PUSH 2 ADD 3

Slide 12

Slide 12 text

1 + 2 1 2 + ICONST_1 ICONST_2 IADD 3

Slide 13

Slide 13 text

? = 1 + 2

Slide 14

Slide 14 text

ТАКСОНОМИЯ

Slide 15

Slide 15 text

Байт-код • Одно-байтные инструкции • 256 возможных вариантов • Используется 200+

Slide 16

Slide 16 text

ОПЕРАЦИЯ ТИП

Slide 17

Slide 17 text

• <тип> ::= b, s, c, i, l, f, d, a ОПЕРАЦИЯ ТИП

Slide 18

Slide 18 text

• <тип> ::= b, s, c, i, l, f, d, a • константы (ldc, iconst_1) ОПЕРАЦИЯ ТИП

Slide 19

Slide 19 text

• <тип> ::= b, s, c, i, l, f, d, a • константы (ldc, iconst_1) • локальные переменные и стек (load/store) • Операции с массивами (aload, astore) • Арифметика (add, sub, mul, div) • Булевые/битовые операции (iand, ixor) • Сравнения (cmpg, cmpl, ifne, ifeq) • Преобразования (l2d, i2l) ОПЕРАЦИЯ ТИП

Slide 20

Slide 20 text

Таксономия

Slide 21

Slide 21 text

Работа со стеком Таксономия

Slide 22

Slide 22 text

Работа со стеком Инструкции управления Таксономия

Slide 23

Slide 23 text

Работа со стеком Инструкции управления Работа с объектами Таксономия

Slide 24

Slide 24 text

Работа со стеком Инструкции управления Арифметика Работа с объектами Таксономия

Slide 25

Slide 25 text

Работа со стеком Инструкции управления Арифметика Работа с объектами monitorenter monitorexit Таксономия

Slide 26

Slide 26 text

ИНСТРУМЕНТАРИЙ

Slide 27

Slide 27 text

javap • Дизассемблер Java класс-файлов • По-умолчанию показывает только структуру класса – Методы, супер-класс, интерфейсы, итд • -c покажет байткод методов • -private покажет все приватные поля и методы • -s покажет сигнатуры • -l покажет номера строк и таблицу локальных переменных

Slide 28

Slide 28 text

Java Bytecode Editor — http://set.ee/jbe/

Slide 29

Slide 29 text

ObjectWeb ASM

Slide 30

Slide 30 text

HELLO WORLD!

Slide 31

Slide 31 text

No content

Slide 32

Slide 32 text

C:\work\geecon\classes>javap Hello -c

Slide 33

Slide 33 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return

Slide 34

Slide 34 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return конструктор по-умолчанию

Slide 35

Slide 35 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return выложить this на стек

Slide 36

Slide 36 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return вызвать для this

Slide 37

Slide 37 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return

Slide 38

Slide 38 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V

Slide 39

Slide 39 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V обратиться к статическому полю

Slide 40

Slide 40 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V загрузить строковую константу в стек

Slide 41

Slide 41 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V вызвать метод с параметром

Slide 42

Slide 42 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V

Slide 43

Slide 43 text

C:\work\geecon\classes>javap Hello -c Compiled from "Hello.java" public class Hello extends java.lang.Object{ public Hello(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return public static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V Что такое #1,#2, итд ?

Slide 44

Slide 44 text

C:\work\geecon\classes>javap Hello -c -verbose

Slide 45

Slide 45 text

C:\work\geecon\classes>javap Hello -c -verbose

Slide 46

Slide 46 text

C:\work\geecon\classes>javap Hello -c -verbose Compiled from "Hello.java“ public class Hello extends java.lang.Object SourceFile: "Hello.java" minor version: 0 major version: 50 Constant pool: const #1 = Method #6.#20; // java/lang/Object."":()V const #2 = Field #21.#22; // java/lang/System.out:Ljava/io/PrintStream; const #3 = String #23; // Hello, World! const #4 = Method #24.#25; // java/io/PrintStream.println:(Ljava/lang/String;)V const #5 = class #26; // Hello const #6 = class #27; // java/lang/Object const #7 = Asciz ; const #8 = Asciz ()V;

Slide 47

Slide 47 text

C:\work\geecon\classes>javap Hello -c -verbose Compiled from "Hello.java“ public class Hello extends java.lang.Object SourceFile: "Hello.java" minor version: 0 major version: 50 Constant pool: const #1 = Method #6.#20; // java/lang/Object."":()V const #2 = Field #21.#22; // java/lang/System.out:Ljava/io/PrintStream; const #3 = String #23; // Hello, World! const #4 = Method #24.#25; // java/io/PrintStream.println:(Ljava/lang/String;)V const #5 = class #26; // Hello const #6 = class #27; // java/lang/Object const #7 = Asciz ; const #8 = Asciz ()V;

Slide 48

Slide 48 text

C:\work\geecon\classes>javap Hello -c -verbose … public Hello(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return LineNumberTable: line 1: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LHello;

Slide 49

Slide 49 text

C:\work\geecon\classes>javap Hello -c -verbose … public Hello(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return LineNumberTable: line 1: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LHello;

Slide 50

Slide 50 text

C:\work\geecon\classes>javap Hello -c -verbose … public Hello(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: return LineNumberTable: line 1: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LHello;

Slide 51

Slide 51 text

C:\work\geecon\classes>javap Hello -c -verbose … public static void main(java.lang.String[]); Code: Stack=2, Locals=1, Args_size=1 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello, World! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return LineNumberTable: line 4: 0 line 5: 8 LocalVariableTable: Start Length Slot Name Signature 0 9 0 args [Ljava/lang/String;

Slide 52

Slide 52 text

МОДЕЛЬ ВЫЧИСЛЕНИЙ

Slide 53

Slide 53 text

• JVM работает со стеком • У каждого потока есть стек • Стек сохраняет “фреймы” • Новый “фрейм” создаётся при вызове метода • “Фрейм состоит из”: – Стек операций – Массив локальных переменных Стековая машина

Slide 54

Slide 54 text

Стек операций Локальные переменные 2 0 1 N … Константы #1

Slide 55

Slide 55 text

public java.lang.String getName(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: getfield #2; //Field name:Ljava/lang/String; 4: areturn LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LGet;

Slide 56

Slide 56 text

public java.lang.String getName(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: getfield #2; //Field name:Ljava/lang/String; 4: areturn LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LGet; aload_0 getfield 00 02 areturn 0 1 2 3 4

Slide 57

Slide 57 text

public java.lang.String getName(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: getfield #2; //Field name:Ljava/lang/String; 4: areturn LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LGet; 2A B4 00 02 B0 0 1 2 3 4

Slide 58

Slide 58 text

public java.lang.String getName(); Code: Stack=1, Locals=1, Args_size=1 0: aload_0 1: getfield #2; //Field name:Ljava/lang/String; 4: areturn LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LGet;

Slide 59

Slide 59 text

No content

Slide 60

Slide 60 text

СТЕКОВЫЕ ОПЕРАЦИИ

Slide 61

Slide 61 text

A B dup pop swap dup_x1 dup2_x1

Slide 62

Slide 62 text

A B dup pop swap dup_x1 dup2_x1 A

Slide 63

Slide 63 text

dup pop swap dup_x1 dup2_x1 A B

Slide 64

Slide 64 text

dup pop swap dup_x1 dup2_x1 A B

Slide 65

Slide 65 text

dup pop swap dup_x1 dup2_x1 A B B

Slide 66

Slide 66 text

dup pop swap dup_x1 dup2_x1 A B B B A

Slide 67

Slide 67 text

dup2_x2 Как поменять местами две переменные типа double?

Slide 68

Slide 68 text

No content

Slide 69

Slide 69 text

dconst_0 0.0

Slide 70

Slide 70 text

dconst_0 dconst_1 1.0 0.0

Slide 71

Slide 71 text

dconst_0 dconst_1 swap 1.0 0.0

Slide 72

Slide 72 text

dconst_0 dconst_1 swap 1.0 0.0 нельзя!

Slide 73

Slide 73 text

dconst_0 dconst_1 swap2 1.0 0.0

Slide 74

Slide 74 text

dconst_0 dconst_1 swap2 1.0 0.0 нет такой инструкции

Slide 75

Slide 75 text

dconst_0 dconst_1 dup2_x2 1.0 0.0 1.0

Slide 76

Slide 76 text

dconst_0 dconst_1 dup2_x2 pop2 0.0 1.0

Slide 77

Slide 77 text

dconst_0 dconst_1 dup2_x2 pop2 0.0 1.0 profit! ☺

Slide 78

Slide 78 text

ЛОКАЛЬНЫЕ ПЕРЕМЕННЫЕ

Slide 79

Slide 79 text

Локальные переменные

Slide 80

Slide 80 text

public int calculate(int); Code: Stack=2, Locals=2, Args_size=2 … LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LLocalVariables; 0 5 1 value I Локальные переменные

Slide 81

Slide 81 text

public int calculate(int); Code: Stack=2, Locals=2, Args_size=2 … LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LLocalVariables; 0 5 1 value I Нумеровка элементов с нуля Локальные переменные

Slide 82

Slide 82 text

у виртуальных методов this всегда на позиции 0 public int calculate(int); Code: Stack=2, Locals=2, Args_size=2 … LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LLocalVariables; 0 5 1 value I Локальные переменные

Slide 83

Slide 83 text

public int calculate(int); Code: Stack=2, Locals=2, Args_size=2 … LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LLocalVariables; 0 5 1 value I таблица сопоставления названия переменных к порядковому номеру Локальные переменные

Slide 84

Slide 84 text

public int calculate(int); Code: Stack=2, Locals=2, Args_size=2 … LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LLocalVariables; 0 5 1 value I размерность предопределена Локальные переменные

Slide 85

Slide 85 text

ldc "Hello" astore_0 iconst_1 astore_1 aload_0 глубина значение Стек переменная значение Локальные переменные 0 1 2 3 4 0 1 2 3 4

Slide 86

Slide 86 text

ldc "Hello" astore_0 iconst_1 astore_1 aload_0 "Hello" 0 1 2 3 4 0 1 2 3 4 глубина значение Стек переменная значение Локальные переменные

Slide 87

Slide 87 text

ldc "Hello" astore_0 iconst_1 astore_1 aload_0 "Hello" 0 1 2 3 4 0 1 2 3 4 глубина значение Стек переменная значение Локальные переменные

Slide 88

Slide 88 text

ldc "Hello" astore_0 iconst_1 astore_1 aload_0 "Hello" 0 1 2 3 4 0 1 2 3 4 1 глубина значение Стек переменная значение Локальные переменные

Slide 89

Slide 89 text

ldc "Hello" astore_0 iconst_1 astore_1 aload_0 "Hello" 0 1 2 3 4 0 1 2 3 4 1 глубина значение Стек переменная значение Локальные переменные

Slide 90

Slide 90 text

ldc "Hello" astore_0 iconst_1 astore_1 aload_0 "Hello" 0 1 2 3 4 0 1 2 3 4 1 "Hello" глубина значение Стек переменная значение Локальные переменные

Slide 91

Slide 91 text

Стек Таблица локальных переменных store load

Slide 92

Slide 92 text

ОБЪЕКТЫ

Slide 93

Slide 93 text

new инициализация экземпляра объекта инициализация класса Создание объектов 0xBB

Slide 94

Slide 94 text

static {} static {}; Code: 0: iconst_1 1: putstatic #2; //Field a:I 4: iconst_2 5: putstatic #3; //Field b:I 8: return

Slide 95

Slide 95 text

static {} static {}; Code: 0: iconst_1 1: putstatic #2; //Field a:I 4: iconst_2 5: putstatic #3; //Field b:I 8: return

Slide 96

Slide 96 text

new

Slide 97

Slide 97 text

new

Slide 98

Slide 98 text

new public Initializer(); Code:

Slide 99

Slide 99 text

new public Initializer(); Code: 0: aload_0

Slide 100

Slide 100 text

new public Initializer(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V

Slide 101

Slide 101 text

new public Initializer(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: aload_0

Slide 102

Slide 102 text

new public Initializer(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: aload_0 5: new #2; //class java/lang/Object 8: dup

Slide 103

Slide 103 text

new public Initializer(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: aload_0 5: new #2; //class java/lang/Object 8: dup 9: invokespecial #1; //Method java/lang/Object."":()V 12: putfield #3; //Field o:Ljava/lang/Object;

Slide 104

Slide 104 text

new public Initializer(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: aload_0 5: new #2; //class java/lang/Object 8: dup 9: invokespecial #1; //Method java/lang/Object."":()V 12: putfield #3; //Field o:Ljava/lang/Object; 15: return

Slide 105

Slide 105 text

new public Initializer(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: aload_0 5: new #2; //class java/lang/Object 8: dup 9: invokespecial #1; //Method java/lang/Object."":()V 12: putfield #3; //Field o:Ljava/lang/Object; 15: return

Slide 106

Slide 106 text

{ }

Slide 107

Slide 107 text

{ } ?

Slide 108

Slide 108 text

{ } public Initializer(int); Code: 0: aload_0 1: invokespecial #1; // .. 4: aload_0 5: iconst_1 6: putfield #2; //Field a:I 9: aload_0 10: iconst_2 11: putfield #3; //Field c:I 14: aload_0 15: iload_1 16: putfield #4; //Field b:I 19: return

Slide 109

Slide 109 text

ВЫЗОВЫ МЕТОДОВ

Slide 110

Slide 110 text

invokeXXX • invokestatic • invokespecial • invokevirtual • invokeinterface • invokedynamic

Slide 111

Slide 111 text

invokestatic • invokestatic • invokespecial • invokevirtual • invokeinterface • invokedynamic Integer.valueOf(“42”)

Slide 112

Slide 112 text

invokespecial • invokestatic • invokespecial • invokevirtual • invokeinterface • invokedynamic private void foo(); super.method();

Slide 113

Slide 113 text

• invokestatic • invokespecial • invokevirtual • invokeinterface • invokedynamic invokevirtual class A class B A/method1 A/method2 A/method1 B/method2 B/method3

Slide 114

Slide 114 text

invokeinterface • invokestatic • invokespecial • invokevirtual • invokeinterface • invokedynamic Efficient Implementation of Java Interfaces: Invokeinterface Considered Harmless, Bowen Alpern, Anthony Cocchi, Stephen Fink, David Grove, and Derek Lieber, OOPSLA’01 class A class B impl X A/method1 A/method2 A/method1 B/method2 B/method3 X/methodX D impl X D/method1 X/methodX

Slide 115

Slide 115 text

Вызов метода

Slide 116

Slide 116 text

obj.method(param1, param2); Вызов метода

Slide 117

Slide 117 text

obj.method(param1, param2); Вызов метода

Slide 118

Slide 118 text

obj.method(param1, param2); push obj push param1 push param2 call method Вызов метода

Slide 119

Slide 119 text

obj.method(param1, param2); push obj push param1 push param2 call method obj Вызов метода

Slide 120

Slide 120 text

obj.method(param1, param2); push obj push param1 push param2 call method obj param1 Вызов метода

Slide 121

Slide 121 text

obj.method(param1, param2); push obj push param1 push param2 call method obj param1 param2 Вызов метода

Slide 122

Slide 122 text

obj.method(param1, param2); push obj push param1 push param2 call method obj? Вызов метода

Slide 123

Slide 123 text

this.add(1, 2); 0: aload_0 1: iconst_1 2: iconst_2 3: invokevirtual #2; //Method add:(II)I Вызов метода

Slide 124

Slide 124 text

ВНУТЕРННИЕ КЛАССЫ INNER CLASSES

Slide 125

Slide 125 text

Внутренние классы

Slide 126

Slide 126 text

class Car$Engine extends j.l.Object{ final Car this$0; Car$Engine(Car); public void start(); Code: 0: aload_0 1: getfield #1; //Field this$0:LCar; 4: invokestatic #3; // Car.access$000:(LCar;)V 7: return } Внутренние классы

Slide 127

Slide 127 text

public class Car extends j.l.Object{ public Car(); private void move(); static void access$000(Car); Code: 0: aload_0 1: invokespecial #1; // move: ()V; 4: return } class Car$Engine extends j.l.Object{ final Car this$0; Car$Engine(Car); public void start(); Code: 0: aload_0 1: getfield #1; //Field this$0:LCar; 4: invokestatic #3; // Car.access$000:(LCar;)V 7: return } Внутренние классы

Slide 128

Slide 128 text

public class Car extends j.l.Object{ public Car(); private void move(); static void access$000(Car); Code: 0: aload_0 1: invokespecial #1; // move: ()V; 4: return } class Car$Engine extends j.l.Object{ final Car this$0; Car$Engine(Car); public void start(); Code: 0: aload_0 1: getfield #1; //Field this$0:LCar; 4: invokestatic #3; // Car.access$000:(LCar;)V 7: return } Внутренние классы

Slide 129

Slide 129 text

@antonarhipov anton@zeroturnaround.com