Sunday, October 15, 2017

[JVM-1] Byte code file structure

Java byte code has a structure so that the virtual machine knows where to look for which information. Usually, an assembly program has the following structure.
Data segment:
  //goes constant
  //array initialization and declaration
  //global variables
Code segment:
  //several sub routines that act on top of the data segment.

Byte Code File Structure:
Byte code has similar structure. It's Data segment follows a very specific format.
  Class_File_Format {
     u4 magic_number;

     u2 minor_version; 
     u2 major_version;

     u2 constant_pool_count; 
   
     cp_info constant_pool[constant_pool_count - 1];

     u2 access_flags;

     u2 this_class;
     u2 super_class;

     u2 interfaces_count; 
   
     u2 interfaces[interfaces_count];

     u2 fields_count; 
     field_info fields[fields_count];

     u2 methods_count;
     method_info methods[methods_count];

     u2 attributes_count; 
     attribute_info attributes[attributes_count];
  }

constant pool is one of the main parts of the bytecode file. It hold's the constants, variable names, method names, interfaces this class implements etc.

One interesting this is the magic number at the beginning for any java byte code file is always OxCAFEBABE. JVM won't read this file if this magic number is not found at the begin.

Constructors:
In byte code files, constructors are treated differently. All the constructors are replaced by a bytecode method <init> (parameters).

// In source packet in file init/ex8/CoffeeCup.java
class CoffeeCup {
    public CoffeeCup() {
        //...
    }
    public CoffeeCup(int amount) {
        //...
    }
    // ...
}
the compiler would generate the following two instance initialization methods in the class file for class CoffeeCup, one for each constructor in the source file:

// In binary form in file init/ex8/CoffeeCup.class:
public void <init>(CoffeeCup this) {...}
public void <init>(CoffeeCup this, int amount) {...}

Reading byte code
java Test.java  ==> produces Test.class
xxd Test.class  ==> reads byte codes of the class
javap -verbose Test.class ==> view the constant pool area
javap -c Test.class  ==> only shows the instructions

Example:
  class Test{
    public static void main(String args[]){
      int i = 0;
      int j = 1;
      for(i = 0; i < 10; i++){
        j = j + 1;
      }
    }
  }

  javap -verbose Test.class output is following
    Classfile /Users/sa050870/Desktop/blog/javacompile/Test.class
    Last modified Oct 3, 2017; size 325 bytes
    MD5 checksum e48f946daadcae98c0ce5bcc07ac8094
    Compiled from "Test.java"
  class Test
    minor version: 0
    major version: 52
    flags: ACC_SUPER
  Constant pool:
     #1 = Methodref          #3.#13         // java/lang/Object."<init>":()V
     #2 = Class              #14            // Test
     #3 = Class              #15            // java/lang/Object
     #4 = Utf8               <init>
     #5 = Utf8               ()V
     #6 = Utf8               Code
     #7 = Utf8               LineNumberTable
     #8 = Utf8               main
     #9 = Utf8               ([Ljava/lang/String;)V
    #10 = Utf8               StackMapTable
    #11 = Utf8               SourceFile
    #12 = Utf8               Test.java
    #13 = NameAndType        #4:#5          // "<init>":()V
    #14 = Utf8               Test
    #15 = Utf8               java/lang/Object
  {
    Test();
      descriptor: ()V
      flags:
      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

    public static void main(java.lang.String[]);
      descriptor: ([Ljava/lang/String;)V
      flags: ACC_PUBLIC, ACC_STATIC
      Code:
        stack=2, locals=3, args_size=1
           0: iconst_0
           1: istore_1
           2: iconst_1
           3: istore_2
           4: iconst_0
           5: istore_1
           6: iload_1
           7: bipush        10
           9: if_icmpge     22
          12: iload_2
          13: iconst_1
          14: iadd
          15: istore_2
          16: iinc          1, 1
          19: goto          6
          22: return
        LineNumberTable:
          line 3: 0
          line 4: 2
          line 5: 4
          line 6: 12
          line 5: 16
          line 8: 22
        StackMapTable: number_of_entries = 2
          frame_type = 253 /* append */
            offset_delta = 6
            locals = [ int, int ]
          frame_type = 15 /* same */
  }
  SourceFile: "Test.java"
 

Reference
[0] object initialization in java. https://www.javaworld.com/article/2076614/core-java/object-initialization-in-java.html
[1] hacking java byte code. https://www.acloudtree.com/hacking-java-bytecode-for-programmers-part3-yes-disassemble-with-javap-all-over-the-place/
[2] Inside the Java 2 virtual machine. Bill Venners. http://www.artima.com/insidejvm/ed2/
[3] Java class file architecture, wikipedia. https://en.wikipedia.org/wiki/Java_class_file
[4] JVM specification. https://docs.oracle.com/javase/specs/jvms/se7/html/index.html

start from here https://www.javaworld.com/article/2076614/core-java/object-initialization-in-java.html?page=2

No comments:

Post a Comment