深入学习和认识class文件内部结构

本文深入探讨Java字节码文件的结构,从魔数、版本信息到常量池、访问标志,再到Fields和Methods部分,解析Java程序如何被JVM执行。通过实际案例,展示如何将Java源代码转换为字节码,以及字节码文件的各部分含义。

我们在学习java的时候总是会说java是一种跨平台性的语言,即一次编译,到处运行。但是为什么说java能够一次编译,导出运行呢?其实这主要还是需要依赖jvm,而JVM其实是不认识java文件的,因此当java程序被编译之后,会变成class文件,只要相应的class文件能够符合jvm的规范要求,那他们就能够被jvm所运行。因此现在除了java语言之外,kotlin,Scala,Clojure等语言都可以在jvm上运行。可以说,很多语言的出现都离不开JVM。那么对于class文件的基本结构,又该如何深入学习呢?

首先在本次学习class文件结构之前,我们需要先准备两个东西。
1.HelloWorld.java程序:
在这里插入图片描述
2.OoLong.jar。Oolong这是一种汇编语言的名称。首先我们需要到指定的github上边去下载资源。
https://github.com/jpbirdy/programming-for-the-jvm

在这里插入图片描述
下载完毕之后,需要将相应的文件编译成class字节码,然后在用java命令将其打包成jar文件。

直接进入src目录底下,输入以下命令:

jar cvf OoLong.jar COM  

(这里的COM文件夹底下的所有java程序都已经被编译成了class字节码)
然后COM目录底下的内容就会被自动打包成为一个叫做OoLang.jar的工具包了。
在这里插入图片描述
然后我们将该jar包放在需要测试的Helloworld.class字节码文件同级目录处。
java -verbose -cp OoLong.jar COM.sootNsmoke.oolong.Gnoloo HelloWorld.class
输入以上命令,即可进行转换:
在这里插入图片描述
转换完毕之后,大致如下图所示:
在这里插入图片描述
接着小编用Notepad++打开了HelloWorld.j文件,查看了里面的内容:
在这里插入图片描述
稍微来解释一下:
.source 指令是指程序的源文件
.class 表示这是一个类 并指定相应的类名
.super 表示这个类的父类是Object类型
.method public ()V 表示这是一个公有的方法 表示这是一个构造函数 V表示该函数的返回类型为void

好了,接下来我们将这个HelloWorld.java文件转换成二进制的字节码文件进行试验:
为了方便阅读和下边的讲解,我用了下边这个指令来进行测试:
java -verbose -cp OoLong.jar COM.sootNsmoke.oolong.DumpClass HelloWorld.class
文件被转成了二进制的字节码文件后,内容如下图所示:
(为了便于观察,小编在实验的时候使用了idea编辑器的终端窗口)
在这里插入图片描述
现在我们来对这段二进制文件作深入的分析。
首先是文件的头部信息:
1.魔数
在这里插入图片描述
这段头部信息也被称之为魔数。主要是用来标识该class文件的类型。通常都是以cafebabe这段十六进制的数字来表示。
2.Class文件的版本信息
接着魔数的下方,我们会发现这些内容:
在这里插入图片描述
这里的两个字节分别是表示相应的最大最小java版本范围。
总结起来就是从000000-000006的这6个字节分别表示了这个class文件的基本头部信息。
这些数字的作用主要是限制低版本jvm执行高版本的class文件。这也就是为什么有的时候,高版本jvm环境生成的class文件在移植到低版本jvm环境中无法执行的根本原因了。

