前言
这篇里的东西,其实是我在草稿箱里找到的.因为当时写的比较粗,而且这个题目的内容没有完结..所以一直没有发布.但是后续有篇文章
java中 obj=null对垃圾回收有用吗
要引用里面局部变量表的知识,所以就先把这个半吊子发布出来,后续慢慢补充.
类执行机制
jvm采用中间码来实现执行.其中,方法执行的指令有下面几个
(1)invokestatic 执行static方法
(2)invokevirtual 调用对象实例方法
(3)invokeinterface 调用接口方法
(4)invokespecial 调用private方法和Init方法
上面说的其实有点笼统,invokevirtual和invokespecial的知识可以看一下 Java方法分派 里面说的比较详细.
另外,jdk7以后新增了一条方法执行 invokedynamic 提供了一条对动态语言的支持.可惜在jdk7没有在java语言中支持该指令. 可以看一下 http://rednaxelafx.iteye.com/blog/477934
sun JDK基于栈的体系来执行字节码.线程在创建后,都会产生程序计数器(PC register)和栈(Stack),其中程序计数器存放要执行的指令在方法内的偏移量,栈当中存放栈帧,每个方法每次调用都会产生栈帧.

可以这么理解,任何在方法体中特意定义过的局部变量,那么都会放到局部变量表(方法参数也会放这里).其他的中间结果.具体看下面的例子
public class Test
{
public int add(int a,int b){
int c = a + 1;
return c * b;
}
}
看javap输出
Code:
Stack=2, Locals=4, Args_size=3
0: iload_1 //将局部变量表中第一个值压入操作数栈(这个值对应add方法中的参数a)
1: iconst_1 //将int 类型的 1 放入操作数栈.
2: iadd //执行add指令. 将操作数栈顶两个元素相加,然后把结果放到栈顶 (a + 1)
3: istore_3 //把栈顶元素放到局部变量表中的第三个位置.也就是c
4: iload_3 //把局部变量表第三个元素压入栈顶,也就是c
5: iload_2 //把局部变量表第二个元素压入栈顶,也就是b
6: imul //执行mul指令,将栈顶两个相乘,然后把结果放入栈顶,也就是 c * b
7: ireturn //把栈顶元素返回.
LineNumberTable:
line 8: 0
line 9: 4
}
补充说明一下,
栈顶缓存
从上面的例子看到,我们计算 c * b 的时候,需要从存放c的寄存器(也就是第三个局部变量表的元素)先压入操作数栈的栈顶,然后再计算相乘操作.而栈顶缓存的效果就是,取消压栈的这次操作,直接把寄存器的数据拿来做相乘操作,然后把结果压入栈.
-----未完待续