00:00
好了,接着咱们来说,刚才呢,咱们是说到了如何去解析这个二进制自解码文件呢,有三种方式啊,123,那咱们接下来呢,就深入这个资金版文件这个内部啊,咱们一点点的去解析啊,就是我们看这个这样的一些指令了,对吧?那么这个解析的话呢,咱们这个主要呢,是以方式一来说,那方式二跟方式三呢,咱们看到它都是已经做了一个反解析了,相当于就是我们一点点解析的效果呢,其实就是方式二或者方式三呢,咱们看到的这样一个场景,那这块呢,我们这样讲啊,以方式一的方式,我们主体来讲,那具体解析出来的这个数据啊,咱们可以以方式二或者方式三呢来做一个验证,哎,这样的话呢,效果会更好一些啊OK,行,那我们来看一下这个下边这个内容。说class文件那个结构啊,结构呢,其实我们刚才呢,就是已经打开过了啊,把它呢使用诶notepad加加呢这样一点开,然后呢,插件这块选择一下这个X是吧,这呢就是我们要解析的这个部分啊一看呢,还是稍微有点崩溃的是吧,那怎么去解析呢?首先提到我们有一个官方的。
01:05
哎,位置啊,官方那个位置的话呢,大家直接把它呢粘过来放到浏览器当中就可以啊,或者的话呢,就是直接,诶我这块也保存了一个书签,嗯,打开我们Java SE的这个规范,昨天呢,我们也提到过这个事儿啊,这个规范里边的话呢,我们主体是以JAVA8为主,因为现在呢,企业中主要用的还是JAVA8啊,在JAVA8这里边呢,我们看到javava虚拟的规范里边选择A帽啊这个格式呢来呈现。在这里边的第四章。第四章呢,就是来讲我们这个自建码文件的一个结构啊,点开。那这就是第四章,那我们就按照这个顺序呢去进行讲解了,那这儿呢,也列举的比较详细,那咱们呢,接下来呢,讲解也是我们这个第一章是吧,咱们的中心呢,其实就是来翻译这个子解码文件啊,当然呢,可以参照一下官网这个文档,你要觉得看的比较麻烦的话呢,这是还可以翻译成中文的是吧?当然翻译成中文呢,很多这个细节呢,翻译的不够准确啊,但是大体上还是可以的,大家可以做一个参照啊,你看这翻译成模法,其实呃,这个别翻译是最好的是吧?哎,Magic number啊最好不要翻译,那这个你刷新一下呢,这块又变成对应的这个英文版是吧?OK,行,呃,这呢是我们说的这个官方的一个文档的位置啊呃,一会儿呢,咱们讲解过程当中也会做个参照,那接着往下看,说这个class类的一个本质。
02:21
啊,Class类的一个本质啊,咱们知道呢,这个Java虚拟机呢,是跟这个资金瓦文件呢打交道的啊,不是跟具体的不一定是Java语言了是吧,主要呢,是跟这个斯基瓦文件为代表的二进制流数据呢打交道的,那我们如何去看待这个class文件呢?说呢,任何一个文件呢,都对应着一个唯一的类或者接口的定义啊,这个呢很清晰是吧,不用多说说,但反过来来讲啊,这个class文件实际上它并不一定是以磁盘文件的形式存在的。什么意思啊?啊,大家看啊,就是咱们刚才呢,针对于啊叫inte test,呃呃,Integer test是吧,这样的一个类,咱们呢,把它编译之后呢,生成了一个资金码文件啊这个资金码文件呢,哎,我们就看得见摸得着是吧,就是它它呢就是一个以磁盘文件方式存在的,存储在我们这个桌面上,这就C盘了啊行。
03:14
那但是我们不是说所有的这种呃,磁解码文件都是以这种磁盘的方式来呈现的啊,也就是说呢,呃,咱们后边呢,会讲这个事儿啊,在第三章第四章中会说,呃,我们知道Java虚拟机啊,准确的来讲呢,是类的加载器啊class loader它呢是来加载一个自行码文件,然后呢,加载完之后呢,诶就会在内存当中进行分配啊,生成相应的这个比较大的class的一个实例啊啊接下来你去new对象等等后续的这个操作啊,内存中进行分配,那分配的这个class加载的来源是一个自行码文件,这个自行码文件呢,可能是以磁盘方式存在的,它也可能比如说我们通过网络。哎,咱们通过网络呢,传输了一个二进制流数据,而这个二进制流数据呢,诶,我们就可以把它还原成内存中的一个类。
04:03
啊,还原成内存中的一个类,这呢是可以的,哎,所以说呢,更准确的来说,Class类的这个本质啊,它就是一个二进制流数据,这个数据呢,你要是把它固定下来的话呢,你可以存储在这个磁盘上,你要没有固定下来呢,我们还可以通过网络进行一个传输,对吧?哎,这就是它的一个本质啊,这个大家关注一下。啊,然后下面的话呢,我们提到这个class文件的这个格式啊,刚才大家其实也看到了,就是这样一块啊,看着稍微有点崩溃是吧?说呢,它不像是我们讲的叉帽语言啊,叉语言呢,有指定的标签作为开始啊,指定标签作为结束啊,斜杠呢,你一看到带斜杠的标签就结束了啊,这个在我们这个class文件当中没有任何的这个分隔符,很显然。一点没有是吧,那那这时候呢,我们就呃要求呢,咱们里边定义的这种字节的顺序啊,你指定指定的这个顺序啊,指定的这个数量啊,都需要被严格的限定。
05:00
啊,你不像你看我这块有个逗号啊,尤其来讲啊,就是咱们说的标点符号了是吧,你要有标点符号呢,我一逗号就知道哦,前边呢是这个事儿,后边呢是另外一个事儿,那现在呢,我们把这个逗号给你去掉了。那你想想,这个时候呢,我们就必须要严格的指定,说你哪一部分有几个长度啊,到这时候呢,就停止,然后下边呢,就是另外一个事儿了,对吧?啊,因为你没有分割符号了,所以呢,都必须要严格的限定这个相应的指定的一些顺序和数量,哪个字节代表什么含义,长度多少啊,先后顺序如何,都不允许被改变。啊,都不允许被改变啊,这个呢是大家特别需要注意的啊,呃,举一个这个例子啊,就突然想到这儿呢,这个小学的时候呢,大家也不知道有没有啊,老师在讲这个标点符号的时候呢,提到过这样的一句话啊,这句话呢叫呃,下雨天啊留客天。啊,留我不留。是吧,哎这样的一段话啊,哎,或者叫一句话,这个话的话呢,没有点标点啊,那么这个标点点到不同的位置啊,它的意思呢,哎,确实还是不一样的啊,哎,比如说叫这个其实有好几种这种解读方式啊。
06:10
比如说哎,下雨天啊,逗号一下啊,叫留客天,就是下天下雨了啊,你是得留这个客人,这个住在这块的这样的一天是吧?啊留我不留。是吧,哎,这呢是一种解读方式,然后还可以怎么去解读呢。啊,下雨天啊,逗号啊,刘克天啊,刘我波啊,一个问号,然后最后呢留啊,比如说一个感叹号,这个就相当于是一个明确的回复了,啊叫流啊这个呃,甚至呢,你还可以有其他的这个解读方式,比如说下雨天啊,下雨是吧,逗号这个天留客。啊,天留客。哎,问这这你可是个问号是吧?哎,天留啊,逗号啊,我不留,这是不是也是一种解读方式啊?啊,所以说呢,你看这个在汉语当中啊,这个博大精深啊,这个标点的位置的不同,发现呢,它表达的意思呢,也是截然不同的,那这里边我们想强调的也是这样一个意思啊,要想能够正确的解析我们这个最信码文件,所以呢,都必须严格的去规定好先后顺序,数量长度是吧?哎,都不能够轻易的改变啊,一旦改变了,我们的意思呢,就完全变了啊,那之所以我们不用标点呢,其实主要呢,还是要压缩这个词加法文件的一个大小啊,OK,行,这呢是我们说的这个事儿。
07:26
然后下面的话呢,我们就来进一步进行一个解释啊,说class文件格式呢,采用一种类似于C语言结构体的方式啊,进行数据存储。来进行数据存储,说这种结构呢,只有两种数据类型啊,一个呢叫做无符号表,哎,无符号数一个呢叫做表,哎,这个大家可能现在呢还不熟啊,咱们一讲你就清楚了啊,所所谓的这个无符号数呢,它主要呢是基本数据类型啊,这个U1 u2 u4 u8来代表的分别对应的就是一个字节,两个四个八个字节啊,这个这个相应的这个字节数的这个无符号数用来描述数字啊,比如你的索引位置啊是吧?哎,然后数量值啊,比如我们把这个数值十放到这个操作数站当中是吧,你这个十,哎,这不就是我们说的这个数量值嘛,或者呢,是按照UTF杠八这个编码构成的这个串的这个值。
08:19
啊也可以,比如说你字符串呢,我们可以看成是这个,呃,U1啊这样的一个数组嘛,是吧,那么。那么下边这个概念呢,叫做表说表啊,它是由多个无符号数或者呢是其他的表哎作为数据项构成的复合数据类型。哎,这个叫复合数据类型啊,那这个时候大家怎么看这个表呢?其实呢非常简单,你就把它想成是咱们Java中的数组就可以了。N像账号中数组,咱们是不是可以是基本数据类型构成的数组,你也可以呢,是不是由数组构成的一个数组啊,哎,那不就是相当于二维数组啊,对吧?那一般说表的话呢,我们习惯是以这个叫杠,这个下划线in for结尾啊来表示一个表啊,用于描述具有层次关系的复合结构的数据。
09:06
什么意思啊,你比如说啊,咱们在一个,哎,咱就比如说这个integer integer换一个吧。比如说这个吧,啊。这个当中呢,我们发现这个丧是吧,它呢里边这个构造器呢,其实在咱们这个字解码当中,咱也看到了,其实对应的是有一个因力的那样一个方法,对吧?哎,那个因利方法跟这个啊print这也是个方法,你这不就俩方法吗?那这俩方法呢,就应该在方法表里边啊,你这个表里边呢,就有两个嘛,哎,就这意思啊,包括一个类中呢,比如说你有好几个属性,三个属性吧,哎,你要有三个属性,那这个属性的话呢,其实这个属性准确的咱呃翻译的其实不能叫属性的啊,这个叫field是吧?啊,因为呢,我们这个X呢叫field,这个field其实准确的翻译成了我们叫这个字段会更合适一点啊,因为我们这个属性呢,在金码文件当中,它有另外的这个含义啊。那如果我们定义了三个字段啊,那你这三个字段呢,就应该在这个few的这个infer当中。
10:05
就相当于是个表当中长度呢,就是三对吧,哎,是这个意思啊,其实就类似于我们说的那个数组的概念啊,只不过这呢我们称为呢叫表。呃,然后呢,下边又提到个事儿,说其实咱们整个这个class文件呢,本质上来讲,它其实就是一张表,就是它也是一张表啊,啊因为这个这另外一个事儿,呃,这个怎么去理解呢?是因为咱们这个class文件呢,咱们里边包含了好几个部分啊,你包含魔术啊,包含class这个版本啊,包含这个呃,字段啊,方法呀,属性啊,当前这个类啊,它的副类啊,当前这个类的标识啊,那这里边儿呢,每一个其实都可以作为咱们表里边的一个项,所以整体这个class文件呢,哎,也是一个表是吧?哎,这个意思啊,然后在下边说,由于表啊没有固定的长度。就是你造的这张,你你这是个表,你这个表有几个元素啊,不确定。对吧,像咱们刚才提到了,说我这里边有仨属性啊,一会呢,我变成有四个属性啊,啊你这个到底有几个属性,就相当于这个表的长度是几,那一开始是没有严格说表只能长度是几的,那所以这时候呢,我们要想表示一张表,你得先呢,告诉我你这个表的长度是多少。
11:15
所以一般呢,我们会啊,下边咱们讲就知道了,大家在发现一个表的时候呢,通常在这个表的前面一个指令当中,都会表明你这个表的长度是几啊,主要原因还是因为是不是没有这个分隔符啊,你要有分和符,一个逗号或者一句号咱就知道啊,你这个长度就到这了,那现在没有分隔符了,你必须得先告诉我一个长度啊才可以。啊就这样啊一个意思好,那下面的话呢,咱们就通过一段代码呢,带着大家呢,去一点点去解析啊,咱就不看这个了,那其实按说这个也能看这个对应的不就是咱们讲的这个test这样的一个文件嘛,是吧,这个呢不太具有这个代表性啊,那那咱们写一个比较有代表性的,这儿呢,我放了一个啊,在我们这儿有一个叫DEMO。
12:00
嗯,这里边呢有呃字段field啊,也有这个方法啊,其实写的呢也不看,不算是太复杂,因为大家要写一个比较复杂,比如说我们代码层面呢,就有这个200行,那你要看最起码文件呢,基本上大家解析一天呢,你也解析不完啊,哎,这个是很明确的告诉大家,那那这儿呢,我们就先写一个比较基本的,先把这个事呢整清楚以后,咱再看复杂的对吧?好,那这个呢,我们先把它做一个。编译。先做一个编译。好编译完以后呢,我们再看到这个al里边打开。嗯,张二一好,这呢就是我们编译完以后生成的这个叫自解码文件了,啊把它呢CTRLC一下,咱呢就放在这个桌面上,然后就放这吧。嗯,这个方上面这个方这啊好,那把它呢,大家打开,比如使用我们这个no态加加开一下,嗯,那不就是它呗,然后把看把这个关掉啊,把它呢,在使用我们这个插件呢,进行一个解析啊好就它那我们要带着大家去解读呢,就是这样的一段信析。
13:06
啊,一点点我们从前往后呢,一点点去解读啊,那解读这个过程当中,我们为了做一个很好的验证呢,咱们再结合一下这个,比如说方式三吧,方式三的话呢,比如说大家直接双击。啊,就使用我们这个啊,相当于是这个杰克lab啊打开的,打开以后呢,这个就是咱们解析以后的这样的一个效果啊,咱希望呢,就是咱解析完以后呢,能跟这个呢,能够匹配的上啊,那就没有问题了啊,这上就我们要做的这个解析的这个事儿啊呃,那另外一个点呢,大家你会发现,你看我们这有一个自解码文件啊,如果我双击一下大家你会发现呢,我们这个资金码文件,诶正常资金码文件不应该打开以后看不到这样的一个像源代码一样。一个一个结果了是吧?呃,这个原因呢,主要是因为咱们这个字节码文件哈,咱们其实看到的呢,都是长这个样子的,那如果说我们一点点把它翻译出来,大家如果能翻译成这样的一个效果的话呢,实际上我们也可以呢,哎,把它对应的这个代码呢,给它再反编译出来。
14:06
诶,咱们idea呢,就比较强大一些啊,他就帮我们把这个磁解码文件当你一双击,说我在这块能不能看到这样的效果呢?诶不好意思,看不见啊,我呢,哎,能让你看到更好的就是一旦呢,你解析出这样的一些数据之后啊,比如说你有爱特方法呀,这个方法里边是什么样的一个执行的这个指令啊,根据这些指令我再给你反编译出来,你代码是怎么写的,哎,完全可以做到这个事儿。这就是这样子的,哎,这个里边大家你会发现呢,哎这么着一下啊。哎,这个我截个图。嗯,诶大家会发现呢,你看我们这个这是原程序,这个呢,是我们反编以后得到的,嗯,多了一个构造器是吧?啊因为本身呢,我们说这个原程序当中,你没有写这个构造器,它也会有一个默认空单构造器,那生成的自间码文件里边呢,是不是包括了我们说的这个叫,诶以构造器为代表的这个叫构造器方法是吧?那它帮我们在反编译的时候呢,就帮我们把这个构造器呢,就给我们提供出来了,哎,这是其一,那接着的话呢,我们会看见这个I的方法下边呢,你看它有这个Z啊,如果你这个number表示的是属是咱们叫属性了啊,其实叫field,呃字段的话呢,它会给我们加上这个this,这个呢,咱们如果自己去看这个资金码指令啊,就能看到这样的一些这个呃所在的这个位置了,相当于就是如果大家呃,你对这个比较熟悉的话呢,呃你能翻译成这样的这个结果,呃其实进一步呢,你也可以把我们对应的这个字节码呢,翻译成我们对应的这个原程序。
15:37
哎,远程序对吧,诶当然了,我们说呃,如果你要有一些注释信息的话呢,这个注释信息本身呢,它不包含在我们的自荐码文件当中,所以说这个呃,注释信息呢,就翻译不回来了啊,这个大家稍微注意一下这个事儿啊。好,这个呢,就是我们给大家强调的这个点啊,咱们接下来要做的一个解读啊。
我来说两句