JVM摘要--指令集介绍03

[color=brown] 【题外话】只要学过编译原理,计算机组成类似的课程的,就不会觉得JVM的字节码太难理解。有兴趣的人,只要边看书,边写几个例子后,再javap一下慢慢看几个就大概心里有数了,其实学习JVM的东西,主要是为了让自己对它的运行方式多一些了解,在实际编程过程中心里有个概念,有些特性的底层实现心里有数就行。

毕竟在大多数编程中,JVM的知识不会直接的影响到你的编程思路,但会潜移默化的让你绕过一些潜在的风险或者障碍。[/color]

下面稍微介绍两个概念:[b]接收参数[/b] 和 [b]方法调用[/b]


[b][size=large]接收参数[/size][/b]
实例方法(非静态方法)和类方法(静态方法)的实现是略有不同的,因为当调用一个实例方法时,首先会将该类的自身的实例的引用作为第0个参数放置在局部变量表中,然后才在局部变量表的第1到N的位置上放置参数(如果有参数, N是参数个数)。

而静态方法不需要传递自身实例的应用,所以参数是从第0个开始存放。

(要注意long和double所占局部变量的大小为2)

大家可以用下面这两个例子做下测试
//example_1
int addTwo(int i, int j) { 
return i + j;
}



//example_2, static method
static  int addTwo(int i, int j)
{
return i + j;
}



[b][size=large]方法调用[/size][/b]

对普通实例方法(即非静态方法)调用是在运行时根据对象类型进行分派的(相当于在C++中所说的“虚方法”), 这类方法通过调用invokevirtual指令实现。

下面看一个简单的例子,然后是其字节码:
public class JVM_3_addTwo {
int addTwo(int i, int j)
{
return i + j;
}

int add12And13(){
return addTwo(12, 13);
}
}



  
...
int addTwo(int, int);
Code:
0: iload_1
1: iload_2
2: iadd
3: ireturn

int add12And13();
Code:
0: aload_0
1: bipush 12
3: bipush 13
5: invokevirtual #2; //Method addTwo:(II)I
8: ireturn

}


其具体流程如下(图只是用来参考,并不一定完全正确...)

[b]STEP1:[/b]
从局部变量表load当前类实例的指针,将其push到操作数栈
[img]http://glutinit.iteye.com/upload/picture/pic/102548/0fc7515c-86a6-390b-b92b-ed04fe591f44.jpg[/img]
[b]
STEP2:[/b]
将常量12和13分别push到操作数栈
[img]http://glutinit.iteye.com/upload/picture/pic/102558/a4938cdf-e39c-3a6e-a2f9-fd203ed08e37.jpg[/img]

[b]STEP3:[/b]
调用addTwo方法,在调用该方法时,JVM创建一个新的frame,并将自己实例的指针,以及参数12和13传给新的Frame中的局部变量表。


注:每条invokevirtual指令都会带有一个表示索引的参数,如图中的#2, 通过该标识,JVM可以通过查找常量池找到方法addTwo的符号引用,该符号引用可以提供方法所在对象的类型的内部二进制名称、方法名称和方法描述符

[img]http://glutinit.iteye.com/upload/picture/pic/102566/c106b400-120c-33ea-b4fa-00f396402f10.jpg[/img]


[b]STEP4:[/b]
目前的操作都针对Frame_addTwo中的操作数栈,如图,从局部变量表加载位置的变量和位置2的变量,即12和13

[img]http://glutinit.iteye.com/upload/picture/pic/102562/8414e6dd-c3fb-38c5-9882-99dfcda29399.jpg[/img]


[b]STEP5:[/b]
求和运算,将结果25压入到操作数栈中

[img]http://glutinit.iteye.com/upload/picture/pic/102552/83b0144a-c551-3fb0-abb5-183a52756e3e.jpg[/img]


[b]STEP6:[/b]
addTwo()方法返回,将其栈顶的值(即25)push到其调用者(即add12And13)方法所在的操作数栈,并且在该调用完成后,addTwo所拥有的frame就被删除掉。


[img]http://glutinit.iteye.com/upload/picture/pic/102550/e522a2db-5989-39d7-a4b7-730c5251fb14.jpg[/img]


[b]STEP7:[/b]
add12And13()方法返回,将其栈顶的值(即25)push到其调用者所在的操作数栈,并且在该调用完成后,add12And13所拥有的frame就被删除掉。

[img]http://glutinit.iteye.com/upload/picture/pic/102560/95325818-a5c5-3a7b-ab5c-2bf4b3fbde09.jpg[/img]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值