Reference: http://viralpatel.net/blogs/tutorial-java-class-file-format-revealed/
A Java class file is consist of 10 basic sections:
1.Magic Number: 0xCAFEBABE
2.Version of Class File Format: the minor and major versions of the class file
3.Constant Pool: Pool of constants for the class
4.Access Flags: for example whether the class is abstract, static, etc.
5.This Class: The name of the current class
6.Super Class: The name of the super class
7.Interfaces: Any interfaces in the class
8.Fields: Any fields in the class
9.Methods: Any methods in the class
10.Attributes: Any attributes of the class (for example the name of the sourcefile, etc.)
You can remember the 10 sections with some funny mnemonic: My Very Cute Animal Turns Savage In Full Moon Areas.
Create JavapTest class as below:
public class JavapTip {
public static void main(String []args) {
}
private static String withStrings(int count) {
String s ="";
for (int i = 0; i < count; i++) {
s += i;
}
return s;
}
private static String withStringBuffer(int count) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < count; i++) {
sb.append(i);
}
return sb.toString();
}
}
Complie:
C:\Program Files\Java\JavaTip>javac JavapTip.java
C:\Program Files\Java\JavaTip>javap -verbose JavapTip
Compiled from "JavapTip.java"
public class JavapTip extends java.lang.Object
SourceFile: "JavapTip.java"
minor version: 0
major version: 50
Constant pool:
const #1 = Method #13.#28; // java/lang/Object."<init>":()V
const #2 = String #29; //
const #3 = class #30; // java/lang/StringBuilder
const #4 = Method #3.#28; // java/lang/StringBuilder."<init>":()V
const #5 = Method #3.#31; // java/lang/StringBuilder.append:(Ljava/lang/S
tring;)Ljava/lang/StringBuilder;
const #6 = Method #3.#32; // java/lang/StringBuilder.append:(I)Ljava/lang
/StringBuilder;
const #7 = Method #3.#33; // java/lang/StringBuilder.toString:()Ljava/lan
g/String;
const #8 = class #34; // java/lang/StringBuffer
const #9 = Method #8.#28; // java/lang/StringBuffer."<init>":()V
const #10 = Method #8.#35; // java/lang/StringBuffer.append:(I)Ljava/lang/
StringBuffer;
const #11 = Method #8.#33; // java/lang/StringBuffer.toString:()Ljava/lang
/String;
const #12 = class #36; // JavapTip
const #13 = class #37; // java/lang/Object
const #14 = Asciz <init>;
const #15 = Asciz ()V;
const #16 = Asciz Code;
const #17 = Asciz LineNumberTable;
const #18 = Asciz main;
const #19 = Asciz ([Ljava/lang/String;)V;
const #20 = Asciz withStrings;
const #21 = Asciz (I)Ljava/lang/String;;
const #22 = Asciz StackMapTable;
const #23 = class #38; // java/lang/String
const #24 = Asciz withStringBuffer;
const #25 = class #34; // java/lang/StringBuffer
const #26 = Asciz SourceFile;
const #27 = Asciz JavapTip.java;
const #28 = NameAndType #14:#15;// "<init>":()V
const #29 = Asciz ;
const #30 = Asciz java/lang/StringBuilder;
const #31 = NameAndType #39:#40;// append:(Ljava/lang/String;)Ljava/lang/String
Builder;
const #32 = NameAndType #39:#41;// append:(I)Ljava/lang/StringBuilder;
const #33 = NameAndType #42:#43;// toString:()Ljava/lang/String;
const #34 = Asciz java/lang/StringBuffer;
const #35 = NameAndType #39:#44;// append:(I)Ljava/lang/StringBuffer;
const #36 = Asciz JavapTip;
const #37 = Asciz java/lang/Object;
const #38 = Asciz java/lang/String;
const #39 = Asciz append;
const #40 = Asciz (Ljava/lang/String;)Ljava/lang/StringBuilder;;
const #41 = Asciz (I)Ljava/lang/StringBuilder;;
const #42 = Asciz toString;
const #43 = Asciz ()Ljava/lang/String;;
const #44 = Asciz (I)Ljava/lang/StringBuffer;;
{
public JavapTip();
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[]);
Code:
Stack=0, Locals=1, Args_size=1
0: return
LineNumberTable:
line 3: 0
}
Magic number is used to uniquely identify the format and to distinguish it from other formats. The first four bytes of the Class file are 0xCAFEBABE.
The next four byte of the class file contains major and minor version numbers. This number allows the JVM to verify and identify the class file. If the number is greater than what JVM can load, the class file will be rejected with error java.lang.UnsupportedClassVersionError.
You can find class version of any Java class file using javap command line utility. For example
javap -verbose JavaTip
Compiled from "JavapTip.java"
public class JavapTip extends java.lang.Object
SourceFile: "JavapTip.java"
minor version: 0
major version: 50
Below is the list of Major versions and corresponding JDK version of class file.
Major Version Hex JDK version
51 0×33 J2SE 7
50 0×32 J2SE 6.0
49 0×31 J2SE 5.0
48 0×30 JDK 1.4
47 0x2F JDK 1.3
46 0x2E JDK 1.2
45 0x2D JDK 1.1
All the constants related to the Class or an Interface will get stored in the Constant Pool.The constants includes class names, variable names, interface names, method names and signature, final variable values, string literals etc.
The constants are stored as a variable length array element in the Constant pool. The arrays of constants are preceded by its array size, hence JVM knows how many constants it will expect while loading the class file. In above diagram, the portion represented in green contains the size of the array.
Within each array elements first byte represents a tag specifying the type of constant at that position in the array. In above diagram the portion in orange represent the one-byte tag. JVM identifies the type of the constant by reading one-byte tag. Hence if one-byte tag represents a String literal then JVM knows that next 2 bytes represents length of the String literal and rest of the entry is string literal itself.
You can analyse the Constant Pool of any class file using javap command. Executing javap on above Main class, we get following symbol table.
C:\>javap -verbose Main
Compiled from "Main.java"
public class Main extends java.lang.Object
SourceFile: "Main.java"
minor version: 0
major version: 50
Constant pool:
const #1 = Method #4.#13; // java/lang/Object."<init>":()V
const #2 = int 16707053;
const #3 = class #14; // Main
const #4 = class #15; // java/lang/Object
const #5 = Asciz <init>;
const #6 = Asciz ()V;
const #7 = Asciz Code;
const #8 = Asciz LineNumberTable;
const #9 = Asciz main;
const #10 = Asciz ([Ljava/lang/String;)V;
const #11 = Asciz SourceFile;
const #12 = Asciz Main.java;
const #13 = NameAndType #5:#6;// "<init>":()V
const #14 = Asciz Main;
const #15 = Asciz java/lang/Object;
The constant pool has 15 entries in total. Entry #1 is Method public static void main; #2 is for integer value 0xFEEDED (decimal 16707053). Also we have two entries #3 and #4 which corresponds to this class and super class. Rest is the symbol table storing string literals.
Access flags follows the Constant Pool. It is a two byte entry that indicates whether the file defines a class or an interface, whether it is public or abstract or final in case it is a class. Below is a list of some of the access flags and their interpretation.
Flag Name Value Interpretation
ACC_PUBLIC 0x0001 Declared public; may be accessed from outside its package.
ACC_FINAL 0x0010 Declared final; no subclasses allowed.
ACC_SUPER 0x0020 Treat superclass methods specially when invoked by the invokespecial instruction.
ACC_INTERFACE 0x0200 Is an interface, not a class.
ACC_ABSTRACT 0x0400 Declared abstract; may not be instantiated.
This Class is a two byte entry that points to an index in Constant Pool. In above diagram, this class has a value 0x0007 which is an index in Constant Pool. The corresponding entry that is pointed by this class Constant_pool[this_class] in Constant pool has two parts, first part is the one-byte tag that represents the type of entry in constant pool, in this case it is Class or Interface. In above diagram this is shown inorange color. And second entry is two-byte having index again in Constant pool. This above diagram, two byte contain value 0x0004. Thus it points to Constant_poo [0x0004] which is the String literal having name of the interface or class
First two bytes in Attribute section is count of the number of attributes, followed by the attributes themselves. The JVMs will ignore any attributes they don't understand.
为了让大家深入理解基于Java字节码的应用,大家可以研究如下Java字节码的开源库(这些开源库都是在充分理解Java字节码类文件格式的基础上编写的):
□ BCEL,http://jakarta.apache.org/bcel/
□ ASM,http://asm.ow2.org/
□ CGLib,http://cglib.sourceforge.net/