Java执行机制

前言

       这篇里的东西,其实是我在草稿箱里找到的.因为当时写的比较粗,而且这个题目的内容没有完结..所以一直没有发布.但是后续有篇文章 

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),其中程序计数器存放要执行的指令在方法内的偏移量,栈当中存放栈帧,每个方法每次调用都会产生栈帧.


注:该图来自 毕玄的书 <发布式Java应用基础和实践>
局部变量区用于存放方法中的局部变量和参数,操作数栈用于存放方法执行过程中的中间结果.
 可以这么理解,任何在方法体中特意定义过的局部变量,那么都会放到局部变量表(方法参数也会放这里).其他的中间结果.具体看下面的例子
public class Test
{
    public int add(int a,int b){
		int c = a + 1;
		return c * b;
	}
}
 看javap输出
首先要说明的是,按照之前的说法,方法参数会放到局部变量表中.所以局部变量表中的第一个值对应add方法的参数a,第二个值对应于参数b.

 

写道
public int add(int, int);
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

}

 补充说明一下,

写道
其实局部变量表是有第零个元素的.不过一般这个元素都是指向this.如果把方法改成static,就可以看到第一个方法参数(也就是a) 就是以iload_0来压栈了.

 

栈顶缓存

   从上面的例子看到,我们计算 c * b 的时候,需要从存放c的寄存器(也就是第三个局部变量表的元素)先压入操作数栈的栈顶,然后再计算相乘操作.而栈顶缓存的效果就是,取消压栈的这次操作,直接把寄存器的数据拿来做相乘操作,然后把结果压入栈.

 

 

 

                                     -----未完待续

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值