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

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

e2e9ca34008a2ba186457ac4758f21bd.png

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

上节回顾

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文件本质上也可以视

作是一张表。

a63d3a21b50d7b50ea19ddfa1709b371.png

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

f555ffc4ba284330c20eda2092459d0a.png

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

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

5df3fd424eafa8adc3b5ddd851c3e667.png

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

1、魔数

47a479a5a9d48bba048c61504032af5f.png

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

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

03c5480eb08798fe8fea259db3a4dc83.png

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

5e9b613ee330262c1984639c672e37dc.png

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

2、文件版本号

517d6303c6d4aff9a152331a031f6a3d.png

紧接着魔数的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)。

b7965925dd38997851318b94e5b8bada.png

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

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

5f842c1273971a6dc9fd80004a59bc17.png

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

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

afdfa2c70a877ba5213e537f1c487768.png

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

常量池解析实战

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

bad07da3219f2df09bb532c6fd448eef.png

bc37da6c36a6df8bf942d09a19134b1e.png

6405a892b1a4aefc350808c02af63ab5.png

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

1.第一个常量

6e147061acf47c9b27296b19f431a3f4.png

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

1daa82c19460368983998c3a89b365c8.png

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

ccdca20d466bcc381e56387e50bdf99b.png

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

2.常量CONSTANT_Utf8_info

4da4d096d04f79529a71f47e19d3b724.png

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

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

c763dadb565752afa1261741ccadd6e0.png

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

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

评论区找答案哦~

4.访问标志

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

者接口层次的访问信息。

8e1b47f1ec1538e6d3f8aa8b27b75cc9.png

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

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

律为零。

38d519f28e5aa3ccf5242fdbdd618e25.png

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

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

首先把0x0021转换为2进制

0000000000100001

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

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

085b9c39fa7c5cb5c47aaca52db8856c.png

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

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

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

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

0314051021042887a7b680c47ee35d10.png

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

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

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

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

2b5f76104eeed6b7df4622ab25a27a47.png

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

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

0e6ae84a9e414319e705075644f8b225.png

全部正确的同学恭喜你已经小有所成啦,点赞👍+关注,下一篇的主题是类加载~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/563629.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java自学笔记_JAVA自学笔记(4)

发现JAVA的有趣Day1 继承不是"继承"1.0 继承的格式public classFU {public voidmethod(){System.out.println("Good night!");}}public class ZI extendsFU {}public classPractice {public static voidmain(String[] args) {ZI zinewZI();zi.method();}}打…

java分隔符算法_《Java数据结构和算法》栈 分隔符分配

分隔符包括“{“、"["、”(”、“] “、“)“、“}”,每个左分隔符需要右分隔符匹配。同时,在字符串中后出现左分隔符应该比早出现的先匹配。程序从字符串中不断读取字符,每次读取一个字符。若发现是左分隔符…

Java集合迭代器原理图解_Java Iterator接口遍历单列集合迭代器原理详解

这篇文章主要介绍了Java Iterator接口遍历单列集合迭代器原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下Iterator接口概述在程序开发中,经常需要遍历集合中的所有元素。针对这种需求&#x…

php商城的购物车功能,php实现购物车功能(以大苹果购物网为例)

首先是几个简单的登录页面登录用户名:密 码:登录页面写好之后,需要进入处理页面,从数据库中调出用户名和密码:session_start(); //开启session 必须要写到第一行header("Content-type:text/html;charsetutf-8&quo…

php的功能和特点,php的特点有哪些

