class文件格式如下:
- 相信学java的人都对new Object();创建对象都很熟悉,但想要真正了解原理就没那么容易!以以下例子为例,解释class代码及执行过程,如有错误,还望各位高手多多指教!
- public class Dog {
- public String name;
- public int age;
- public Dog() {
- }
- public Dog(String name)
- {
- this.name = name;
- }
- public Dog(String name, int age)
- {
- this.name = name;
- this.age = age;
- }
- public static void getStaticValue(int j)
- {
- int i=j;
- System.out.println(i);
- }
- public void getValue(int j)
- {
- int i=j;
- System.out.println(i);
- }
- public static void main(String[] args) {
- try {
- new Dog().getValue(10);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- 如上代码很简单,main方法加上try catch只是为了 让大家看一下java文件生产字节码是怎么样的
- 执行javac Dog.java文件,生成class文件。然后使用javap -verbose Dog反编译出class代码。
- 生成如下代码:
- view plaincopy to clipboardprint?
- Compiled from "Dog.java"
- public class Dog extends java.lang.Object
- SourceFile: "Dog.java"
- minor version: 0 // minor version: major version:这两个是表示class文件的版本号,
- major version: 50 //详细见http://blog.csdn.net/xiaxiaorui2003/archive/2009/07/07/4327029.aspx这位兄弟的blog
- Constant pool: //常量池,如下以const开头的都是常量池信息,每个class文件都有一些常量池信息
- //当线程调用一个方法的时候,jvm会开辟一个帧出来,这个帧包括操作栈、局部变量列表、常量池的引用
- //如下以#开头的表示偏移量编号,相当于id号,接下来解释如下代码的作用
- 如下 #11.#31; 这段代码什么作用呢?很简单,就是表示创建Object对象。
- 首先来看.号左边的#11,找到常量池中#11,跳到const #11 = class #42; // java/lang/Object
- 这个表示是一个Object类型,class后面的 #42;表示接下来要跳到常量池中#42
- 找到const #42 = Asciz java/lang/Object; 表示生成Object类型
- 接下来看.号右边的#31。
- const #31 = NameAndType #16:#17; //解释:这里指定到#16 #17
- const #16 = Asciz <init>;
- const #17 = Asciz ()V; //解释:到这里完成初始化工作
- //NameAndType表示名字和类型 调用构造方法 的Name都是<init>, V表示没有返回值 ,() 括号里面是空的表示没有参数
- //到这里完成Dog
- //
- 如下有 :
- Method //方法
- Field //类名.属性
- class //类型
- Asciz //方法签名
- NameAndType //变量名和类型
- java类型对应的class文件方法签名的标识符:
- invokespecial //调用构造方法、父类方法
- invokevirtual //调用普通方法(非构造方法、static方法)
- invokestatic //调用static方法
- Ljava/lang/String;; //这表示String类型,这里要全路径,java/lang/String;;前面的L表示非java八大基本类型
- void V
- int char byte short long float double 都是类型第一个字母(大写)
- boolean 比较特别,用Z表示 ,因为B被byte给占用了
- const #1 = Method #11.#31; // java/lang/Object."<init>":()V 解释:初始化Object
- const #2 = Field #6.#32; // Dog.name:Ljava/lang/String; Dog类中定义的String name
- const #3 = Field #6.#33; // Dog.age:I Dog类中定义的int age
- const #4 = Field #34.#35; // java/lang/System.out:Ljava/io/PrintStream;
- const #5 = Method #36.#37; // java/io/PrintStream.println:(I)V 解释:调用println(int value), V表示返回值是void
- const #6 = class #38; // Dog
- const #7 = Method #6.#31; // Dog."<init>":()V 解释:初始化Dog,调用构造函数,"<init>"是初始化标识符, V表示返回值是void
- const #8 = Method #6.#39; // Dog.getValue:(I)V 解释:调用getValue(int j)方法, V表示返回值是void
- const #9 = class #40; // java/lang/Exception
- const #10 = Method #9.#41; // java/lang/Exception.printStackTrace:()V
- const #11 = class #42; // java/lang/Object
- const #12 = Asciz name;
- const #13 = Asciz Ljava/lang/String;;
- const #14 = Asciz age;
- const #15 = Asciz I;
- const #16 = Asciz <init>;
- const #17 = Asciz ()V;
- const #18 = Asciz Code;
- const #19 = Asciz LineNumberTable;
- const #20 = Asciz (Ljava/lang/String;)V;
- const #21 = Asciz (Ljava/lang/String;I)V;
- const #22 = Asciz getStaticValue;
- const #23 = Asciz (I)V;
- const #24 = Asciz getValue;
- const #25 = Asciz main;
- const #26 = Asciz ([Ljava/lang/String;)V;
- const #27 = Asciz StackMapTable;
- const #28 = class #40; // java/lang/Exception
- const #29 = Asciz SourceFile;
- const #30 = Asciz Dog.java;
- const #31 = NameAndType #16:#17;// "<init>":()V
- const #32 = NameAndType #12:#13;// name:Ljava/lang/String;
- const #33 = NameAndType #14:#15;// age:I
- const #34 = class #43; // java/lang/System
- const #35 = NameAndType #44:#45;// out:Ljava/io/PrintStream;
- const #36 = class #46; // java/io/PrintStream
- const #37 = NameAndType #47:#23;// println:(I)V
- const #38 = Asciz Dog;
- const #39 = NameAndType #24:#23;// getValue:(I)V
- const #40 = Asciz java/lang/Exception;
- const #41 = NameAndType #48:#17;// printStackTrace:()V
- const #42 = Asciz java/lang/Object;
- const #43 = Asciz java/lang/System;
- const #44 = Asciz out;
- const #45 = Asciz Ljava/io/PrintStream;;
- const #46 = Asciz java/io/PrintStream;
- const #47 = Asciz println;
- const #48 = Asciz printStackTrace;
- {
- public java.lang.String name;
- public int age;
- //如下的Locals表示方法内局部变量个数,该例中是1,有些人疑惑的是Dog()中明明没有参数啊,应该是0啊!
- //当线程调用一个方法的时候,jvm会开辟一个帧出来,这个帧包括操作栈、局部变量列表、常量池的引用
- //非static方法,在调用的时候都会给方法默认加上一个当前对象(this)类型的参数,不需要在方法中定义,
- //这个时候局部变量列表中index为0的位置保存的是this,其他索引号按变量定义顺序累加
- //static方法不依赖对象,所以不用传this
- //Args_size表示参数个数,public Dog();会传一个this进去,所以value是1
- public Dog();
- Code:
- Stack=1, Locals=1, Args_size=1
- 0: aload_0 //加载局部变量表index为0的变量,在这里是this
- 1: invokespecial #1; //Method java/lang/Object."<init>":()V //调用构造方法
- 4: return
- LineNumberTable:
- line 6: 0
- line 7: 4
- //这个构造方法与上个构造方法也是同理,只是多少个String参数和 给name赋值
- public Dog(java.lang.String);
- Code:
- Stack=2, Locals=2, Args_size=2
- 0: aload_0
- 1: invokespecial #1; //Method java/lang/Object."<init>":()V
- //这里的#1;表示对常量池的引用,创建一个类,必须先初始化父类,创建Dog之前创建Object
- 4: aload_0 //加载局部变量表index为0的变量,在这里是this
- 5: aload_1 //加载局部变量表index为1的变量,在这里是String name局部变量
- 6: putfield #2; //Field name:Ljava/lang/String; 赋值操作
- 9: return
- LineNumberTable:
- line 10: 0
- line 11: 4
- line 12: 9
- public Dog(java.lang.String, int);
- Code:
- Stack=2, Locals=3, Args_size=3
- 0: aload_0
- 1: invokespecial #1; //Method java/lang/Object."<init>":()V
- 4: aload_0
- 5: aload_1
- 6: putfield #2; //Field name:Ljava/lang/String;
- 9: aload_0
- 10: iload_2
- 11: putfield #3; //Field age:I
- 14: return
- LineNumberTable:
- line 15: 0
- line 16: 4
- line 17: 9
- line 18: 14
- //这里的Args_size=1,是因为是static方法,不会传进this
- public static void getStaticValue(int);
- Code:
- Stack=2, Locals=2, Args_size=1
- 0: iload_0
- 1: istore_1 //istore_1其实是是有两部分组成,i表示int类型 ,1表示局部变量表中index为1。那合起来就是存储在局部变量表中,index为1的位置
- 2: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream; //引用常量池 #4;
- 5: iload_1
- 6: invokevirtual #5; //Method java/io/PrintStream.println:(I)V //引用常量池 #5;
- 9: return
- LineNumberTable:
- line 21: 0
- line 22: 2
- line 23: 9
- public void getValue(int);
- Code:
- Stack=2, Locals=3, Args_size=2
- 0: iload_1
- 1: istore_2
- 2: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
- 5: iload_2
- 6: invokevirtual #5; //Method java/io/PrintStream.println:(I)V
- 9: return
- LineNumberTable:
- line 26: 0
- line 27: 2
- line 28: 9
- public static void main(java.lang.String[]);
- Code:
- Stack=2, Locals=2, Args_size=1
- 0: new #6; //class Dog 解释:创建Dog
- 3: dup //复制引用到stack(栈)
- 4: invokespecial #7; //Method "<init>":()V
- 7: bipush 10 //压入一个常量10
- 9: invokevirtual #8; //Method getValue:(I)V
- 12: goto 20
- 15: astore_1
- 16: aload_1
- 17: invokevirtual #10; //Method java/lang/Exception.printStackTrace:()V
- 20: return
- Exception table:
- from to target type
- 0 12 15 Class java/lang/Exception //表示上面代码从1到12行之间如果发生Exception异常就goto到15处
- LineNumberTable:
- line 32: 0
- line 35: 12
- line 33: 15
- line 34: 16
- line 36: 20
- //如下这块我不太理解什么意思,加了try catch之后才出现这个的,还有如上的 Stack= ,
- //这个不知道是什么意思,暂没有领悟 ,望高手指导
- StackMapTable: number_of_entries = 2
- frame_type = 79 /* same_locals_1_stack_item */
- stack = [ class java/lang/Exception ]
- frame_type = 4 /* same */
- }
相信学java的人都对new Object();创建对象都很熟悉,但想要真正了解原理就没那么容易!以以下例子为例,解释class代码及执行过程,如有错误,还望各位高手多多指教!
public class Dog {
public String name;
public int age;
public Dog() {
}
public Dog(String name)
{
this.name = name;
}
public Dog(String name, int age)
{
this.name = name;
this.age = age;
}
public static void getStaticValue(int j)
{
int i=j;
System.out.println(i);
}
public void getValue(int j)
{
int i=j;
System.out.println(i);
}
public static void main(String[] args) {
try {
new Dog().getValue(10);
} catch (Exception e) {
e.printStackTrace();
}
}
}
如上代码很简单,main方法加上try catch只是为了 让大家看一下java文件生产字节码是怎么样的
执行javac Dog.java文件,生成class文件。然后使用javap -verbose Dog反编译出class代码。
生成如下代码:
view plaincopy to clipboardprint?
Compiled from "Dog.java"
public class Dog extends java.lang.Object
SourceFile: "Dog.java"
minor version: 0 // minor version: major version:这两个是表示class文件的版本号,
major version: 50 //详细见http://blog.csdn.net/xiaxiaorui2003/archive/2009/07/07/4327029.aspx这位兄弟的blog
Constant pool: //常量池,如下以const开头的都是常量池信息,每个class文件都有一些常量池信息
//当线程调用一个方法的时候,jvm会开辟一个帧出来,这个帧包括操作栈、局部变量列表、常量池的引用
//如下以#开头的表示偏移量编号,相当于id号,接下来解释如下代码的作用
如下 #11.#31; 这段代码什么作用呢?很简单,就是表示创建Object对象。
首先来看.号左边的#11,找到常量池中#11,跳到const #11 = class #42; // java/lang/Object
这个表示是一个Object类型,class后面的 #42;表示接下来要跳到常量池中#42
找到const #42 = Asciz java/lang/Object; 表示生成Object类型
接下来看.号右边的#31。
const #31 = NameAndType #16:#17; //解释:这里指定到#16 #17
const #16 = Asciz <init>;
const #17 = Asciz ()V; //解释:到这里完成初始化工作
//NameAndType表示名字和类型 调用构造方法 的Name都是<init>, V表示没有返回值 ,() 括号里面是空的表示没有参数
//到这里完成Dog
//
如下有 :
Method //方法
Field //类名.属性
class //类型
Asciz //方法签名
NameAndType //变量名和类型
java类型对应的class文件方法签名的标识符:
invokespecial //调用构造方法、父类方法
invokevirtual //调用普通方法(非构造方法、static方法)
invokestatic //调用static方法
Ljava/lang/String;; //这表示String类型,这里要全路径,java/lang/String;;前面的L表示非java八大基本类型
void V
int char byte short long float double 都是类型第一个字母(大写)
boolean 比较特别,用Z表示 ,因为B被byte给占用了
const #1 = Method #11.#31; // java/lang/Object."<init>":()V 解释:初始化Object
const #2 = Field #6.#32; // Dog.name:Ljava/lang/String; Dog类中定义的String name
const #3 = Field #6.#33; // Dog.age:I Dog类中定义的int age
const #4 = Field #34.#35; // java/lang/System.out:Ljava/io/PrintStream;
const #5 = Method #36.#37; // java/io/PrintStream.println:(I)V 解释:调用println(int value), V表示返回值是void
const #6 = class #38; // Dog
const #7 = Method #6.#31; // Dog."<init>":()V 解释:初始化Dog,调用构造函数,"<init>"是初始化标识符, V表示返回值是void
const #8 = Method #6.#39; // Dog.getValue:(I)V 解释:调用getValue(int j)方法, V表示返回值是void
const #9 = class #40; // java/lang/Exception
const #10 = Method #9.#41; // java/lang/Exception.printStackTrace:()V
const #11 = class #42; // java/lang/Object
const #12 = Asciz name;
const #13 = Asciz Ljava/lang/String;;
const #14 = Asciz age;
const #15 = Asciz I;
const #16 = Asciz <init>;
const #17 = Asciz ()V;
const #18 = Asciz Code;
const #19 = Asciz LineNumberTable;
const #20 = Asciz (Ljava/lang/String;)V;
const #21 = Asciz (Ljava/lang/String;I)V;
const #22 = Asciz getStaticValue;
const #23 = Asciz (I)V;
const #24 = Asciz getValue;
const #25 = Asciz main;
const #26 = Asciz ([Ljava/lang/String;)V;
const #27 = Asciz StackMapTable;
const #28 = class #40; // java/lang/Exception
const #29 = Asciz SourceFile;
const #30 = Asciz Dog.java;
const #31 = NameAndType #16:#17;// "<init>":()V
const #32 = NameAndType #12:#13;// name:Ljava/lang/String;
const #33 = NameAndType #14:#15;// age:I
const #34 = class #43; // java/lang/System
const #35 = NameAndType #44:#45;// out:Ljava/io/PrintStream;
const #36 = class #46; // java/io/PrintStream
const #37 = NameAndType #47:#23;// println:(I)V
const #38 = Asciz Dog;
const #39 = NameAndType #24:#23;// getValue:(I)V
const #40 = Asciz java/lang/Exception;
const #41 = NameAndType #48:#17;// printStackTrace:()V
const #42 = Asciz java/lang/Object;
const #43 = Asciz java/lang/System;
const #44 = Asciz out;
const #45 = Asciz Ljava/io/PrintStream;;
const #46 = Asciz java/io/PrintStream;
const #47 = Asciz println;
const #48 = Asciz printStackTrace;
{
public java.lang.String name;
public int age;
//如下的Locals表示方法内局部变量个数,该例中是1,有些人疑惑的是Dog()中明明没有参数啊,应该是0啊!
//当线程调用一个方法的时候,jvm会开辟一个帧出来,这个帧包括操作栈、局部变量列表、常量池的引用
//非static方法,在调用的时候都会给方法默认加上一个当前对象(this)类型的参数,不需要在方法中定义,
//这个时候局部变量列表中index为0的位置保存的是this,其他索引号按变量定义顺序累加
//static方法不依赖对象,所以不用传this
//Args_size表示参数个数,public Dog();会传一个this进去,所以value是1
public Dog();
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0 //加载局部变量表index为0的变量,在这里是this
1: invokespecial #1; //Method java/lang/Object."<init>":()V //调用构造方法
4: return
LineNumberTable:
line 6: 0
line 7: 4
//这个构造方法与上个构造方法也是同理,只是多少个String参数和 给name赋值
public Dog(java.lang.String);
Code:
Stack=2, Locals=2, Args_size=2
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
//这里的#1;表示对常量池的引用,创建一个类,必须先初始化父类,创建Dog之前创建Object
4: aload_0 //加载局部变量表index为0的变量,在这里是this
5: aload_1 //加载局部变量表index为1的变量,在这里是String name局部变量
6: putfield #2; //Field name:Ljava/lang/String; 赋值操作
9: return
LineNumberTable:
line 10: 0
line 11: 4
line 12: 9
public Dog(java.lang.String, int);
Code:
Stack=2, Locals=3, Args_size=3
0: aload_0
1: invokespecial #1; //Method java/lang/Object."<init>":()V
4: aload_0
5: aload_1
6: putfield #2; //Field name:Ljava/lang/String;
9: aload_0
10: iload_2
11: putfield #3; //Field age:I
14: return
LineNumberTable:
line 15: 0
line 16: 4
line 17: 9
line 18: 14
//这里的Args_size=1,是因为是static方法,不会传进this
public static void getStaticValue(int);
Code:
Stack=2, Locals=2, Args_size=1
0: iload_0
1: istore_1 //istore_1其实是是有两部分组成,i表示int类型 ,1表示局部变量表中index为1。那合起来就是存储在局部变量表中,index为1的位置
2: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream; //引用常量池 #4;
5: iload_1
6: invokevirtual #5; //Method java/io/PrintStream.println:(I)V //引用常量池 #5;
9: return
LineNumberTable:
line 21: 0
line 22: 2
line 23: 9
public void getValue(int);
Code:
Stack=2, Locals=3, Args_size=2
0: iload_1
1: istore_2
2: getstatic #4; //Field java/lang/System.out:Ljava/io/PrintStream;
5: iload_2
6: invokevirtual #5; //Method java/io/PrintStream.println:(I)V
9: return
LineNumberTable:
line 26: 0
line 27: 2
line 28: 9
public static void main(java.lang.String[]);
Code:
Stack=2, Locals=2, Args_size=1
0: new #6; //class Dog 解释:创建Dog
3: dup //复制引用到stack(栈)
4: invokespecial #7; //Method "<init>":()V
7: bipush 10 //压入一个常量10
9: invokevirtual #8; //Method getValue:(I)V
12: goto 20
15: astore_1
16: aload_1
17: invokevirtual #10; //Method java/lang/Exception.printStackTrace:()V
20: return
Exception table:
from to target type
0 12 15 Class java/lang/Exception //表示上面代码从1到12行之间如果发生Exception异常就goto到15处
LineNumberTable:
line 32: 0
line 35: 12
line 33: 15
line 34: 16
line 36: 20
//如下这块我不太理解什么意思,加了try catch之后才出现这个的,还有如上的 Stack= ,
//这个不知道是什么意思,暂没有领悟 ,望高手指导
StackMapTable: number_of_entries = 2
frame_type = 79 /* same_locals_1_stack_item */
stack = [ class java/lang/Exception ]
frame_type = 4 /* same */
}