如何解析Java虚拟机的Class文件
发表于:2024-11-18 作者:千家信息网编辑
千家信息网最后更新 2024年11月18日,这篇文章给大家介绍如何解析Java虚拟机的Class文件,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对大家能有所帮助。前面发了几篇学习笔记,但是看这些东西总是感觉很"玄乎",来一篇实战的东西来揭
千家信息网最后更新 2024年11月18日如何解析Java虚拟机的Class文件
这篇文章给大家介绍如何解析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、理解"编译期可知,运行期不变":
编译器可确定调用方法的版本,符合这个标准的方法主要有两种:私有方法,静态方法。
关于如何解析Java虚拟机的Class文件就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。
方法
变量
常量
类型
推送
实例
静态
编译
文件
字节
属性
函数
参数
名称
对象
指令
源码
不同
东西
两个
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
数据库在主文件组添加文件夹
学生宿舍的网络技术投标书
sql在展开数据库展开
数据库大小写有关系吗
上海免费数据库
eps有多少个数据库
德阳网络安全局
漯河财务软件开发
智慧树数据库原理期末答案
警校的网络安全是干什么的
计算机网络技术贵吗
怎么组装电脑数据库
游戏服务器内存条
66铃声软件开发
it软件开发学什么
云帆网络技术服务有限公司
软件开发过程中的各个模型
医药数据库靠谱吗
数据库连接基本语法
课程管理和数据库
网络技术专业面试问题
数据库的可公开验证更新
网络技术十进制转二进制
国际服改了服务器怎么变回来
视频聊天软件开发怎样做
山西天上网络技术有限公司
漯河财务软件开发
服务器工作组管理
普陀区参考网络技术服务多少钱
可道云数据库怎么配置