java虚拟机 实例_深入java虚拟机--Class文件实例解析

前面发了几篇学习笔记,但是看这些东西总是感觉很"玄乎",来一篇实战的东西来揭一下"JVM"的面纱,让"SSH"时代的童鞋们来熟悉一下Java的"老祖爷"JVM。由于自己的水平有限,所以大家在看过程中发了什么问题,或者您有什么疑问请及时提出来,我及时解决。如果您有什么建议,那么更好大家一块讨论。

1. 源码文件

public class LearningClassFile {

//普通变量

private int id1;

//静态变量

private static int id2;

//常量

private final int id3 = 4;

//静态常量

private static final int id4 = 5;

public LearningClassFile() {

}

public LearningClassFile(int id1, int id2) {

this.id1 = id1;

this.id2 = id2;

}

//使用public修饰的addPub方法

public void addPub(int a, int b) {

int result = a + b;

System.out.println(result);

}

//使用private修饰的addPri方法

private void addPri(int a, int b) {

int result = a + b;

System.out.println(result);

}

//使用static修饰的方法

public static void addSta() {

int result = id2 + id4;

System.out.println(result);

}

public static final void addFinal(int a, int b) {

int result = a + b;

System.out.println(result);

}

public static void main(String[] args) {

LearningClassFile lcf = new LearningClassFile(1, 2);

lcf.addPub(1, 2);

lcf.addPri(1, 2);

addSta();

addFinal(1, 2);

}

}

Class文件:

Compiled from "LearningClassFile.java"

public class LearningClassFile extends java.lang.Object

SourceFile: "LearningClassFile.java"

minor version: 0

major version: 50

//运行时常量池:用于存放编译期生成的各种字面量和符号引用。

Constant pool:

//从父类Object继承的默认构造方法

//观察该方法的特征:无参,返回类型void

const #1 = Method #13.#35; // java/lang/Object."":()V

//常量id3

//"#7.#36; // LearningClassFile.id3:I"

//#7:查找常量池中的类名LearningClassFile

//#36-->"const #36 = NameAndType #17:#15;// id3:I"

//NameAndType字面的意思是名称和类型。即id3是变量的名称,I表示id3是int类型

//综合描述:LearningClassFile中的id3是int类型

const #2 = Field #7.#36; // LearningClassFile.id3:I

const #3 = Field #7.#37; // LearningClassFile.id1:I

const #4 = Field #7.#38; // LearningClassFile.id2:I

//将System的out存储至常量池

//System类中out被public static final修饰的

//"public final static PrintStream out = nullPrintStream();"

//综合描述:System类的out属性是PrintStream类型

const #5 = Field #39.#40; // java/lang/System.out:Ljava/io/PrintS

tream;

//将PrintStream的Println()方法存储至常量池

//该方法的参数为I,返回值为void

const #6 = Method #41.#42; // java/io/PrintStream.println:(I)V

//类LearningClassFIle

const #7 = class #43; // LearningClassFile

//构造函数

//该构造函数需传入两个int类型的变量

const #8 = Method #7.#44; // LearningClassFile."":(II)V

//LearningClassFile的addPub方法

//#4-->"const #45 = NameAndType #27:#26;// addPub:(II)V"

//#27-->"const #27 = Asciz addPub;" 方法的名称为:addPub

//#26-->"const #26 = Asciz (II)V;" 方法的类型:两个int类型的参数,返回类型为void

const #9 = Method #7.#45; // LearningClassFile.addPub:(II)V

const #10 = Method #7.#46; // LearningClassFile.addPri:(II)V

const #11 = Method #7.#47; // LearningClassFile.addSta:()V

const #12 = Method #7.#48; // LearningClassFile.addFinal:(II)V

const #13 = class #49; // java/lang/Object

const #14 = Asciz id1;

const #15 = Asciz I;

const #16 = Asciz id2;

const #17 = Asciz id3;

//ConstantValue属性表示一个常量字段的值

//即final修饰的属性

const #18 = Asciz ConstantValue;

//对于final修饰的常量直接将类型和值存入常量池

const #19 = int 4;

const #20 = Asciz id4;

const #21 = int 5;

const #22 = Asciz ;

const #23 = Asciz ()V;

//Code属性只为唯一一个方法、实例类初始化方法或类初始化方法保存Java虚拟机指令及相关辅助信息

//简而言之:保存方法编译后的指令信息

const #24 = Asciz Code;

//java源码行号与编译后的字节码指令的对应表

const #25 = Asciz LineNumberTable;

const #26 = Asciz (II)V;

const #27 = Asciz addPub;

const #28 = Asciz addPri;

const #29 = Asciz addSta;

const #30 = Asciz addFinal;

const #31 = Asciz main;

const #32 = Asciz ([Ljava/lang/String;)V;

//java 源码文件

const #33 = Asciz SourceFile;

const #34 = Asciz LearningClassFile.java;

const #35 = NameAndType #22:#23;// "":()V

const #36 = NameAndType #17:#15;// id3:I

const #37 = NameAndType #14:#15;// id1:I

const #38 = NameAndType #16:#15;// id2:I

const #39 = class #50; // java/lang/System

const #40 = NameAndType #51:#52;// out:Ljava/io/PrintStream;

const #41 = class #53; // java/io/PrintStream

const #42 = NameAndType #54:#55;// println:(I)V

const #43 = Asciz LearningClassFile;

const #44 = NameAndType #22:#26;// "":(II)V

const #45 = NameAndType #27:#26;// addPub:(II)V

const #46 = NameAndType #28:#26;// addPri:(II)V

