00:00
那讲完这个战争里边具体的,呃,这个各个部分结构以后呢,我们下边呢,就具体来说一说每一部分结构的一个作用和它的一些使用细节,那这块我们讲解的话呢,基本上就按照咱们这个说重要性的一个先后顺序,那首当其冲的话呢,我们就来讲一下叫局部变量表,诶这个英文呢,叫做local variables哎,所以呢,正常的也会翻译成叫本地变量表,因为local呢,翻译成本地叫局部都可以,就跟咱们说这个局部变量一样啊,也是local variable行,那么局部变量表呢,也称为叫局部变量数组,或者呢叫做本地变量表。啊,那之所以叫做局部变量数组,是因为这个局部变量表表嘛,这个大家应该都清楚啊,就是有行有列,它其实当然这个咱们平时说这个表呢,它是一个二维的啊,有行有列,那这块呢叫表,其实它还是一个一维的,是一个数组啊,数组可以看成是个一尾这样的一个形式啊,定义为一个数字数组,那存的数据呢,主要就是方法的参数,从这个行参开始算,这个定义在方法体内的局部变量。
01:08
啊,当然这里边儿呢,像实例变量的话呢,当前这个对象其实也是作为这个局部变量表中的一个,呃,这个位置啊,一个索引位置来存储的。那么这里边这个变量呢,我们说都包括哪些类型呢?呃,有基本数据类型,那这呢,就咱们说的八种基本数据类型,还有呢,引用数据类型中的这个对象的引用,呃,这个reference以及呢,Return address就是返回值这个类型,诶就是可以存储这些数据,那关于这个局部变量的表呢,大家最先记住的就是这句话。诶,它是一个呃数组,呃,是一个数字数组,为什么叫数字呢?因为咱们说的这个基本数类型,咱可以先来看一下这个这个吧,一会儿咱们也会说到像基本数据类型里边这个BAT short,这个int long,对吧,本身它们就是数值,加上这个float呀,Double啊,它本身就是数值了啊,然后呢,这个叉类型呢,咱们说它也会有对应的像X码啊或U库的值啊等等,所以呢,也把它看成是这个int类型。
02:09
啊,并且呢,我们说这个八种基本数类型中的这个七种,除了布尔类型,那它们七种都可以做想加减乘除运算,那进而呢,证明差类型,呃也是可以转换成int类型的啊,因为有对应的这个unode值了,然后布尔类型呢,这个呢跟咱们说的这个C语言有点像了,我们用这个零呢表示false,非零呢表示处,那那就意味着咱们八种基本数据类型其实都可以用数值来表示的,那再加上呢,咱们说的这个引用地址啊,然后返回值类型啊等等,诶,他们都可以用这种数值类型啊来表示啊,返回值类型其实无外乎也是基本数类型或者这个引用类型啊,都是一个数值型的,所以这个数组的类型就是呃数字类型的。那叫数值,这都可以啊,然后下边说,由于这个局部变量表呢,它是建立在现程的站上啊,归一个一个战帧是吧,一个战帧呢,有一份,呃是线程私有的数据,所以呢,不存在数据安全问题,这个我们说这个数据安全问题呢,呃主要呢,就是指的是多个线程如果来共同操作它的话呢,操作一个共享数据,诶会有这种安全问题,因为呢,你这涉及不到共享的问题了,所以就不会有安全问题啊,这是这个问题,好,然后我们看下一条哈,说这个局部变量表啊,它所需要的容量的大小,所需要的这个容量的大小是在编译期呢就确定下来的,哎,保存在我们相应的这个属性的这样的一个呃变量数据项当中。
03:39
在运行期间呢,不会随着这个诶不会改变局部变量表的大小,说白了就是这个大小呢,一旦确定下来就不会被更改,诶是这个意思,那么关于他在编译器确定下来这个事呢,咱们做一个验证啊,做一个验证好这呢我已经写好了一个代码了,那这个代码呢,是为了咱们演示的方便,我做了一个,呃,就是特意的一个精心的一个设计啊,所以这呢,本身这个代码呢,其实这个细节呢,没有多难,呃,咱这块呢,就直接看一个这个现成的就行啊,那我们演示刚才说这个事儿呢,咱就以这个没方法为例啊进行一个说明,那我们说每一个方法呢,这不都是对应着算是一个战争,哎,都是一个战争,好,那咱们呢,现在点右键rise s,相当于把这个主线上呢跑起来了。
04:25
嗯。这个呢,提示说找不到或无法加载主类,这个我们先给它重新的在这编译一下哈,因为我这个文件呢是被替换过,所以呢,我再重新粘过来的时候呢,它会给我提示这个问题了,来我们再重新的执行一下。好了出来了啊行,那我们这呢说一下这个魅方法,我们现在呢,把它执行起来以后呢,在当前这个主线程的这个战当中,我们就把这个没方法,首先呢,是把这个没方法呢,作为一个战争呢就加载进来了,那我们现在呢,来考虑这个没方法的这个战争内部的局部变量表,诶考虑它的这个局部变量表,嗯,一方面呢,大家可以在咱们的这个termindo这块呢,做一个诶扎P的一个操作。
05:13
哎,在这块啊,咱们还是写在这个JAVA1的这个下边的,所以我这呢就诶Java p这个Java p呢,诶之前呢,我一直说它叫一个反编译的操作啊,有的同学呢,可能会想反编译不就是说把这个自件码文件又还原成我们这个像这个这个Java源代码嘛,说这不叫反编译,这不才叫反编译吗?就比如说像咱们这个idea呢,本身它就具有这个反编译的功能,像大家呢,在这儿看到的。诶先说个小插曲啊,在这看到呢,其实就是点class自解码文件了,这个磁解码文件呢,按正常来说,我们CTRLC一下,大家放到这个桌面上,呃,你试图呢,比如说你用这种记事本打开它是相当于就像乱码一样啊,是看不了的,那但是我们在这个idea当中呢,大家双击打开呢,你会发现呢,诶也是跟我们写的这个Java代码很像,这是因为idea呢,它本身具有一个反编译的功能啊,是这样子的,那咱们现在呢,叫javap,呃,叫反编译呢,呃,其实稍微有点牵强,你可以呢,就把它理解成。
06:14
咱们使用jarp这个命令呢,对咱们这个字节码文件进行了一个解析,啊,进行了一个解析,就像咱们在桌面上呢,大家直接双击打开。看到的这样,这其实就是理解成是一个解析啊,是这个样子啊,你要说没有解析是什么样子呢,可以理解成就是咱们用的这个bary viewer。用它来打开。这儿呢,我把它直接呢就拖进来。这样子这个呢,你可以理解成它是一个原封不动的一个样子,是没有解析的一个格式,然后这呢,就像是诶还原成对应的这个这个字符了啊,就是解析以后的一个效果啊嗯,这个大家清楚这个问题,所以我们这个jarp呢,你可以称为就是咱们将这个自解码文件呢,进行了一个解析的操作啊,就是有时候呢,也就泛泛的就称为叫反编译了啊行,这个大家能够理解这个事。
07:09
然后呢,我们叉P-V啊local。Variable test.class行,嗯,我是不是写错了?Local variables少一个S。行出来了好,那出来以后呢,诶大家从这个角度,就是咱们这个扎P这个命令这个角度呢,实际上呢,就能够,诶看到我们这里边的一些关于方法,我们叫一个战争的信息了,比如说咱们现在呢,想看的是这个may方法,对吧?哎,这个may方法,然后在这个位置呢,叫LOCALS3,实际上这个三呢,就是指的咱们这个局部变量表的一个最大的长度,就是我们这个数组的长度啊其实呢,就是三或者呢,大家你往下看。在这个位置呢,你看局部变量表,哎,局部变量表就是我们这个方法内的,这不都算叫局部变量表吗?哎,一共呢是有012这三个三,这012呢指的是它的索引,那是有哪三个呢?大家看那第一个呢,就是我们的行参叫做X。
08:15
啊,是string类型的一个数组,这个L呢表示的是引用类型的意思,然后第二个呢,是我们这个当前这个类的一个对象,叫做test,引用类型的是这个类型的一个test的这个变量名,然后下一个呢,是我们这个定义的int型的一个number,这呢是一个int类型,Number是它的名字,它在所以二的位置上,所以在这呢就能看到我们这三个值。那那刚才有同学说了,说不是说这个最大容量嘛,你现在只说的是个容量,那其实这个容量呢,指的就是最大容量。啊,那我们再换一个方式来看呢,就是咱们前面说过呢,大家用这个叫诶接class lab啊使用它是可以的,这个插件呢,如果大家没有装的话呢,你再去安装一下,前面咱们已经讲过了,在这个设置呢,Plug in这块呢,你输入j class lab bad code viewr,你去输入接class s其实就可以了,然后呢,你把它做一个安装,诶安装完以后呢,这个时候当然前提呢,你先编译啊,编译完以后我们在这呢,就能够看到这样一个选项打开,好大家来看啊,嗯,在这块呢,列举出来了,实际上这就是我们整个这个字节码的一个整体的一个从上往下的一个格式了。
09:27
像涉及到这个,呃,一开始其实是个魔术,看这个咖fe baby是吧,后边呢,就是我们的最小版本啊,这个这个最大的一个版本啊等等等这些信息,这个咱们现在呢,不过多的给大家去讲解,咱们再讲到下一篇字解码和这个类的加载的时候呢,咱们再重点的讲这个内容啊,实际上这个Java虚拟呢,有一点不好讲,在哪呢?是因为咱们讲这个内存和这个垃圾回收吧,他会嵌套着讲这个磁解码这块,然后要上来就讲字节码吧,大家又会觉得很枯燥又不形象,所以呢,就是这个知识呢,就是相相当于是你中有我,我中有你,大家相互之间嵌套着先讲哪个呢,感觉都差点意思,那我这块呢,就是还是以咱们内存和垃圾回收为主线,因为呢这块呢,大家相对来讲还是比较熟悉的啊,因为大家长期都在写Java代码,对这块呢是印象比较深一些的,那么在这个过程当中呢,咱们也会穿插着呢,把这个自检码指令这一块内容呢,根据需要进行。
10:28
个讲解,所以不会全面的去讲,然后呢,诶,奔着我们还是对内存的一个更深入的理解,我们来讲,那么关于字节码的完整内容,从全局上呢,包括哪些知识点,然后细节上呢,又是怎么样来展开的,这个咱们放到这个中篇,哎,来具体展开来讲。就像咱们前面讲这个类的加载一样,这个class order sub system,类在加载器,包括呢,这个双性品派机制啊,沙箱安全机制等等这个主体的东西咱们都讲了类在加载的,呃,第一个过程叫加载loading啊,Linking这个链接,还有这个initialization啊,初始化,包括呢这个链接,链接里边呢,又分成这一开始的叫验证,对吧,还有verify,还有这个prepare准备,还有最后一个。
11:13
最后一个环节叫什么来着,呃,叫这个。解析是吧,呃,Resolve啊,解析就是这样的一些环节,主体上我们都讲了,这个大家能够清楚,包括呢,像我们在这个prepared环节呢,有一个静态变量的默认初始化,对吧?然后呢,在初始化这个阶段呢,我们有一个静态变量的显示初始化和静态代码块的一个执行,像这一点呢,大家都清楚就可以了,等我们到这个中篇讲自节码和类的加载时候,我们再详细的展开,包括如何定义,呃,这个自定义的类的加载器等等,我们再展开说,啊所以这块呢,我们基于需要,基于咱们对这个内存理解的需要,咱们来看一下这块的一个四解码指令,所以直接就定位到咱们想看的内容。在方法这块呢,我们能够看到呢,一共是定义了这样的一些方法,咱们现在主要关注的是这个may方法,然后这个main方法,下边呢,就是它具体这个code打开以后,诶,我们先来看这个code,然后在这块是它的字,这个字解码是从零一直到15,实际上呢,跟我们在这看的诶从零到这个15是一样的啊,是可以对应起来的,行,这是这块内容,然后这呢是异常表,因为咱们这个密方法呢没有异常,所以这块呢就没有信息了,然后在第三项,哎,大家看第三项呢,我们就看到了这样的一个信息啊,最大的局物变量表,它的一个长度,这呢是三,哎,这就是我们刚才说到的这样的一个值。
12:41
啊,这样一个值,那这个值呢,大家看到了,咱们现在呢,是编译以后拿着这个自检码文件来看的,那说明呢,就是我们这方法。以这个main方法为代表的啊,所有的方法在编译完以后就确定了它这一个战争中局部变量表的长度。
13:05
啊,这个我在这已经写了,所以我就不不在这个代码中再敲一遍了啊,这个能清楚这个意思,这个已经确定下来了,而且这个长度呢,在运行时候不会改变。诶,就是这样子啊,下边这个呢,叫Co LAS,就是它的一个整个我们那个main方法,它的一个代码的长度,这写的是16,诶你看它这个是15,就是它这后边还有一个这个像收尾的一个大括号等等啊,就一共呢算是有16条指令啊,16行就是这个lengths的意思。啊行这块呢,我们看到这个三啊就可以了啊行,那这块大家清楚这个事儿。然后呢,这块这两个段落的内容呢,其实大家这个咱们在讲上一节的时候呢,都说过了啊,再稍微的温习一下,说方法嵌套的次数呢,由占的大小决定。啊,这个很显然对吧,这个你这个占越大,不是这个占越大的话呢,当然方法签到的次数就越多哈,嗯,那这个方法的话呢,我们说又是由它内部的这个战争来决定的啊,其实这个就是这呢是如果固定下来的一个战的话呢,呃,你能够到底到这个战占越大,当然这个方法嵌套的就越多了,那如果站在固定的前提下,那方法的话呢,你要是占的空间越大。
14:19
啊,这块我我占的特别大,直接呢就报stackflow了,哎,就是方法的大小决定了我们可以嵌套调用的次数的多少,那方法呢,就叫一个对应的一个叫战针,战针里边主要呢,来影响它的大小的就是我们的局部变量表。啊,就是局部变量表啊,就是我们说的这个事情啊,行,这就上面这个具体的一个描述,我们就不多说了,下边提到了,说局部变量表当中的变量啊,它只在当前方法中是有效的啊,只在当前方法中有效,那方法执行时啊,虚拟机通过使用求求变量表完成参数值到参数变量列表的一个传递过程。
15:00
啊,这个咱们后边呢,讲这个具体的自源码指令的时候呢,像提到比如说这个load,哎做加载,还有做这个store存储,诶就是从我们这个局部变量表表里边往里边放数据,取数据等等,诶这个呢,都依托于咱们这个局留变局部变量表。啊,这个简而言之,这个纠边表就是咱们方法内部。在这儿方法内部定义的这个行参呀,呃,这个局部变量值啊,包括它的返回值啊等等,哎,都存储在我们的这个局部变量表当中,哎,就是这个意思啊,那当方法结束以后呢,你战争也没了,战争也没了,局部变量表当然就没了,就是我们所说的叫,哎这个叫什么?皮之不存,毛将焉附是吧?皮之不存,毛尖焉附啊,对着呢,没说错,皮都没了,然后毛也没有了是吧,或者叫兔死狗烹是吧,兔子死了,那狗也跟着没了,当然这个皮之不存,毛尖焉腐更合适一些啊嗯,行,这呢就是我们对这个局部变量表呢,大家先有一个初步的一个认识啊,然后接下来呢,咱们再进一步的看一下这个呃表格,通过这个表呢,我们再对这个局部变量表呢,有一个更深入的认识。
我来说两句