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开发工具排名_排名前16的Java工具类

在Java中,工具类定义了一组公共方法,这篇文章将介绍Java中使用最频繁及最通用的Java工具类。以下工具类、方法按使用流行度排名,参考数据来源于Github上随机选取的5万个开源项目源码。一. org.apache.commons.io.IOUtilscloseQuietly&#xf…

java 线程 事件_Java事件调度线程解释

我最近开始学习和探索Java编程的基础知识。已经编程了一段时间,我只做了后端工作或工作,因此最接近我已经得到用户界面是命令控制台(我知道的尴尬)。我使用Swing,就我可以收集这意味着通过扩展我也使用AWT。我的问题是基于这段代码&#xff1…

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中isolate时间_Java HikariDataSource.setIdleTimeout方法代码示例

import com.zaxxer.hikari.HikariDataSource; //导入方法依赖的package包/类private HikariDataSource createHikariDataSource(JdbcProperties jdbcProperties) {HikariDataSource hikariDataSource new HikariDataSource();hikariDataSource.setJdbcUrl(jdbcProperties.getJ…

java连接mysql通用方法_jdbc操作数据库通用方法

1 /**2 * 增删改查操作公共类(以oracle数据库为例)3 * 2017-8-29 wuyafei4 *5 */6 public classCrudUtil {7 /**8 * 1.获取数据库连接9 * 2.获取statement,加载sql语句10 * 3.获取resultset11 *12 */13 public static Connection connnull;14 public static Stateme…

java velocity 邮件_邮件集成java mail + 读取邮件模板

项目做异地登录提醒功能,通过java mail发送邮件。读取邮件模板sendMail.vm文件。1.邮件发送import java.io.StringWriter;import java.util.Properties;import javax.mail.Message;import javax.mail.Session;import javax.mail.Transport;import javax.mail.intern…

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

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

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

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

mysql1846错误_远程连接MySQL报错ERROR 2003解决办法

转自https://blog.csdn.net/hjwang1/article/details/51669223问题代码代码ERROR 2003 (HY000): Cant connect to MySQL server on 192.168.0.19 (111)ERROR 2003 (HY000): Cant connect to MySQL server on 192.168.0.19 (111) 这个 原因就是Mysql数据库的默认配置文件my.cnf(…

java webview 对象_Android – 将JSON对象从webview javascript传递给java

我在java端有一个带有webview和javascript接口的Activity.我想用Java编写一个可以接受来自webview的json参数的方法.JavascriptInterfacepublic String test(Object data) {Log.d("TEST", "data " data);}在我的webview javascript上我打电话&#xff1a…

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用fwrite写入文件中文乱码的问题

如何解决PHP用fwrite写入文件中文乱码的问题发布时间:2020-07-15 13:52:07来源:亿速云阅读:220作者:Leah这期内容当中小编将会给大家带来有关如何解决PHP用fwrite写入文件中文乱码的问题,文章内容丰富且以专业的角度为…

php判断有没有登录,请问thinkphp 怎么在每个方法里面判断是否登录?

[tp版本3.2.3]我在Controller里面写了一个公共类CommonController.class.php,写了一个构造方法来判断是否登录,没登录就重定向到登陆页:namespace Admin\Controller;use Think\Controller;class CommonController extends Controller{public …

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

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

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

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

server.mappath php,Server.MapPath( ) 方法的主要功能是获取文件的绝对路径。

9、“别有忧愁暗恨生”中的“忧”应写作“幽”。( )尺寸标注的组成中包含单位,尺寸线,尺寸文字,尺寸箭头目前常见的光纤通常为单模光纤,因为直径细,通信容量大。“给予,提供”的日语假名是( )。1010.( )在FX系列PLC功能指令中有符号P表示脉冲执行。20世纪70年代,设计出了()系统…

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

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

php cdr,win10彻底禁止cdr联网

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

php授权验证系统 c,OAuth 2.0 授权码认证

参考文章组成成分用户应用1应用2流程用户在应用1浏览、使用的过程中,涉及到要使用应用2功能的时候,就产生了 oauth 认证!A. 登录授权应用1携带如下查询字符串:response_typeclient_idredirect_uriscopestate跳转到应用2的登录授权…