对于非静态的方法,总会有一个this参数
test()方法有4个局部参数,分别是this,is,serverSocket,ex。catch语句只会执行一条所以只有一个ex
下面来讲异常部分
这里的一行代码对应五行字节码
ExceptionTable
上面表格的第一个异常处理,当在0~25行代码执行时出现异常的时候,跳到37行去执行处理异常语句,由于为catch{}为空,所以直接执行finally语句。
每个异常处理的字节码后面都会跟着finally语句块,有多少catch,就会复制多少finally执行的字节码
行号表,linenumbertable
存储字节码和代码之间的对应关系
局部变量表,localvariabletable
这里只列出了3个,因为ex变量只有运行的时候才会知道是哪个exception
异常处理的第二种方式,使用throw来抛出异常
发现多了一个Exceptions属性
下面来讲栈帧,每个线程会有自己的栈帧,所以不需要考虑并发的情况
方法调用的五条指令
invokestatic方法
invokestatic、invokespecial
一个例子
一个例子,方法重写
在字节码里其实apple.test()调用的是fruit.test()
invokevirtual多态查找流程
1.找到操作数栈顶的第一个元素,查看它所引用的实际类型
2.在实际类型中查找是否有test()方法,且拥有访问权限
3.如果找到就将com/shengsiyuan/jvm/bytecode/Fruit.test的符号引用转换为对apple.test()的直接引用,即引用Apple类里的test方法。
4,.如果没有找到就沿着父类去找。最后实在没找到,抛出异常
可以看到即使是相同的符号引用如Fruit.test,在运行期也可以转换成不同的直接引用
下个例子
虚方法表中的每一项存储的是方法调用的入口地址
如果子类重写了父类的方法,在虚拟方法表中的索引号是与父类相同的
如果子类没有重写父类的某个方法,那么在方法表中会直接指向父类的这个方法的入口地址
编译执行和解释执行
结合例子进行讲解
stack=2,表示栈的深度为2,栈最多能够容纳两个元素,locals=6,表示最多有6个局部变量,args_size=1,表示参数的数量是1,即this
iconst_1即把数字1推送至操作数栈当中
动态代理
字节码总结