const #47 = NameAndType #29:#23;// addSta:()V

const #48 = NameAndType #30:#26;// addFinal:(II)V

const #49 = Asciz java/lang/Object;

const #50 = Asciz java/lang/System;

const #51 = Asciz out;

const #52 = Asciz Ljava/io/PrintStream;;

const #53 = Asciz java/io/PrintStream;

const #54 = Asciz println;

const #55 = Asciz (I)V;

{

//默认构造方法

public LearningClassFile();

Code:

Stack=2, Locals=1, Args_size=1

0: aload_0

1: invokespecial #1; //Method java/lang/Object."":()V

//将id3的引用推送至栈顶

4: aload_0

//将4推送至栈顶

5: iconst_4

//将4赋值给id3

6: putfield #2; //Field id3:I

9: return

LineNumberTable:

line 11: 0 //public LearningClassFile() {

//对于final类型的实例变量在每个构造方法中都会进行一次初始化。

line 7: 4 // private final int id3 = 4;

line 12: 9 //}

public LearningClassFile(int, int);

Code:

Stack=2, Locals=3, Args_size=3

0: aload_0

1: invokespecial #1; //Method java/lang/Object."":()V

4: aload_0

5: iconst_4

6: putfield #2; //Field id3:I

9: aload_0

10: iload_1

11: putfield #3; //Field id1:I

14: aload_0

15: pop

16: iload_2

17: putstatic #4; //Field id2:I

20: return

LineNumberTable:

line 14: 0 //public LearningClassFile(int id1, int id2) {

//对于final类型的实例变量在每个构造方法中都会进行一次初始化。

line 7: 4 // private final int id3 = 4;

line 15: 9 // this.id1 = id1;

line 16: 14 // this.id2 = id2;

line 17: 20 //}

public void addPub(int, int);

Code:

Stack=2, Locals=4, Args_size=3

0: iload_1

1: iload_2

2: iadd

3: istore_3

4: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;

7: iload_3

8: invokevirtual #6; //Method java/io/PrintStream.println:(I)V

11: return

LineNumberTable:

line 21: 0 // int result = a + b;

line 22: 4 // System.out.println(result);

line 23: 11 // }

public static void addSta();

Code:

Stack=2, Locals=1, Args_size=0

//获取静态变量id2推送至栈顶

0: getstatic #4; //Field id2:I

//直接从常量池中取出id4的值5推送至栈顶

3: iconst_5

//执行相加操作

4: iadd

//将计算结果推送至栈顶

5: istore_0

//获取静态与out

6: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;

//取出计算结果

9: iload_0

//调用println方法

10: invokevirtual #6; //Method java/io/PrintStream.println:(I)V

//方法正常结束

13: return

LineNumberTable:

line 33: 0 // int result = id2 + id4;

line 34: 6 // System.out.println(result);

line 35: 13 //}

public static final void addFinal(int, int);

Code:

Stack=2, Locals=3, Args_size=2

0: iload_0

1: iload_1

2: iadd

3: istore_2

4: getstatic #5; //Field java/lang/System.out:Ljava/io/PrintStream;

7: iload_2

8: invokevirtual #6; //Method java/io/PrintStream.println:(I)V

11: return

LineNumberTable:

line 38: 0

line 39: 4

line 40: 11

public static void main(java.lang.String[]);

Code:

Stack=4, Locals=2, Args_size=1

//创建一个LearningClassFile对象,并将对象的引用推送至栈顶

0: new #7; //class LearningClassFile

//将对象的引用进行备份推送至栈顶

//使用原有的引用值调用实例方法,现在置于栈顶的引用值的位置将被接下来的操作覆盖。

3: dup

//将构造函数中的参数1推送至栈顶

4: iconst_1

5: iconst_2

//执行构造方法

6: invokespecial #8; //Method "":(II)V

//将栈顶引用型数值存入第二个本地变量

9: astore_1

10: aload_1

11: iconst_1

12: iconst_2

//调用实例方法

13: invokevirtual #9; //Method addPub:(II)V

16: aload_1

17: iconst_1

18: iconst_2

19: invokespecial #10; //Method addPri:(II)V

//调用静态方法

22: invokestatic #11; //Method addSta:()V

25: iconst_1

26: iconst_2

27: invokestatic #12; //Method addFinal:(II)V

30: return

LineNumberTable:

line 43: 0 // LearningClassFile lcf = new LearningClassFile(1, 2);

line 44: 10 // lcf.addPub(1, 2);

line 45: 16 // lcf.addPri(1, 2);

line 46: 22 // addSta();

line 47: 25 // addFinal(1, 2);

line 48: 30 //}

}

final变量和static final变量的区别:

1. 实例常量和类常量的区别

2. 初识方式不同:从class字节码来看final修饰的变量会出现在每个构造方法中进行一次初始化;static final类型的变量必须在定义的时候进行初始化。

理解"编译期可知,运行期不变": 编译器可确定调用方法的版本,符合这个标准的方法主要有两种:私有方法,静态方法。详情请看:深入理解JVM读书笔记--字节码执行引擎。

2. final变量和static final变量的区别: (1) 实例常量和类常量的区别 (2) 初始化方式不同:从class字节码来看final修饰的变量会出现在每个构造方法中进行一次初始化;static final类型的变量必须在定义的时候进行初始化。

3. 理解"编译期可知,运行期不变": 编译器可确定调用方法的版本,符合这个标准的方法主要有两种:私有方法,静态方法。详情请看:深入理解JVM读书笔记--字节码执行引擎。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值