PHP是一种服务器端、跨平台、html嵌入式的脚本语言执行速度快:PHP是一种强大的CGI脚本语言,语法混合了C、Java、Perl和PHP式的新语法,执行网页比CGI、Perl和ASP更快,这是它的第一个突出的特点。 (推荐学习:PHP视频教程…

php小程序码生成并保存,小程序中如何生成小程序码

导语:小程序是一种不需要下载安装即可使用的应用,它实现了应用“触手可及”的梦想,用户扫一扫或者搜一下即可打开应用。也体现了“用完即走”的理念,用户不用关心是否安装太多应用的问题。应用将无处不在,随时可用&…

php写不了php,php写入内存不足怎么办

php写入内存不足的解决办法:1、修改【php.ini】;2、在程序里面添加相关语句,代码为【ini_set(memory_limit, 12M)】;3、在根目录建立【.htaccess】文件。本教程操作环境:windows7系统、PHP5.6版,DELL G3电脑…

java 终态类,javaoo,继承,抽象类,终态类,访问修饰符!

java的继承!Java的继承使用extends关键字!为什么要使用继承呢?我们先来举例说明一下!比如说!烟是类!而叶子烟,和纸烟,烟这个类包含了,叶子烟和纸烟这两个类,如…

php cdr,win10彻底禁止cdr联网

1、打开Win10电脑,然后按winPauseBreak,来到“系统”属性窗口,点击控制面板,如图所示:2、打开来到控制面板页面,鼠标单击“系统和安全”,如图:3、打开在“系统和安全”对话框中&…

微信 语音转文字 java,在微信——怎么将语音转化为文字,你需要学习了

有时候和好友在聊天,这时好友在微信上发来语音信息,可是你这个时候不方便听语音,那怎么办呢?这个是我们就可以运用微信的语音转文字的功能,那么如何使用这个功能呢?跟着小编看看吧!操作方法01小…

php开发添加表情功能,WordPress网站评论区如何实现添加表情包功能?

做网站过程中,可以给自己的网站添加评论框,供用户评论。默认情况下,Wordpress网站评论框是没有添加表情功能的,那么WordPress网站评论区如何实现添加表情包功能?今天我们介绍一下如何给自己的Wordpress网站评论框添加表…

日冕物质抛射检测matlab,日冕图像论文,关于基于实时数据的日冕物质抛射自动检测方法相关参考文献资料-免费论文范文...

导读:本论文主要论述了日冕图像论文范文相关的参考文献,对您的论文写作有参考作用。(昆明理工大学信息与自动化学院,昆明 650504)(Faculty of Information Engineering and Automation,Kunming University of Science and Technology,Kunming 650504,China)摘 要:本…

link url下载php,php脚本生成google play url的下载链接,下载apk并自动反编译后获取android版本号...

php脚本生成google play url的下载链接,下载apk并自动反编译后获取android版本号需求:get the offer tracking linkfollow the redirect to get google play urlGo to http://apps.evozi.com/apk-downloader/Enter google play urlDownload APK fileDecompile APK f…

oracle单行子查询返回多个行 order by,单行子查询返回多个行 Issue分析求助

with order_base as --获取订单基础情况(select ou.order_key order_key, ou.order_quantity_i, ood.dispatch_time_t, ou.part_number_s, I032ZZ01 pline_name_sfrom order_uv ou left join at_as_om_orderdispatchstatus ood on ou.order_key ood.order_54union allselect m…

php按照名称搜索,PHP从类型和名称搜索

很抱歉,标题不好,但我不知道有更好的选择.目前,我正在创建一个搜索引擎以获取产品详细信息.我有2种搜索类型,第一种是使用产品类型进行搜索,另一种是使用产品名称进行搜索.这是搜索代码:$search_exploded explode (" ", $search);$x "";$cons…

简述oracle数据库特殊状态,【OracleDB】 01 概述和基本操作

实例概念:Oracle有一个特殊的概念Oracle数据库 数据库 Oracle文件系统 Oracle实例实例处理Oracle的请求,调用文件系统然后返回结果响应给客户端单实例和多实例一个数据库可以对应多个实例操作数据库服务这是Oracle数据库的服务,一定要安装…

oracle中affirm,2.Oracle Data Guard 参数介绍

Oracle Data Guard 参数介绍Data Guard作为Oracle提供的一个高可用及灾备解决方案,理解并可以实施它对于DBA来说是非常重要套的技能上节介绍了有关Data Guard的概念,这节将介绍相关的一些参数有的参数是做为备库角色时才生效的,会单独说出来1. DB_NAME该…

Linux单独编译设备树,迅为IMX6Q开发板-非设备树内核-单独编译内核驱动

内核驱动不仅可以将驱动编译到内核中,还可以动态的编译内核驱动。本文档介绍如何以模块的方式编译内核驱动。要动态的编译内核,首先需要将内核源码编译通过,内核的编译请参考使用手册第五章。9.5.2.1 内核和编译器路径本节介绍内核路径、编译…

win8关闭uefi+linux,UEFI启动是什么?Win8关闭UEFI引导方式的方法

UEFI启动是什么?不少新电脑都给用户直接预装了Win8系统,后来使用又非常不习惯,因此想改成Win7系统,但是在换系统之前,需要在BIOS下关闭UEFI引导方式,可能很多朋友都不懂该如何关闭UEFI启动项。针对这个问题&#xff0…

android listview自动加载更多,如何实现 Android ListView『上拉加载更多』?

ListView上拉加载更多的UI需求(1)向上滑动 ListView,当最后一个条目滚入屏幕时开始加载更多条目,在列表底部增加一个 footerView:一个 infinite progressBar,一个 textView 显示 “Loading...”;(2)根据数据加载的结果…