3.常量池
接下来的这部分主要是描述常量池的内容:
在这里插入图片描述
这些东西被称之为常量池,常量池里面主要存放了两种类型的常量。
字面值常量(String字符串和final修饰的值)和符号引用(类名,接口名字,方法名称,字段名称等)
仔细观察会发现,每个常量都是由三个字节来进行描述的。基本结构如下:
在这里插入图片描述
jvm中定义了多种常量的类型,分别用数字来一一对应。
常量类型中包括了我们所熟知的一些Integer,String类型。
接下来我们通过解释几个不常见的常量类型来加深对于常量池的理解:
UTF8常量类型(有些书籍也称之为CONSTANT_Utf8_info)
在这里插入图片描述
在jvm的数字对应规则中,01表示的常量类型是utf8常量,这里的末尾数字6表示这个常量的长度为6。
在CONSTANT_Utf8_info常量类型里面,该常量的长度被限制为了2个字节,也就是64k,又由于class文件的接口,字段,方法名称,包名都是用这个常量类来表示的,因此类的全限定名、字段名、方法名的最大长度不能超过2个字节所能表示的最大整数,也就是65535。
Fieldref,Methodref常量类型
在这里插入图片描述

这种类型主要是用于描述class项里面的属性和方法。

Class常量类型
这种常量类型主要是用于描述该类的名称
在这里插入图片描述
4.访问标志
在常量池之后的部分,主要是一些描述类本身的相关信息内容。例如是否实现接口,是否为抽象类,属性个数,方法个数等。
在这里插入图片描述
5.Fields和Methods部分
这部分的内容主要是指程序本身的属性和方法的一些描述信息:
例如说一些本地栈的深度,常量的个数等信息,以及异常个数等信息:
在这里插入图片描述
6.class属性的描述
在这里插入图片描述
这里面主要是两个java语言的属性描述,sourcefile和name的描述。

