Upgrade to Pro — share decks privately, control downloads, hide ads and more …

JPoint 2016 - Bytecode

JPoint 2016 - Bytecode

1bc80e2eee2adeaa8bb577798d92e9d0?s=128

Anton Arhipov

April 24, 2016
Tweet

Transcript

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

  2. Антон Архипов • ZeroTurnaround • Product Manager • Таллин, Эстония

    • Инструменты для Java-разработчиков • Программирую на Java с 2001 года
  3. None
  4. Зачем? • Стоит знать свою платформу! • Может быть вы

    хотите написать свой компилятор? • Фреймворки (AOP, ORM) • Всевозможные инструменты, например JRebel :) • … ну или может просто скучно?
  5. INTRO

  6. 1 + 2

  7. 1 + 2 1 2 +

  8. 1 + 2 1 2 +

  9. 1 + 2 1 2 + PUSH 1 1

  10. 1 + 2 1 2 + PUSH 1 PUSH 2

    2 1
  11. 1 + 2 1 2 + PUSH 1 PUSH 2

    ADD 3
  12. 1 + 2 1 2 + ICONST_1 ICONST_2 IADD 3

  13. ? = 1 + 2

  14. ТАКСОНОМИЯ

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

    200+
  16. ОПЕРАЦИЯ ТИП

  17. • <тип> ::= b, s, c, i, l, f, d,

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

    a • константы (ldc, iconst_1) ОПЕРАЦИЯ ТИП
  19. • <тип> ::= 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) ОПЕРАЦИЯ ТИП
  20. Таксономия

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

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

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

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

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

    monitorexit Таксономия
  26. ИНСТРУМЕНТАРИЙ

  27. javap • Дизассемблер Java класс-файлов • По-умолчанию показывает только структуру

    класса – Методы, супер-класс, интерфейсы, итд • -c покажет байткод методов • -private покажет все приватные поля и методы • -s покажет сигнатуры • -l покажет номера строк и таблицу локальных переменных
  28. Java Bytecode Editor — http://set.ee/jbe/

  29. ObjectWeb ASM

  30. HELLO WORLD!

  31. None
  32. C:\work\geecon\classes>javap Hello -c

  33. 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."<init>":()V 4: return
  34. 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."<init>":()V 4: return конструктор по-умолчанию
  35. 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."<init>":()V 4: return выложить this на стек
  36. 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."<init>":()V 4: return вызвать <init> для this
  37. 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."<init>":()V 4: return
  38. 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."<init>":()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
  39. 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."<init>":()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 обратиться к статическому полю
  40. 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."<init>":()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 загрузить строковую константу в стек
  41. 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."<init>":()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 вызвать метод с параметром
  42. 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."<init>":()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
  43. 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."<init>":()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, итд ?
  44. C:\work\geecon\classes>javap Hello -c -verbose

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

  46. 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."<init>":()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 <init>; const #8 = Asciz ()V;
  47. 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."<init>":()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 <init>; const #8 = Asciz ()V;
  48. 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."<init>":()V 4: return LineNumberTable: line 1: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LHello;
  49. 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."<init>":()V 4: return LineNumberTable: line 1: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LHello;
  50. 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."<init>":()V 4: return LineNumberTable: line 1: 0 LocalVariableTable: Start Length Slot Name Signature 0 5 0 this LHello;
  51. 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;
  52. МОДЕЛЬ ВЫЧИСЛЕНИЙ

  53. • JVM работает со стеком • У каждого потока есть

    стек • Стек сохраняет “фреймы” • Новый “фрейм” создаётся при вызове метода • “Фрейм состоит из”: – Стек операций – Массив локальных переменных Стековая машина
  54. Стек операций Локальные переменные 2 0 1 N … Константы

    #1
  55. 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;
  56. 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
  57. 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
  58. 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;
  59. None
  60. СТЕКОВЫЕ ОПЕРАЦИИ

  61. A B dup pop swap dup_x1 dup2_x1

  62. A B dup pop swap dup_x1 dup2_x1 A

  63. dup pop swap dup_x1 dup2_x1 A B

  64. dup pop swap dup_x1 dup2_x1 A B

  65. dup pop swap dup_x1 dup2_x1 A B B

  66. dup pop swap dup_x1 dup2_x1 A B B B A

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

  68. None
  69. dconst_0 0.0

  70. dconst_0 dconst_1 1.0 0.0

  71. dconst_0 dconst_1 swap 1.0 0.0

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

  73. dconst_0 dconst_1 swap2 1.0 0.0

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

  75. dconst_0 dconst_1 dup2_x2 1.0 0.0 1.0

  76. dconst_0 dconst_1 dup2_x2 pop2 0.0 1.0

  77. dconst_0 dconst_1 dup2_x2 pop2 0.0 1.0 profit! ☺

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

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

  80. 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 Локальные переменные
  81. 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 Нумеровка элементов с нуля Локальные переменные
  82. у виртуальных методов 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 Локальные переменные
  83. 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 таблица сопоставления названия переменных к порядковому номеру Локальные переменные
  84. 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 размерность предопределена Локальные переменные
  85. ldc "Hello" astore_0 iconst_1 astore_1 aload_0 глубина значение Стек переменная

    значение Локальные переменные 0 1 2 3 4 0 1 2 3 4
  86. ldc "Hello" astore_0 iconst_1 astore_1 aload_0 "Hello" 0 1 2

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

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

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

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

    3 4 0 1 2 3 4 1 "Hello" глубина значение Стек переменная значение Локальные переменные
  91. Стек Таблица локальных переменных store load

  92. ОБЪЕКТЫ

  93. new <init> <clinit> инициализация экземпляра объекта инициализация класса Создание объектов

    0xBB
  94. static {} static {}; Code: 0: iconst_1 1: putstatic #2;

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

    //Field a:I 4: iconst_2 5: putstatic #3; //Field b:I 8: return <clinit>
  96. new

  97. new

  98. new public Initializer(); Code:

  99. new public Initializer(); Code: 0: aload_0

  100. new public Initializer(); Code: 0: aload_0 1: invokespecial #1; //Method

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

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

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

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

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

    java/lang/Object."<init>":()V 4: aload_0 5: new #2; //class java/lang/Object 8: dup 9: invokespecial #1; //Method java/lang/Object."<init>":()V 12: putfield #3; //Field o:Ljava/lang/Object; 15: return
  106. { }

  107. { } ?

  108. { } public Initializer(int); Code: 0: aload_0 1: invokespecial #1;

    // ..<init> 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
  109. ВЫЗОВЫ МЕТОДОВ

  110. invokeXXX • invokestatic • invokespecial • invokevirtual • invokeinterface •

    invokedynamic
  111. invokestatic • invokestatic • invokespecial • invokevirtual • invokeinterface •

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

    invokedynamic <init> private void foo(); super.method();
  113. • invokestatic • invokespecial • invokevirtual • invokeinterface • invokedynamic

    invokevirtual class A class B A/method1 A/method2 A/method1 B/method2 B/method3
  114. 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
  115. Вызов метода

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

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

  118. obj.method(param1, param2); push obj push param1 push param2 call method

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

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

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

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

    obj? Вызов метода
  123. this.add(1, 2); 0: aload_0 1: iconst_1 2: iconst_2 3: invokevirtual

    #2; //Method add:(II)I Вызов метода
  124. ВНУТЕРННИЕ КЛАССЫ INNER CLASSES

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

  126. 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 } Внутренние классы
  127. 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 } Внутренние классы
  128. 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 } Внутренние классы
  129. @antonarhipov anton@zeroturnaround.com