Your SlideShare is downloading. ×

Mastering Java ByteCode

1,027
views

Published on

Understanding bytecode and what bytecode is likely to be generated by a Java compiler helps the Java programmer in the same way that knowledge of assembler helps the C or C++ programmer. Java bytecode …

Understanding bytecode and what bytecode is likely to be generated by a Java compiler helps the Java programmer in the same way that knowledge of assembler helps the C or C++ programmer. Java bytecode is the form of instructions that Java virtual machine executes. This knowledge is crucial when debugging and doing performance and memory usage tuning. The presenter will share his knowledge on what bytecode means for your platform and how to create compiler while using some awesome tools.

Published in: Education, Technology

0 Comments
7 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
1,027
On Slideshare
0
From Embeds
0
Number of Embeds
4
Actions
Shares
0
Downloads
0
Comments
0
Likes
7
Embeds 0
No embeds

Report content
Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
No notes for slide
  • Добавить много Realtime примеров в Far и Inteliji Idea или Eclipse!!!!
  • #1, #2 и т.д. храняться в пуле констант. Подробней в -verbose
  • #1, #2 и т.д. храняться в пуле констант. Подробней в -verbose
  • #1, #2 и т.д. храняться в пуле констант. Подробней в -verbose
  • #1, #2 и т.д. храняться в пуле констант. Подробней в -verbose The array of local variables, also called the local variable table, contains the parameters of the method and is also used to hold the values of the local variables.
  • Байт-кода стеко-ориентированный язык, похожий по своей структуре на ассемблер. Что бы произвести операции с данными их сначала нужно положит на стек. Мы хотим взять поле у объект. Что бы это сделять нужно его положить в стек. В байт-коде нет имен переменных, у них есть номера. Нулевой номер у ссылки на текущий объект или у переменой this. Потом идут параметры исполняемого метода. Затем остальные переменные.
  • Each thread has a JVM stack which stores frames . A frame is created each time a method is invoked, and consists of an operand stack, an array of local variables, and a reference to the runtime constant pool of the class of the current method.
  • Intel opcode выполняються в среде ОС, Sun opcode в среде JVM Платформы java имеется две особенности. Для обеспечения кроссплатформенности программа сначала компилируется в промежуточный язык низкого уровня - байт-код. Вторая особенность загрузка исполняемых классов происходит с помощью расширяемых classloader. Это механизм обеспечивает большую гибкость и позволяет модифицировать исполняемый код при загрузки, создавать и подгружать новые классы во время выполнения программы. Такая техника широко применяется для реализации AOP, создания тестовых фреймворков, ORM.
  • Каждому классу в java соответствует один откомпилированный файл. Это справедливо даже для подклассов или анонимным классов. Такой файл содержит информацию об имени класса, его родители, список интерфейсов которые он реализует, перечисление его полей и методов. Важно отметить, что после компиляции информации которая содержит директива import теряется и все классы именуются теперь через полный путь. Например в место String будет записано java/lang/String.
  • #1, #2 и т.д. храняться в пуле констант
  • Добавить диограму с Constant pool
  • prefix определяет тип, для которого предназначен opcode
  • Each method has a corresponding bytecode array. These values correspond to the index into the array where each opcode and its arguments are stored. You might wonder why the values are not sequential. Since bytecode got its name because each instruction occupies one byte, why are the indexes not 0, 1, and 2? The reason is some of the opcodes have parameters that take up space in the bytecode array. For example, the aload_0 instruction has no parameters and naturally occupies one byte in the bytecode array. Therefore, the next opcode, getfield, is in location 1. However, areturn is in location 4. This is because the getfield opcode and its parameters occupy location 1, 2, and 3
  • Class Loader при загрузке байткода проверяет его на безопастность и исправность. Больше информации про Class loader
  • Добавить утелиты для реалных примеров (Jrebel), изменение байт кода без деплоя и тд?
  • Создадим класс SimpleProgram с помощью библиотеки ASM
  • Добавить диаграму разницы
  • Добавить Realtime примеры в Far и Inteliji Idea или Eclipse!!!!
  • Добавить Realtime примеры в Far и Inteliji Idea или Eclipse!!!!
  • Добавить Realtime примеры в Far и Inteliji Idea или Eclipse!!!!
  • В чем разница межжу top1 and top2 ?
  • Они одинаковые. Методы работают с одной скоростю, если нет, то какой быстрее?
  • Они одинаковые. Методы работают с одной скоростю, если нет, то какой быстрее?
  • Они одинаковые. Методы работают с одной скоростю, если нет, то какой быстрее?
  • показать байт коды классов?
  • Strange2 хранит в astore_1 ex, а в astore_2 Missing. Strange1 хранить в a_store_1 Missing. Как же правильно сделать прверку? Обяснить подробней
  • Правильный способ проверки наличия класса. Обяснить его подробней?
  • Transcript

    • 1. Mastering byte code
    • 2. The master plan• JVM• javap• opcode• ClassLoader• Toolkits• Puzzles
    • 3. Stack1+2 PUSH 1 112+ PUSH 2 2
    • 4. Stack1+2 PUSH 1 312+ PUSH 2 ADD
    • 5. Stack1+2 ICONST_1 312+ ICONST_2 IADD
    • 6. Frame
    • 7. Local Variables & Stack
    • 8. Java Stack Machine• JVM is a stack-based machine• Each thread has a stack• Stack stores frames• Frame is created on method invocation• Frame: o Operand stack o Array of local variables o Reference to the runtime constant pool
    • 9. Compiling to binaryC/C++ (*.h, *.cpp) Java (*.java)Assembler BytecodeIntel opcode Sun opcode
    • 10. javap• Java class file disassembler• Used with no options shows class structure only• Methods, superclass, interfaces, etc• -c – shows the bytecode• -private – shows all classes and members• -s – prints internal types signatures• -verbose – prints stack size, number of locals and args for methods
    • 11. javap -c -verbose Clazz
    • 12. public class SimpleProgram{ public static void main(String[] args) { System.out.println("Hello Java Fusion!"); }}
    • 13. public class SimpleProgram{ public static void main(String[] args) { System.out.println("Hello Java Fusion!"); }}javap SimpleProgram -c
    • 14. public class SimpleProgram{ public static void main(String[] args) { System.out.println("Hello Java Fusion!"); }}javap SimpleProgram -cCompiled from "SimpleProgram.java"public class SimpleProgram extends java.lang.Object{public SimpleProgram(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello Java Fusion! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return}
    • 15. public class SimpleProgram{ public static void main(String[] args) { System.out.println("Hello Java Fusion!"); }}javap SimpleProgram -cCompiled from "SimpleProgram.java"public class SimpleProgram extends java.lang.Object{public SimpleProgram();// The default constructor Code: 0: aload_0 //Push this sto stack 1: invokespecial #1; //Method java/lang/Object."":()V //Invoke <init> on this 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello Java Fusion! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return}
    • 16. public class SimpleProgram{ public static void main(String[] args) { System.out.println("Hello Java Fusion!"); }}javap SimpleProgram -cCompiled from "SimpleProgram.java"public class SimpleProgram extends java.lang.Object{public SimpleProgram(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; //get static field 3: ldc #3; //String Hello Java Fusion! //Load String to the stack 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V //invoke method with parameter 8: return}
    • 17. public class SimpleProgram{ public static void main(String[] args) { System.out.println("Hello Java Fusion!"); }}javap SimpleProgram -cCompiled from "SimpleProgram.java"public class SimpleProgram extends java.lang.Object{public SimpleProgram(); Code: 0: aload_0 1: invokespecial #1; //Method java/lang/Object."":()V 4: returnpublic static void main(java.lang.String[]); Code: 0: getstatic #2; //Field java/lang/System.out:Ljava/io/PrintStream; 3: ldc #3; //String Hello Java Fusion! 5: invokevirtual #4; //Method java/io/PrintStream.println:(Ljava/lang/String;)V 8: return}
    • 18. public class SimpleProgram{ public static void main(String[] args) { System.out.println("Hello Java Fusion!"); }}javap SimpleProgram -c -verboseCompiled from "SimpleProgram.java“public class SimpleProgram extends java.lang.ObjectSourceFile: "SimpleProgram.java"minor version: 0major version: 50Constant pool:const #1 = Method #6.#20; // java/lang/Object."<init>":()Vconst #2 = Field #21.#22; // java/lang/System.out:Ljava/io/PrintStream;const #3 = String #23; // Hello Java Fusion!const #4 = Method #24.#25; // java/io/PrintStream.println:(Ljava/lang/String;)Vconst #5 = class #26; // SimpleProgramconst #6 = class #27; // java/lang/Objectсonst #7 = Asciz <init>;...
    • 19. BytecodeOne-byte instructions256 possible opcodes207 in use49 currently unassigned for opcodes and are reservedfor future use
    • 20. TYPE OPERATIONInstructions fall into a number of broad groups:•Local variables and stack interaction (e.g. aload_0,istore)•Array operations (aload, astore)•Arithmetic and logic (e.g. ladd,fcmpl)•Type conversion (e.g. i2b,d2i)•Object creation and manipulation (new, putfield)•Operand stack management (e.g. swap,dup2)•Control transfer (e.g. ifeq, goto)•Method invocation and return (e.g. invokespecial,areturn)•Operations with constant values (ldc, iconst_1)•Math (add, sub, mul, div)•Boolean/bitwise operations (iand, ixor)•Comparisons (cmpg, cmpl, ifne)•...
    • 21. Opcode typePrefix/Suffix Operand Typei integerl longs shortb bytec charf floatd doublea reference
    • 22. 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: areturnLocalVariableTable: Start Length Slot Name Signature 0 5 0 this LGet;
    • 23. 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: areturnLocalVariableTable: Start Length Slot Name Signature 0 5 0 this LGet;
    • 24. 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: areturnLocalVariableTable: Start Length Slot Name Signature 0 5 0 this LGet;
    • 25. 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: areturnLocalVariableTable: Start Length Slot Name Signature 0 5 0 this LGet;
    • 26. ClassLoader- Works with bytecode- Has native methods- Bytecode Verification via SecurityManager.class
    • 27. ToolkitsJVM:•ASM•Javassist•BCEL (Byte Code Engineering Library)JrebelTerracotta
    • 28. Common samplepublic class SimpleProgram{ public static void main(String[] args) { System.out.println("Hello Java Fusion!"); }}
    • 29. ASM samplepublic class ASMSample extends ClassLoader implements Opcodes {{ public static void main(String[] args) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(V1_1, ACC_PUBLIC, "SimpleProgram", null, "java/lang/Object", null); }}
    • 30. ASM samplepublic class ASMSample extends ClassLoader implements Opcodes {{ public static void main(String[] args) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(V1_1, ACC_PUBLIC, "SimpleProgram", null, "java/lang/Object", null); // creates a GeneratorAdapterfor the (implicit) constructor Method m = Method.getMethod("void <init> ()"); GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw); mg.loadThis(); mg.invokeConstructor(Type.getType(Object.class), m); mg.returnValue(); mg.endMethod(); }}
    • 31. ASM samplepublic class ASMSample extends ClassLoader implements Opcodes {{ public static void main(String[] args) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(V1_1, ACC_PUBLIC, "SimpleProgram", null, "java/lang/Object", null); // creates a GeneratorAdapter for the (implicit) constructor Method m = Method.getMethod("void <init> ()"); GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw); mg.loadThis(); mg.invokeConstructor(Type.getType(Object.class), m); mg.returnValue(); mg.endMethod(); // creates a GeneratorAdapter for the main method m = Method.getMethod("void main (String[])"); mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw); mg.getStatic(Type.getType(System.class), "out",Type.getType(PrintStream.class)); mg.push("Hello Java Fusion!"); mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)")); mg.returnValue(); mg.endMethod(); cw.visitEnd(); }}
    • 32. ASM samplepublic class ASMSample extends ClassLoader implements Opcodes {{ public static void main(String[] args) { ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS); cw.visit(V1_1, ACC_PUBLIC, "SimpleProgram", null, "java/lang/Object", null); // creates a GeneratorAdapter for the (implicit) constructor Method m = Method.getMethod("void <init> ()"); GeneratorAdapter mg = new GeneratorAdapter(ACC_PUBLIC, m, null, null, cw); mg.loadThis(); mg.invokeConstructor(Type.getType(Object.class), m); mg.returnValue(); mg.endMethod(); // creates a GeneratorAdapter for the main method m = Method.getMethod("void main (String[])"); mg = new GeneratorAdapter(ACC_PUBLIC + ACC_STATIC, m, null, null, cw); mg.getStatic(Type.getType(System.class), "out",Type.getType(PrintStream.class)); mg.push("Hello Java Fusion!"); mg.invokeVirtual(Type.getType(PrintStream.class), Method.getMethod("void println (String)")); mg.returnValue(); mg.endMethod(); cw.visitEnd(); byte[] code = cw.toByteArray(); ASMSample loader = new ASMSample (); Class<?> exampleClass = loader.defineClass("SimpleProgram", code, 0, code.length); // uses the dynamically generated class to print Hello Java Fusion exampleClass.getMethods()[0].invoke(null, new Object[] { null } ); }}
    • 33. ASM vs. Javassist• Javassist source level API is much easier to use than theactual bytecode manipulation in ASM• Javassist provides a higher level abstraction layer over complexbytecode level operations. Javassist source level API requires very less orno knowledge of actual bytecodes, so much easier & faster toimplement.• Javassist uses reflection mechanism which makes it slowercompared to ASM which uses Classworking techniques at runtime.• Overall ASM is much faster & gives better performance thanJavassist. Javassist uses a simplified version of Java source code, whichit then compiles into bytecode. That makes Javassist very easy to use, butit also limits the use of bytecode to what can be expressed within the limitsof the Javassist source code.• In conclusion, if someone needs easier way of dynamicallymanipulating or creating Java classes Javassist API should be used &where the performance is the key issue ASM library should be used.
    • 34. JRebelRedeploying sucks, so JRebeleliminates it. How? JRebel maps your project workspace directly to the application under development. When you change any class or resource in your IDE, the change is immediately reflected in the application, skipping the build and redeploy phases.
    • 35. How JRebel works1) Classes• JRebel integrates with the JVM and rewrites each class to beupdateable• JRebel versions each class individually, instead of an application or module at a time• It does not use classloaders!• Changes to classes are always visible in the Reflection API
    • 36. How JRebel works2) Workspace mapping petclinic.war • JRebel integrates with application servers, frameworks and your IDE • When a class or resource is being looked up, JRebel redirects straight to the workspace • When an HTTP resource needs to be served, JRebel serves it from the workspace
    • 37. Size and speed issues
    • 38. Size and speed issuestop1 and top2 are functionally identical
    • 39. Size and speed issuesMethod int top1() 0 aload_0 //Push the object reference(this) at index //0 of the local variable table. 1 getfield #6 <Field int intArr[]> //Pop the object reference(this) and push //the object reference for intArr accessed //from the constant pool. 4 iconst_0 //Push 0. 5 iaload //Pop the top two values and push the //value at index 0 of intArr. 6 ireturn //Pop top value and push it on the operand //stack of the invoking method. Exit.
    • 40. Size and speed issuesMethod int top2() 0 aload_0 1 astore_2 2 aload_2 3 monitorenter 4 aload_0 5 getfield #6 <Field int intArr[]> 8 iconst_0 //Push 0. 9 iaload 10 istore_1 11 jsr 19 14 iload_1 . 15 ireturn 16 aload_2 17 monitorexit . Exception table: //If any exception occurs between 18 athrow . from to target type //location 4 (inclusive) and location 19 astore_3 4 16 16 any //16 (exclusive) jump to location 16 20 aload_2 21 monitorexit 22 ret 3.
    • 41. Size and speed issuestop1 and top2 are functionally identicaltop1 is 13% faster than top2 as well as much smaller.
    • 42. Puzzle Cutting Class public class Strange2 {public class Strange1 { public static void main(String[] args) { public static void main(String[] args) { Missing m; try { try { m = new Missing(); } catch Missing m = new Missing(); } catch (java.lang.NoClassDefFoundError ex) {(java.lang.NoClassDefFoundError ex) { System.out.println("Got it!"); System.out.println("Got it!"); } } } } } } class Missing { Missing() { } }
    • 43. Puzzle Cutting Class public class Strange2 {public class Strange1 { public static void main(String[] args) { public static void main(String[] args) { Missing m; try { try { m = new Missing(); } catch Missing m = new Missing(); } catch (java.lang.NoClassDefFoundError ex) {(java.lang.NoClassDefFoundError ex) { System.out.println("Got it!"); System.out.println("Got it!"); } } } } } } class Missing { Missing() { } }
    • 44. Puzzle Cutting Class public class Strange2 {public class Strange1 { public static void main(String[] args) { public static void main(String[] args) { Missing m; try { try { m = new Missing(); } catch Missing m = new Missing(); } catch (java.lang.NoClassDefFoundError ex) {(java.lang.NoClassDefFoundError ex) { System.out.println("Got it!"); System.out.println("Got it!"); } } } } } } class Missing { Missing() { } } ??? System.out.println("Got it!"); throws an uncaught NoClassDefFoundError
    • 45. Puzzle Cutting Class public class Strange2 {public class Strange1 { public static void main(String[] args) { public static void main(String[] args) { Missing m; try { try { m = new Missing(); } catch Missing m = new Missing(); } catch (java.lang.NoClassDefFoundError ex) {(java.lang.NoClassDefFoundError ex) { System.out.println("Got it!"); System.out.println("Got it!"); } } } } class Missing { Missing() { } } System.out.println("Got it!"); Expected throws an uncaught NoClassDefFoundError throws an uncaught Result System.out.println("Got it!"); NoClassDefFoundError
    • 46. Puzzle Cutting Class0: new #2; // class Missing3: dup4: invokespecial #3; // Method Missing."<init>":()V7: astore_18: goto 2011: astore_112: getstatic #5; // Field System.out:Ljava/io/PrintStream;15: ldc #6; // String "Got it!"17: invokevirtual #7; // Method PrintStream.println:(String;)V20: returnException table:from to target type 0 8 11 Class java/lang/NoClassDefFoundErrorThe corresponding code for Strange2.main differs in only one instruction:11: astore_2 //Store ex catch parameterjavap -c Strange1
    • 47. Using reflectionpublic class Strange { public static void main(String[] args) throws Exception { try { Object m = Class.forName("Missing").newInstance(); } catch (ClassNotFoundException ex) { System.err.println("Got it!"); } }}
    • 48. Benefits• Improve speed and size of your applications• Critical when debugging and doing performance and memory usage tuning• Realtime injection• Build ORM project• Clustering with AOP• Know your platform!• Create your own compile/decompiler?