马上过年啦,不知道大家今年有没有投资基金股票呢?是赚的盆满钵满还是拍断大腿,可以评论区一起交流交流,秀一秀哈哈,反正我是没来得及上车。

暴富西不可能暴富的啦,打工人嘛几能写写文章啦~记得点赞➕关注呀

上节回顾

1.创建对象的7个步骤

2.java对象的内存布局了解多少

3.内存分配的并发问题怎么解决

一点说不上来的同学注意啊!你离暴富又远了一步,好在我这儿有本秘籍,暴富秘籍

写在前面

从本章开始,我打算用2章的篇幅来讲述一个类文件结构和类的加载过程。很多工作了几年的同学都会有这种感受:几个月不学技术,不去接触新的东西,渐渐的就会跟不上潮流了。就像前几年一直鼓吹中台,到现在又要拆中台,这都是种种原因所导致的,可理解为是一种潮流。但不管潮流怎么变,最底层的知识永远都不会轻易动摇和变化的,我们现在学的可能未来5年、10年都不会有所改变,对于短短的编码生涯来说基本属于终生受益了。九九乘法表虽然枯燥难背,但现在不也深入每个人的生活,并终生受用。

本章内容

本章我们主要学习class类文件的结构,要想更好的理解和掌握本章的知识点的话,需要同学们也上手一起来操作,同时针对一些常用的字节码指令简单进行一些介绍。

一、Class类文件的结构

Class文件是一组以8个字节为基础单位的二进制流,各个数据项目严格按照顺序紧凑地排列在文

件之中,中间没有添加任何分隔符,这使得整个Class文件中存储的内容几乎全部是程序运行的必要数

据,没有空隙存在。当遇到需要占用8个字节以上空间的数据项时,则会按照高位在前的方式分割

成若干个8个字节进行存储。

Class文件有两种数据结构:无符号数和表

无符号数:属于基本的数据类型,以u1、u2、u4、u8来分别代表1个字节、2个字节、4个字节和8个

字节的无符号数,无符号数可以用来描述数字、索引引用、数量值或者按照UTF-8编码构成字符串

值。

表:是由多个无符号数或者其他表作为数据项构成的复合数据类型,为了便于区分,所有表的命名

都习惯性地以“_info”结尾。表用于描述有层次关系的复合结构的数据,整个Class文件本质上也可以视

作是一张表。

在解析之前我们需要下载一个能查看class文件内容的工具,我这边使用的是Hex Fiend,windows系统的同学也可以下载WinHex都是一样的。

希望同学们也能自己下载一个也尝试着来解析一下,这样就不至于隔天就忘记了。

使用javac指令生成对应的class文件,并把文件拖入Hex Fiend中打开

好了,今天我们要将的就是这些个16进制数字组合。

1、魔数

每个Class文件的头4个字节被称为魔数(Magic Number),它的唯一作用是确定这个文件是否为

一个能被虚拟机接受的Class文件。

java使用的魔数是CAFEBABE,这个压根不用记住,看一眼java图标就显而易见了

以前一直不清楚这图标到底是咖啡还是茶呢,本人喝茶比较多一点,当然老外的话一定是咖啡比较多。现在相信大家都能确定这就是一杯咖啡。

2、文件版本号

紧接着魔数的4个字节存储的是Class文件的版本号:第5和第6个字节是次版本号(Minor

Version),第7和第8个字节是主版本号(Major Version)。

至于版本号的作用相信大家都能想到,毕竟java从JDK1.1开始,到现在JDK16新特性都已经出来了,大版本都已经有十几个了,这还是不计算各个小版本的情况下。为了保持非常良好的向后兼容性,这个版本号必不可少,所谓向后兼容就是说低版本的JDK下开发的产品能在高版本的JDK中跑。

Java的版本号是从45开始的,JDK 1.1之后的每个JDK大版本发布主版本号向上加1(JDK 1.0~1.1使用了45.0~45.3的版本号)。这边我们看到主版本号的16进制是34,对应的10进制就是52,也就是说我们从这个就能推断出,我们是用JDK1.8来编译生成这个class文件的。

关于次版本号,曾经在现代Java(即Java 2)出现前被短暂使用过,JDK 1.0.2支持的版本45.0~

45.3(包括45.0~45.3)。JDK 1.1支持版本45.0~45.65535,从JDK 1.2以后,直到JDK 12之前次版本号均未使用,全部固定为零。而到了JDK 12时期,由于JDK提供的功能集已经非常庞大,有一些复杂的新特性需要以“公测”的形式放出,所以设计者重新启用了副版本号,将它用于标识“技术预览版”功能特性的支持。如果Class文件中使用了该版本JDK尚未列入正式特性清单中的预览功能,则必须把次版本号标识为65535,以便Java虚拟机在加载类文件时能够区分出来。

