00:00
那第一章呢,咱们就说到这儿,重点的话呢,就是我们解读class文件结构,好这个呢我们就结束了,然后下边呢,咱们来看一下第二章,第二章的话呢,叫做自解码指令集与解析举例啊,这个是什么意思呢?这个咱们从第一章呢给它引过来啊,这个第一章啊,咱们主要讲的是自解码文件的这个解构,咱们是以这个DEMO这个类生成的字解码文例呢为例呢,咱们来进行的一个解读,对吧?那几度化呢,咱们也说过三种不同的方式,一个呢,就是咱们自己一个一个的这样去解读,这也是咱们花的篇幅比较大的这个地方。第二个呢,使用扎P咱们也讲了,第三个呢,就是使用我们第三方的一个插件或者叫工具,咱们在第二当中可以使用这个jup lab。这块呢,我们就能够呈现出来,对吧,那我们主要呢,解读的就是这个信息,那使用这个j lab这块呢,实际上呢,就帮我们把这个资金码文件一个一个呢给做了一个解读,哎,然后以相应的这个结构呢,给我们呈现出来。这呢是咱们第一章当中的主要内容,咱们第二章主要要做什么事呢?咱们就回归到咱们第一章当中那个漏掉的那个部分,咱们漏掉哪了呢?就是关于一个方法,它的方法体的一个执行的具体细节,对吧?那具体这个执行细节的话呢,我们就会找到方法表集合当中具体的这个方法内部的叫做扣得属性。
01:23
这个咱们上一章当中都提到过这个事儿,行,那么扣掉属性当中这块呢,呈现到的是不是就是我们说的自己码指令啊。对吧,那咱们在一开始引入咱们讲这个中篇的时候呢,提到过很多这个方法的,这个方法起啊,咱们如果只是从代码层面来看。大家还记不记得咱们当时举的这个例子对吧?像这个例子,这个例子这个例子,或者是咱们说的这个string这个例子,那我们从代码层面来看的话呢,New了两个string中间做了一个连接操作,也不知道它底层到底是怎么做的,那对于我们来讲,直接呢,是一个自动装箱,它底层是怎么设计怎么做的,为什么这两个它就相等了,我们如果看这个代码的话呢,实际上大家是看不出来的,对吧?那要想我们对这个执行的细节更清晰的话呢,咱们就需要呢,去解读这个字解码的指令。
02:18
啊,就是这些细节的这个指令,那这儿呢,就是咱们这一章的重点。哎,就是咱们这一章的重点行,那包括咱们说对于Java程序员来讲,咱们去设计一个项目或者系统的时候呢,呃,我们说设计一个类,这个类呢,咱们主要的精力呢,也确实花在是不是方法的设计上呀。对吧,方法在设计上,而且呢,我们通常说一个类它的功能强大啊,这个类强大,那个类感觉不行是吧,这个功能很很薄,或者说这个类是干这个的,那个类是干那个的,主要的体现其实就是通过方法来体现的。对吧,那主要就是通过方法,像这些属性,咱们也都是在方法内呢,进行了一个调用啊,通常都是这样子的,如果你在方法内呢,都不掉这个属性,那咱们也没有必要呢去声明这个属性了,或者说呢,我们把这个相应的变量呢,咱们就生明在你这个方法内了,对吧。
03:11
嗯,注意我刚才这个词呢,还是说习惯了用的叫属性,严格上来讲,咱们从字解码的角度来说,叫field,那就叫字段,翻译成字段啊更合适一些。好,那我们设计好一个方法之后呢,咱们通过一个类啊去调用,那就是静态方法,或者呢,非静态的方法呢,我们就通过当前类的实例呢进行调用,这呢是咱们的一个主体过程,那么调用的时候,这个方法到底都做什么事了,我们从自解码的角度就来看一下这个相应的自解码指令。哎,这呢,就是咱们这一章说的这个重点,好,那首先呢,我们来看一下这个整体的概述,整体的概述说Java自解码对于虚拟机就好比是汇,汇编语言呢,对于计算机都属于基本的执行指令。啊,一方面呢,叫做基本的执行指令,另外一方面呢,也是看作咱们相应你操作这个相应一些数据的时候的一个原材料,对吧?对于虚拟机来讲呢,资金码就是你的原材料,对于我们基于像叉八六架构的这个计算机来讲,汇编语言呢,就是它的一个原材料,啊这样来理解,那这呢也都算是我们说的基本的这个执行指令。
04:15
基本的执行指令就类似于像最起码呢,我们可以看成是虚拟的一个汇编语言一样啊好,那下边呢,这个比较重要的,我们看一下。说Java逊尼的指令啊,就是我们所谓的字节码指令,它是由一个字节长度的,代表着某种特定操作含义的操作,呃,数字,这个数字呢,我们就称为呢,叫做操作码。Up code叫做操作码,以及呢,它在后面呢,还可能跟着零个到多个,代表此操作所需要的参数,这个参数呢,我们称为呢叫操作数,叫op啊哎,这个相当于我们一个指令的话呢,是由两部分构成的,注意一个呢叫做操作码,一个呢叫做操作数,那典型的代表我们可以先拿咱们说的ADD,或者说咱们当时解读这个。
05:05
DEMO的时候,咱们艾这块呢,是没有具体给大家来说的,因为说跟上面这个init方法类似是吧,那咱们不妨就看这个上面init方法,它的这个code里边这块呢,就是我们所谓的这些指令,说这个指令呢,应该有两部分构成,那我们先以这个比较典型的第二个来说,这个invoke special就是我们称为呢叫操作码,我简写了啊,然后后边这有一个叫景一是吧,实际上呢,是指向咱们常量池当中索引为一的这样的一个位置,这个呢,我们称为呢叫操作数。叫做操作数up code,这叫up是吧?哎,操作码加上一个操作数,中间呢,注意其实不是个加号,是一个空格来表示的,对吧?好,那我们也看到了,像上面这个叫lo的下划线零,注意这儿呢,也是一类典型的操作,它只有操作码,没有操作数。
06:00
包括下边这个I_一,这也只有操作码,没有操作数,Return呢也这样对吧,那put field呢,是有个操作码后边有个操作数的。我们会看到,包括咱们下边要展开学习的时候呢,大家会发现有很多的这个自解码指令都只有操作码,没有操作数,哎,注意这样的一个细节啊,没有具体一个操作数行,那对于咱们说的这个in来讲,你看啊,这个lo_零我们点一下,它会跟咱们Oracle官方的这个说密文档呢做一个关联,直接呢就链接过来了啊漏的下划线零,它分配的这个值呢,叫做2A,十进制是40 26进制呢,就是2A,这个2A你看我们在这里边是不是也可以找得到呢。这个咱们得再来分析一下,咱们当初说到这儿的时候呢,是你这个方法里边的属性计数器,咱们这只有一个属性,那其实就是in这个,嗯,In里边这个扣的属性对吧?然后再往后这个零九就是这块属性免索引,这四个呢叫属性的长度啊,这两个呢,我们叫做操作数占的最大深度,这呢叫局部变量表的长度,再后边这四个呢,是资金码指定的一个长度,然后再往后这块。
07:13
这2A2A是多少啊,应该是十对吧,那这四五六七八九十,这不就这十个吗?这十个呢,对应的就是我们这个颜色的,就是具体的自己码指令,那这十个代表的其实就是我们这块的这个区域。我把这块截个图。盯一下,好,我把这个截个图回过来,呃,大家注意这里边我们看到的这些,呃,咱们说这叫资金码指令,实际上呢,也可以把它呢叫成一个叫助基符。帮助我们去记忆的。主机浮对吧,你像我们这看到这个2A,这是不是就2A啊,这个2A其实代表的就是A漏的下限零,咱们刚才不在这也看到了A漏的下限零,它是不是就是2A啊,那这个2A呢,其实是我们本质上的这样的一个字节,咱们说这一个框不就一个字节嘛,这个字节呢,其实对应的是一个二进制的数,只不过我们现在是以16进制来显示的,对吧?那这个数呢,我们给它分配一个诸积符,这个诸积符呢,就做就叫做lo的零,方便呢,咱们去识别到底是谁对吧?你要写2A的话,你能记住这个吗?显然记不住嘛,所以这呢就是个主基符,我们也称为呢,就是具体的,不管你看2A也好,还是看它也好,这都叫最金码指令,对吧?
08:31
然后下一个呢,叫invoke special,这个special呢,基本上你也能够猜得出来,我们一点击它的这个值,是不是就应该是我们刚才看到的这个B7吧。就是它对吧,然后你这个special后边呢,是有一个操作数的,这个操作数呢,在这呢,我们用的是两个字节来表示,这个是叫零一,那就是指向咱们上边常量池当中这个零一这个索引位置。嗯,你看这个零一这个索引位置对应的不就是常量池中这个索引位置它嘛,对吧,然后这个呢,是一个方法引用,呃,指明了我们这个所属的这个结构,或者我们称为这个叫呃对应的这个类是object类里边的哪个结构呢?呃是那个其实就是我们说那in方法啊,这个in方法呢,它的名字是叫in,然后呢,描入符是word的,是没有参数的。
09:19
哎,它所属的类呢是object,哎,就是这样个情况,哎,就是我们这里边要调用的是这个类当中的这个方法对吧?哎,这个大家稍微注意一下行,它呢是有一个操作数的,然后下边又有一个LO0,下边这个LO0,那不对应的就是我们右下边一个这个2A吗。对吧,哎,那大家意思呢,进行解读就可以了。啊就可以了,所以这里边我们看到这儿呢,一个这个叫什么呀,一个字节是吧,它代表的就是一个呃,操作码对吧?啊一个操作码。好,这个我们再回到这个介绍这块来说,那由于我们说障碍群机限定了我们这个操作码呢,是不是只有一个字节大小啊,那一个字节呢,咱们说是八个位,一共呢,就是可以组成二的八次方,这么多种情况对应呢就256个,那相应的就是我们字节码这个注记符也好,叫指令也好,是不是就不能超过256吧。
10:12
哎,不能超过256256啊,那官方的这个地址,那这块呢,大家CTRLC其实也就对应的我们这个地址,大家就往上拽也行。啊,这就我们这个第六章对吧,那这里边儿呢,就是我们具体这些指令,这也是咱们这一章的重点,就是解读这些指令,那目前的话呢,有200来个,200来个啊,这个在可预见的未来,我们也不会超,超不出这个256,所以呢也足够我们去使用。那我们这当然了,你用一个字节能搞定的,是不是就不要用两个字节啊,那直接把文件小一点是不是对我们不管是数据传输也好,解读也好,是不是意义都很大对吧?好。下面也提到说,对于熟悉啊,自解码指令,对于我们说,呃,动态的自解码生成反编译class文件,或者class文件的一个修补都具有非常重要的价值,所以呢,这也算是我们学习Java群机的一个基本技能。
11:03
啊,一个基本技能,不管是我们看官方也好,还是我们看到相应的一些书当中也好,这个中文的也好,英文的也好,大家会发现关于字节码的一个解读,也都是非常重要的一个章节,啊这呢也是一个我们对于Java程序来讲一个基本的技能。啊,一个基本的技能,或者说呢,不是Java程序员,我们这个使用别的语言呢,你通过编译器编译好以后,是不是也是满足我们第一章中讲的这些结构,对吧,那相应的这个指令呢,也都是,呃,我们的这些能够识别的指令,那大家呢,去熟悉这些指令的话呢,就有助于我们去解读这个方法体到底执行的细节是什么。啊,甚至说呢,大家如果对于这些自己码指令比较熟悉的话呢,我们自己都可以反编译出来,它对应的这个方法体是什么样子的啊,基本上八九不离十,所以呢,这也相当于一个反编译的一个功能啊。好,那下边呢,我们再看一个,这个叫执行模型。这些模型是什么意思呢?呃,是这样子的啊,就是我们呢,对于Java虚拟机的这个解释器,它用于解释执行咱们的资金码文件了,对吧,那怎么去执行这个过程是什么样子的,实际上是对应的一个循环结构。
12:10
那首先呢,是自动的计算PC寄存器的这个值,让它这个值呢加一这个PC寄存器呢,是咱们上天讲到的内存中的一个结构,哎,不知道大家呢,是不是还比较清晰啊,咱们说呢,这个在。Java虚拟当中,咱们是基于这个站结构的啊,这呢是我们一个站。啊,这个叫战一啊,这呢也是一个站,这个我们呢叫战二,那咱们说一个线程,一个线程是不是对应着一个站啊。一个虚拟战对吧,就咱们平时说的那个战啊,那这是一个线程,这一个线程,然后这个战一里边我们有一个方法,就叫对应了一个战针,然后这个方法呢,又调用了这个方法,然后这个方法又调用这个方法,现在呢,这个调用系统资源正在执行,我们比如说这个方法中的某一行代码,那现在这个资源呢,切换到我们执行战二的这个线程了,那切换过去之后呢,如果回头又切换回来了,我们是不是需要专门记录一下你刚才战一当中执行到哪了呀?
13:04
然后我们再接着往往后执行呗,对吧,那记录一下你执行到哪了,是由谁来做的呢?就是PC寄存器来做的。比如说呢,我们在执行咱们刚才提到的这个叫这个伊利的这个方法,对吧,这个方法呢,假设我们现在执行到这个B7了。那B7呢,我们就记录一下它的这个位置。啊,记录一下它这个位置,然后呢,我们PC寄存器发现后边,呃,当然这个是循环进来的,一开始就是头部呗,对吧,头部的话呢,我们这块加个一就是定位到它第一个位置了,然后假设呢,现在我们比如说就定义到这儿了,那加一之后我们呢,就根据这个指示的位置呢,从字节码流当中呢,取出这个操作码,那操作码一取出来啊,这个B7是一个evoke special行,然后接下来呢,我们再看一下你当前这个。呃,操作码后边有没有存在这个具体的操作数啊,那我们一看,对于这个special来讲,后边存在,那我们就把后边这个零音呢给它再读出来,那操作码配合这个操作数这个整个在一起,咱们就执行它对应的这个操作。
14:07
那执行对应那个操作就可以了,那执行完以后呢,我们看这个形码长度是不是大于零,就是你是不是后边还有这个数据,如果有的话呢,我们这个PC寄存器的值呢,再加一再加一是不是就开始执行到这2A啊,哎,接着往后走就行。那这个呢,就是我们去这个解释运行读这个词金码文件的时候呢,就一点点的往后这样的进行一个循环操作就可以了。行,这个呢,整个大家做一个了解。
我来说两句