00:00
那接着我们来看一下,叫方法返回地址,哎,叫return address,哎,这儿呢是我们说的战争结构里边的第四个结构,前面的话呢,我们已经讲过局部变量表,操作数站,动态链接,哎,我们下边来讲这个方法返回地址,相对来讲它是比较简单的,那我们前面也提到过,这个除了局部变量表和操作数站之外,这两个是咱们说的非常重要的两个结构,或者叫最重要的两个结构,剩下的这三个呢,动态链接方法访问地址和一些附加信息,在一些帖子和书上呢,统一的叫程真数据区。啊,真数据区这个大家也要清楚这个概念啊,就把这三个呢就合一起了,因为前面两个比较重要,就单独来讲解,那当然咱们在这个讲完动态链接以后呢,又讲了这个方法的调用,对大家呢,写这个方法,平时写代码的时候啊,对方法的一个调用情况呢,应该有一个更直接的一个认识的就啊行,那我们来看一下这个方法返回地址,哎,想要描述的是什么情况。
01:01
诶说呢,方法返回地址,首先呢,它是我们帧这个战帧当中的一个,呃,内存内存结构了,对吧,它存储的是什么呢?存储的就是该方法的PC寄存器的值。该方法的PC寄存器的值。那么大家先要说PC寄存器里存储的是什么?哎,PC寄存器呢,咱们说它存储的就是该方法要只执行的下一条指令的值,那我们把这个PC寄存器里边保存的下一条指令的值给了我们方法返回值什么意思呢?就是交给咱们执行引擎,让他呢去接着执行后续的操作,诶就是这个意思啊,简单来说呢,比如说。这是咱们这个战,这个占空间,这是一个战争对应的一个方法,然后这个方法呢,我们叫做方法A,在方法A当中咱们调用了方法B啊,这个方法B呢,就是当前战争,呃,在我们这个,比如说我们是在这一行代码中执行的这个方法B,导致这个B呢又加载进来,然后是成为当前战争了,当我们这个方法B啊正常执行完的时候。
02:13
诶大家想当咱们这个方法B呢,正常执行完的时候呢,诶它呢要把它的这个,呃PC寄存器,我们说PC寄存器呢,记录的就是下一条指令在哪呢?那就该执行这一条指令了,诶把这个地址在这儿,诶把它呢就作为我们这个方法返回地址呢,诶返回回去给了谁呢?给了我们的这个执行引擎,我捡起了啊就执行引擎,执行引擎呢,拿到这个地址以后呢,哎,他就能够接着知道啊我下边要执行这一行操作了,那我们当前这个B的这个战帧呢,就出战了,然后A呢又变成当前战阵,哎这呢就是我们说这个方法返回地址,它的一个作用就是来保存PD寄存器的地址值的啊,这个的值的啊。它对应的就是下一条地址值,好,那这块呢,我们说了说一个方法的结束啊,正常有两种方式,那一种呢叫正常执行结束,一种呢叫出现未处理的异常,非正常的退出,这个呢,对于大家来讲呢,是再熟悉不过了啊,那下边提到说不管呢,你是哪种方式的退出,在方法退出以后呢,都需要回到该方法被调用的位置。
03:20
哎,被调用的位置,然后正常退出的时候,咱们调用者的PC寄存器的值就作为返回地址呢,诶也就是调用在调用这个该方法的指定的下一条指定地址作为一个返回,你要是异常退出的。这是另外一种情况,如果是异常退出呢,返回地址就我们这个结构里边,它呢,呃,是通过异常表来进行确定的,战帧里边呢,我们就不保存这部分信息了。所以我们这个方法返回地址呢,它主要是针对于正常退出的这种情况啊,那正常退出跟异常退出的主要区别呢,这不刚才也提到了,就是你通过异常完成这个出口退出呢,它不会给它的上层调用者呢,返回任何的返回值了,诶这个这个情况啊,行,那比如说呢,就是咱们看一下我这已经写好的一个程序啊,这个程序呢,相对来讲也比较简单一些。
04:11
呃,整个上边呢,是有一些,诶没有异常的这种方法,那我们直接还是看到下边我在这个方法二里边调用了方法一,方法一呢,诶是咱们写了一段比较简单的程序,就是读本地的一个文件中的这个字符,把它呢输入到这个控制台上这样一个程序,那么在我们的这个位置啊,这个位置还有这个位置呢,都有可能出现异常,这个大家如果写过这个代码应该比较清楚,都有可能出现异常,嗯,那么一旦呢,在这个位置出现异常了。出现异常呢,我们这儿呢,还没有进行异常的处理,它就会呢,将这个异常对象呢,给他抛出作为诶咱们呃抛出给方法的调用者,我们是在方法A2里边调的这个方法一,所以呢就会抛给我们这个方法二,哎,就会抛到这儿来了。
05:00
嗯,如果呢,没有这个异常的情况呢,就正常执行结束,诶它就呢,把你下一行执行的这个地址呢,诶返回作为这个返回值给了我们这个方法二,哎给了我们这个方法二啊就比如说呢,呃,我上边呢,你看写的这些方法都没有出现异常,这个方法体我也没有写啊,那就相当于它这个执行的时候呢,就诶很快进去就很快就出来了,比如我们在这块执行一下叫VO这个方法呢,我放在这MA2里边去执行了,诶它执行完以后呢,就把它这个的呃。这个PC接听器的下个地址值,其实就是我们这个接下来要执行的MAC2的后续这个操作呢,哎返回回来,哎直接呢,我们直行引擎呢,就接着它往后走,就这个意思啊,就稍微的是有点枯燥是吧。行,那清楚这个意思以后,其实非常简单啊,我们接着呢,大家呢,再多看一点事情啊,你看说这个方法退出呢,有两种方式啊,这呢我们先来说一下这个正常退出,说一个方法呀,在正常调用完成之后啊,究竟需要使用哪一个返回指令,需要根据方法具体返回的这个类型来定,这呢我们一共有这样的一些类型,有I return的指令。
06:13
啊,它针对的是布尔bet char short int诶这样的几种情况,那这种这几种情况呢,咱们在讲这个局部变量表的时候呢,也说过是吧,局部变量表的时候呢,呃,这几种类型它也都是放到这个int型占一个呃,32位的slot一个槽啊然后呢,还有这个l return啊,这个是针对long类型,这是float的啊,然后这是double的,这个是针对引用类型的啊那如果呢,你要是一个wide的方法,它呢直接就用的是return指令。以及呢,包括我们说的这个构造器啊,类活接口的这个初始化结构啊等等,它呢,都是用的这个return。好来咱们演示一下啊,当年这个程序呢,我们可以呃给他做一个呃,Re compel啊,重新做一个编译。
07:03
编异完以后的话呢,嗯,咱们可以直接在这个位置啊,可以看一下这个结构啊,哎,这就出来了啊,以防万一可以刷新一下,那这块呢,我们看一下这里边的这些方法的话呢,诶我这个命名呢也是有技巧的,只要呢是method后边是什么类型,它的反问值类型呢,就对应的是什么类型,那比较清楚,好那回过来我们先来看一下这个波尔类型,它呢是I return,就是代表是以int类型呢来返回的。这是bit的情况。少的情况。差的情况。Int啊,都是I return以int类型啊来返回,然后呢,Long呢是l return float呢是f return。这个呢是double是吧,D return OK,然后接下来的话呢,我们这是string跟date啊,我这是放了两个不同的类型的,两个不同的这个引用类型,他们俩呢,那都是以引用类型作为返回的,叫a return。
08:04
A return OK,没有问题,挺清楚的啊,然后下面的话呢,我们是一个word的方法过来,其实之前咱们也见过啊,就是一个纯return。哎,就完事,那另外呢,我们说在一个类当中啊,它还会有构造器,包括呢,甚至还有这个静态代码块,对吧?哎,这个静态代码块来我们看一下这个构造器,构造器的话呢,它其实也是一个在我们自解码文件里边也是一个方法了啊init这样一个方法,诶你看它用的也是称相当于是一个没有返回值的一个方法,然后呢,这个CL呢,是咱们这个类的这个构造器的这个方法,它呢也有一个return,诶是这样子的,诶它们呢,都属于这个返回的是return,呃就是用的是这个return指令的情况,所以我把咱们刚才这个PPT里边的这个,呃这段文字呢,就整个呢就拿过来了啊,我就不用写了,就啊针对这些类型都是a return,然后还有这样的一些类型啊,知道a return也知道呢,我们说的这个return OK,就是这样的一些指令。
09:04
这呢是咱们说的这个正常执行完成,它会有这样的一些自解码指令,那如果要是异常情况呢。对吧,我们说第二种方法结束的情况呢,就是出现了异常了,那并且这个异常呢,还没有在方法内呢,进行处理,这个时候呢,嗯,也就是说只要在本方法的异常表当中没有搜索到这个匹配的异常的处理器,我就异常退出了,那对于咱们这个METHOD1来讲。这个异常的话呢,如果出现了,我们就没有处理,对吧,然后呢,对于这个MAC2来讲呢,出现异常的话呢,我们就进行了一个处理。哎,当然前提是你这个异常能够把它,呃,出现的任何MA1出现的任何异常呢,我们这个MA2这个catch都能搞得定啊,是它的异常的一个类,哎,我们可以这个处理的啊,负类的类型的行,这儿呢是我们说的这个异常的情况,那我这儿呢,就提供了一个叫异常表,咱们后边讲字节码指令的时候呢,还会提到这些结构啊,那这个怎么看呢。
10:08
这样看哈,说如果呢,你是在注意咱们这儿呢,写的46,这是自解码指令的这个地址,不是咱们这个代码的这个行号哈,是自解码令的这个行号,他们俩不是有一个一一对应关系吗?呃,如果你是从第四行到第16行这个字节码指令中出现了一场,那就按照第16行这个字节码指令的这种catch始的方式进行处理,针对的是任何类型,如果是19~21行这块出现的呢,就按照这块来处理啊,针对任何类型,这就是我们说的异常处理表。啊,异常处理表,嗯,这个异常处理表呢,咱们不是在这看的哈,这个我是用这个jarp啊来演示的,所以我们这块呢,先通过这个jarp呢来解析一下,嗯,我这呢是把这个代码放到JAVA3这个包下了,所以先CD。给三一下。啊,写错了点点是吧,然后CD23,然后呢A2杠。
11:05
我们是。诶address test.class诶打开了,然后呢,我们找一下这个谁呢,方法二啊。这有点长,方法一再往上。哎,这是方法二,方法二呢,它不是有这个异常的处理吗?我们就去找他这个异常处理表,诶在这呢。呃,说呢,是从这个第四行到第八行,是按照第11行来进行处理,四八十一,其实你在这看也行,四。呃,第四行到第八行哈。从这到这儿,一旦呢,你出现这个八的时候呢,Got to直接蹦到这个16这。呃,蹦到这个这它是蹦到这个16,这就算是结束了,这是言外之意呢,你要没有处理的话呢,就结束了啊,我们这块呢,你要是处理的话呢,就按第11行这个方式来进行处理,那四八十一对应的咱们这个代码是第几行呢?我们来这个接lab这块来看一下。
12:06
找到咱们这个二。诶,打开。诶在这个位置呢,你看其实也能看啊,只不过呢,这个格式呢,跟咱们在这看这个格式不太一样了,我这呢就觉得这样比较清晰一些,所以就粘了咱们这个扎P的指令的啊,在这也能看出来四八十一对吧,四八,然后我们再打开看一下这个。嗯,四八是吧,四八呢是72行到七十五行,72~75,哎在这块出现这个情况啊,然后呢,按照这个11,诶这个11是咱这个73,哎七十三七十三这不在这进行开始吗。哎,就是如果呢,你要四八这块出现了这个情况的话呢,我们按照这个11的这种方式来进行异常的一个处理。哎,是这样这个意思啊,行这呢,就是说明了一下,咱们这个,呃,异常处理表,这个大家能够基本上能看懂知道的意思就行啊,重点呢,我们讲这一节需要大家掌握住的啊,需要大家掌握住的就是方法返回地址,它记录的是什么呢?就是记录的咱们PC寄存器存储的这个值啊,把它作为返回地址。
13:15
啊,这呢是针对咱们正常退出的,你要是异常退出呢,我们就不保存这个信息了,啊是这个意思,哎,这个这也说过了,说本质上呢,方法的退出。就是当前战争出战的过程,因此呢,咱们需要恢复上层方法的局变量表操作数站,诶将返位置地址呢,再压入你敌王者的战争的操作数站啊,然后设置PC寄存器的这个值等等,呃,就是为了恢复我们调用当前方法的前一个方法,所以呢,你得方返回地址,把前一个呃接下来要执行的这个指令呢给人家返回回去,诶就是这个意思啊,就跟咱们说这个接力赛一样,诶你跑完以后呢,你把这个棒呢再传给假设就是你俩人接力啊,哎,这个人的话呢,先把这个棒给了你了,传给你了,然后你这块呢,跑完以后,跑完一圈呢,回来以后呢,你再把这个棒呢再交接给人家,诶这呢把你执行的下一条要执行的这个地址指令呢,你给了执行引擎,执行引擎呢,接着去执行人家下一个这个方法啊好,这呢就是方法返回地址的一个说明。
我来说两句