3、常量池

同学们应该都还记得在DAY1中我们曾经讲过方法区中的运行时常量池,我们这边讲的常量池指的是class文件中的常量池,这个大家要区分开。两者的区别就是运行时常量池具备动态性,这里我们就不展开讲了。

紧接着主、次版本号之后的是常量池入口,由于常量池中常量的数量是不固定的,所以在常量池的入口需要放置一项u2类型的数据,代表常量池容量计数值(constant_pool_count)。

这里我们看到这个16进制值是0013,对应的10进制就是19。与Java中语言习惯不同,这个容量计数是从1而不是0开始的,所以记录的是#1到#18的常量。

这个可能不大好理解。我们通过事实来证明一下,使用javap -c -v指令来看一下我们的class文件,眼见为实

显而易见这里一共是18个常量。

对应到我们Hex Fiend里面的字段的话就是这大段

大家先别慌,这些其实都是死的,只要参照着字典表一个个对照来查找就很简单了,下面我们也一起来走一遍。

常量池解析实战

首先拿出我们的字典表,先放着不急着看

每一种类型都是以_info结尾的,证明这是几个常量都是表,笼统地去看不难发现,每一个常量的开头都是一个u1字节长度的tag,这就好比是一个id号,大家可以这样来理解。

1.第一个常量

看图中,紧接着常量池入口的第一个字节就是我们第一个常量的tag,他的值为0A,也就是10,根据这个id查找字典,找到

也就是说这个常量是一个u1和两个u2组成的,一共5个字节,很快哦,啪~一下我们就把第一个常量找到了

其他的都是类似的,除了tag = 01的utf_8比较特殊

2.常量CONSTANT_Utf8_info

这个常量的第二个项目的含义是lenth也就是第三个项目有多少个位数的含义。

我们用第一个CONSTANT_Utf8_info常量来作为例子

tag = 01表明他是一个CONSTANT_Utf8_info常量,0001表示这个常量的长度是1,6D就是长度为1的UTF-8编码的字符串

这样分开来讲应该很容易理解来把。同学们能自己把这18个常量一一找出来吗?

评论区找答案哦~

4.访问标志

在常量池结束之后,紧接着的2个字节代表访问标志(access_flags),这个标志用于识别一些类或

者接口层次的访问信息。

可以看到这边的16进制值是0x0021

access_flags中一共有16个标志位可以使用,当前只定义了其中9个,没有使用到的标志位要求一

律为零。

每一个访问标志占用一位目前一共又9位,还有6位还未使用,全部记为0。

下面我们看一下这个访问标志是怎么算出来的

首先把0x0021转换为2进制

0000000000100001

也就是说我们第0位和第5位为1的两个访问标志位为1,其他全部为0,对应到上面表格中很容易就能查出,这边除了ACC_PUBLIC和ACC_SUPER为真,其他全部为假。

最后我们通过javap -c -v指令来验证一下

5.类索引、父类索引与接口索引集合

类索引(this_class)和父类索引(super_class)都是一个u2类型的数据,而接口索引集合

(interfaces)是一组u2类型的数据的集合,Class文件中由这三项数据来确定该类型的继承关系。

java是不允许多重继承,但是允许实现多个接口,所以除了Object类的父类索引是0x0000,其他类的父类索引都不为0,父类索引后面紧跟着的是一个u2长度的接口索引集合计数,可以类比常量池计数器,接口索引集合按照代码中接口实现的顺序从左到右记录索引位置。

对应到我们的Hex Fiend工具里面是这3个u2字符,分别表示

类索引: 0x0003 代表常量池的#3号常量

父类索引:0x0004 代表常量池的#4号常量

接口索引集合计数器: 0x0000 代表没有实现任何接口

考虑到本章讲的内容相对来说比较多,而且看到到这里跟着我一起一边学一边操作的同学应该已经对类文件的结构的解析套路有了一个大致的了解了,所以正文的类文件结构就告一段落。剩余的字段表集合、方法表集合和属性表集合这三个部分我另外开一章来写,感兴趣的同学可以继续进入进阶学习

最后附上常量池解析的结果

全部正确的同学恭喜你已经小有所成啦,点赞