2019最新深入理解JVM内存结构及运行原理(JVM调优)高级核心课程视频教程下载。JVM是Java知识体系中的重要部分,对JVM底层的了解是每一位Java程序员深入Java技术领域的重要因素。本课程试图通过简单易懂的方式,系统的深入讲解JVM相关知识。包括JVM执行过程、虚拟机类加载机制、运行时数据区、GC、类加载器、内存分配与回收策略等,全套视频加资料高清无密码  第1讲 说在前面的话 免费 00:05:07  第2讲 整个部分要讲的内容说明 免费 00:06:58  第3讲 环境搭建以及jdk,jre,jvm的关系 免费 00:20:48  第4讲 jvm初体验-内存溢出问题的分析与解决 免费 00:17:59  第5讲 jvm再体验-jvm可视化监控工具 免费 00:21:17  第6讲 杂谈 免费 00:12:37  第7讲 Java的发展历史 00:27:24  第8讲 Java的发展历史续 00:02:27  第9讲 Java技术体系 00:08:46  第10讲 jdk8的新特性 00:07:31  第11讲 lanmbda表达式简介 00:07:02  第12讲 Java虚拟机-classic vm 00:06:06  第13讲 Java虚拟机-ExactVM 00:03:35  第14讲 Java虚拟机-HotSpotVM 00:04:23  第15讲 Java虚拟机-kvm 00:03:04  第16讲 Java虚拟机-JRockit 00:04:12  第17讲 Java虚拟机-j9 00:04:23  第18讲 Java虚拟机-dalvik 00:02:20  第19讲 Java虚拟机-MicrosoftJVM 00:03:57  第20讲 Java虚拟机-高性能Java虚拟机 00:02:58  第21讲 Java虚拟机-TaobaoVM 00:03:06  第22讲 Java内存区域-简介 00:07:56  第23讲 Java内存区域-Java虚拟机栈 00:12:04  第24讲 Java内存区域-程序计数器 00:12:54  第25讲 Java内存区域-本地方法栈 00:02:39  第26讲 Java内存区域-堆内存 00:05:08  第27讲 Java内存区域-方法区 00:06:32  第28讲 Java内存区域-直接内存运行时常量池 00:15:53  第29讲 对象在内存中的布局-对象的创建 00:21:19  第30讲 探究对象的结构 00:13:47  第31讲 深入理解对象的访问定位 00:08:01  第32讲 垃圾回收-概述 00:06:20  第33讲 垃圾回收-判断对象是否存活算法-引用计数法详解 00:14:08  第34讲 垃圾回收-判断对象是否存活算法-可达性分析法详解 00:07:09  第35讲 垃圾回收算法-标记清除算法 00:04:36  第36讲 垃圾回收算法-复制算法 00:14:35  第37讲 垃圾回收算法-标记整理算法分代收集算法 00:05:24  第38讲 垃圾收集器-serial收集器详解 00:09:45  第39讲 垃圾收集器-parnew收集器详解 00:04:53  第40讲 垃圾收集器-parallel收集器详解 00:11:02  第41讲 垃圾收集器-cms收集器详解 00:14:58  第42讲 最牛的垃圾收集器-g1收集器详解 00:18:04  第43讲 内存分配-概述 00:04:23  第44讲 内存分配-Eden区域 00:22:51  第45讲 内存分配-大对象直接进老年代 00:06:42  第46讲 内存分配-长期存活的对象进入老年代 00:03:40  第47讲 内存分配-空间分配担保 00:04:54  第48讲 内存分配-逃逸分析与栈上分配 00:10:32  第49讲 虚拟机工具介绍 00:10:27  第50讲 虚拟机工具-jps详解 00:11:20  第51讲 虚拟机工具-jstat详解 00:09:20  第52讲 虚拟机工具-jinfo详解 00:05:03  第53讲 虚拟机工具-jmap详解 00:08:48  第54讲 虚拟机工具-jhat详解 00:08:10  第55讲 虚拟机工具-jstack详解 00:10:19  第56讲 可视化虚拟机工具-Jconsole内存监控 00:07:09  第57讲 可视化虚拟机工具-Jconsole线程监控 00:12:18  第58讲 死锁原理以及可视化虚拟机工具-Jconsole线程死锁监控 00:10:38  第59讲 VisualVM使用详解 00:08:03  第60讲 性能调优概述 00:11:22  第61讲 性能调优-案例1 00:23:28  第62讲 性能调优-案例2 00:10:05  第63讲 性能调优-案例3 00:12:41  第64讲 前半部分内容整体回顾 00:15:41  第65讲 Class文件简介发展历史 免费 00:11:26  第66讲 Class文件结构概述 免费 00:16:50  第67讲 Class文件设计理念以及意义 免费 00:13:41  第68讲 文件结构-魔数 免费 00:09:49  第69讲 文件结构-常量池 免费 00:23:44  第70讲 文件结构-访问标志 免费 00:11:36  第71讲 文件结构-类索引 00:11:26  第72讲 文件结构-字段表集合 00:13:21  第73讲 文件结构-方法表集合 00:10:06  第74讲 文件结构-属性表集合 00:18:23  第75讲 字节码指令简介 00:09:18  第76讲 字节码与数据类型 00:09:34  第77讲 加载指令 00:09:33  第78讲 运算指令 00:10:24  第79讲 类型转换指令 00:13:42  第80讲 对象创建与访问指令 00:09:38  第81讲 操作树栈指令 00:03:27  第82讲 控制转移指令 00:11:58  第83讲 方法调用返回指令 00:06:37  第84讲 异常处理指令 00:09:44  第85讲 同步指令 00:07:34  第86讲 类加载机制概述 00:07:26  第87讲 类加载时机 00:13:15  第88讲 类加载的过程-加载 00:15:15  第89讲 类加载的过程-验证 00:10:24  第90讲 类加载的过程-准备 00:05:40  第91讲 类加载的过程-解析 00:14:04  第92讲 类加载的过程-初始化 00:19:41  第93讲 类加载器 00:22:41  第94讲 双亲委派模型 00:17:03  第95讲 运行时栈帧结构 00:08:46  第96讲 局部变量表 00:20:48  第97讲 操作数栈 00:08:36  第98讲 动态连接 00:02:56  第99讲 方法返回地址附加信息 00:03:24  第100讲 方法调用-解析调用 00:09:49  第101讲 方法调用-静态分派调用 00:16:21  第102讲 方法调用-动态分派调用 00:09:02  第103讲 动态类型语言支持 00:09:27  第104讲 字节码执行引擎小结 00:03:38  第105讲 总结与回顾 00:10:55  第106讲 happens-before简单概述 00:15:17  第107讲 重排序问题 00:23:19  第108讲 锁的内存语义 00:13:54  第109讲 volatile的内存语义 00:12:04  第110讲 final域内存语义
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值