java怎编写么解析一个类型_DAY3:你必须知道的java虚拟机之类篇——类文件的结构...相关推荐

  1. 无法从命令行或调试器启动服务.必须首先_十大Java面试问题-您必须知道的Java基础知识...

    问:什么是JRE,为什么需要它? JRE代表" Java运行时环境",您通常可以将其下载为Java软件.JRE由Java虚拟机,Java平台类和支持库组成.JRE是Java软件的运 ...

  2. java泛型常用特点_?你必须知道的Java泛型

    前言 文本已收录至我的GitHub仓库,欢迎Star:https://github.com/bin3923282... 种一棵树最好的时间是十年前,其次是现在 我知道很多人不玩qq了,但是怀旧一下,欢 ...

  3. Android必须知道的Java内存结构及堆栈区别

    一.认识Android储存结构 对于Android来说,存储主要分为三个部分:内存.内部存储以及外部存储,详细介绍如下: (1)内存存储RAM(Random Access Memory) 内存与PC的 ...

  4. 关于循环语句你必须知道的Java新手常遇的问题

    for语句 for(a初始条件:b循环判断条件:c循环过程表达式){ d循环体 ; } a一般为循环变量的赋值表达式(for example i=1) c一般为循环变量增值语句(for example ...

  5. [深入理解Java虚拟机]第六章 Class类文件的结构

    在本章关于Class文件结构的讲解中,我们将以<Java虚拟机规范(第2版 )> (1999年发布,对应于JDK 1.4时代的Java虚拟机)中的定义为主线,这部分内容虽然古老,但它所包含 ...

  6. 网页最少要有一个html标签,PHP_网页开发人员必须知道的10个不常用HTML标签, 网页开发人员常常希望能 - phpStudy...

    网页开发人员必须知道的10个不常用HTML标签 网页开发人员常常希望能够了解并掌握多种语言,结果是,学习一门语言的所有内容是棘手的,但是却很容易发现你并没有完全利用那些比较特殊却很有用的标签. 不幸的 ...

  7. [你必须知道的.NET]第二十三回:品味细节,深入.NET的类型构造器

    1 引言 今天Artech兄在<关于Type Initializer和 BeforeFieldInit的问题,看看大家能否给出正确的解释>一文中让我们认识了一个关于类型构造器调用执行的有趣 ...

  8. [你必须知道的.NET] 开篇有益-------这是一个系列,文章中有后面章节的连接

    本文将介绍以下内容: • .NET的核心知识汇总 • 学习.NET的圣经心得 1. 引言 最近常常为学习中的问题而伤神,幸有管伟一起常常就技术问题拿来讨论,我已想将讨论的内容以基本原貌的方式,形成一个 ...

  9. c4d python使用方法_Cinema 4D Python脚本编写必须知道的5行Python代码教程

    Cinema 4D Python脚本编写必须知道的5行Python代码教程 在这期Cinema 4D python教程中的第一篇.Alpha Pixel将介绍如何使用python脚本进行设置,并查看一 ...

最新文章

  1. (C++)1027 打印沙漏
  2. C# 小数位数保留的方法集锦
  3. 计算机网络的组成相关,计算机网络的组成
  4. SVN状态图标不显示
  5. 【P1326】超级教主
  6. 大数据之路- Hadoop环境搭建(Linux)
  7. MyBatis 插件原理与自定义插件-插件编写与注册
  8. SAP UI5 数据绑定中的工厂函数
  9. 可以进行单元测试么_前端与单元测试
  10. 【Linux网络编程学习】I/O多路复用——epoll
  11. linux php 网站计数器,PHP图形数字计数器的实现
  12. keras + tensorflow —— 函数式 API编程
  13. discuz! X3.2 自定义后台门户模块模板里的标签
  14. 共享办公室租赁,突出市场重围
  15. React开发者工具 React Developer Tools 的下载
  16. 【PDF提取内容重命名】咕嘎批量PDF批量提取PDF识别重命名,如何批量读取pdf内容并重命名,根据pdf内容修改文件名称,如何提取pdf标题为文件名,用电子发票为例教你操作方法
  17. 解决联想笔记本 FN键不起作用的方法
  18. 加拿大卡尔顿大学暑课两个月入门Java全记录_1
  19. C++笔试笔记1(4399 西山居 深信服 剑心互娱 快手)
  20. linux卡住重启_linux df -h 命令卡住 解决方法

热门文章

  1. 64位程序怎么判断指针是否有效_AArch64应用程序级编程模型
  2. win7发现不了无线网络怎么办 win7发现不了无线网络的解决办法
  3. iis7.5 php伪静态,Windows Server 2008 下WordPress IIS7.5伪静态规则设置(最新)
  4. npm的镜像替换淘宝
  5. idea编辑器中使用@Data注解无效解决办法
  6. abap数据类型转换_ABAP 中JSON格式的转换与解析
  7. vue 调用webservice_js跨域调用WebService的简单实例
  8. 动态分区添加的新字段无法插入数据
  9. 转专业计算机c语言,转专业申请美国计算机专业研究生必须要做的准备
  10. Fail-fast 和 Fail-safe 机制