返回信息流以下为《深入理解Java虚拟机》的描述
1. 每一个栈帧都包括了局部变量表、操作数栈、动态链接、方法返回地址和一些额外的附加信息...
2. 每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接...
3. class文件的常量池中存有大量的符号引用,字节码中的方法调用指令以常量池中指向方法的符号引用作为参数,这些符号引用一部分会在类加载阶段或者第一次使用的时候就转化为直接引用,另外一部分将在每一次运行期间转化为直接引用
有没有大虾解释一下这个"指向运行时常量池中该栈帧所属方法的引用"在动态链接过程中如何起作用的呢?
这是一条镜像帖。来源:北邮人论坛 / java / #53682同步于 2016/11/3
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖
Java 栈帧
liuyehcf
2016/11/3镜像同步4 回复
订阅后,新回复会通过你的通知中心匿名送达。
4 条回复
我不觉得这个引用有什么作用。实际的实现中,这个引用或许根本不存在。
如果这个JVM是用解释器实现的,或许这个指针可以用来找到下一个字节码的地址;如果是JIT编译的,那么当前PC地址就足以确定是哪个方法。
http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.6.3
JVM spec确实提到了这个东西的存在。但是具体实现中,这个东西即使不存在,也没人能发现,就像一个用编译器实现的JVM可以用PC反查出那个方法的描述数据,还能让调试器知道当前在执行哪个方法,别人根本看不出来这个实现在“作弊”。
【 在 liuyehcf 的大作中提到: 】
: 以下为《深入理解Java虚拟机》的描述
: 1. 每一个栈帧都包括了局部变量表、操作数栈、动态链接、方法返回地址和一些额外的附加信息...
: 2. 每个栈帧都包含一个指向运行时常量池中该栈帧所属方法的引用,持有这个引用是为了支持方法调用过程中的动态链接...
: ...................
谢暖神~
根据你的解释,如果这个引用起作用的话,是不是以下这样一个过程:
1、在"方法区"当前执行某个字节码,需要操作"操作数栈"
2、转到"Java 虚拟机栈"区域的该方法的栈帧操作"操作数栈"
3、操作完毕后,通过这个引用返回到下一条字节码指令的地址?
【 在 nuanyangyang 的大作中提到: 】
: 我不觉得这个引用有什么作用。实际的实现中,这个引用或许根本不存在。
: 如果这个JVM是用解释器实现的,或许这个指针可以用来找到下一个字节码的地址;如果是JIT编译的,那么当前PC地址就足以确定是哪个方法。
: http://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.6.3
: ...................
【 在 liuyehcf 的大作中提到: 】
: 谢暖神~
: 根据你的解释,如果这个引用起作用的话,是不是以下这样一个过程:
: 1、在"方法区"当前执行某个字节码,需要操作"操作数栈"
: 2、转到"Java 虚拟机栈"区域的该方法的栈帧操作"操作数栈"
: 3、操作完毕后,通过这个引用返回到下一条字节码指令的地址?
不知道。这几句话和执行的关系很模糊,也说不清楚哪句话是对的。
现实中的JVM实现可能跟你想象的完全不一样。
现实中,JVM要执行一个方法的时候,可以把这个方法直接编译成机器码,然后之后完全和这些数据结构没有关系了。
就算JVM是用解释器实现的,具体的解释过程用不用这些引用,也都不一定。甚至到底有没有“操作数栈”,还是JVM内部把基于栈的字节码转换成基于寄存器的程序了,都说不定。
所以,建议,不要太在意“JVM执行程序到底是一个什么过程”。
JVM specification确实提到这些引用,比如frame里有一个“局部变量数组”、一个“操作数栈“、一个指向“当前方法的类的常量池”的引用。这些都是用于描述JVM的语义用的。JVM spec的其它部分会利用这些数据结构来描述各个指令的语义的,比如iadd指令的语义是“从‘操作数栈’上弹出两个操作数,相加,再把结果压回‘操作数栈’”,ireturn指令的语义是“将一个操作数从‘操作数栈’中弹出来,然后返回它”。用这种描述方法,一个程序会有什么样的行为,比如“会打印什么数字”,“某个函数会返回什么值”,都能很清楚地描述出来。
但是JVM并不一定按照”语义“描述的那样实现。就像我刚才说的,用编译器来实现JVM也是合法的,因为JVM的用户从外部根本看不见JVM里到底有没有”操作数栈“。就算.class文件的字节码里真的有个iadd指令,用户也不知道它到底是从”操作数栈“里弹出的操作数,还是直接从机器寄存器,或者机器的栈内存里,或者是机器指令的立即数里获取的操作数。有一句话是真理:只要你不不被发现,怎么作弊都可以(You can cheat as long as you don't get caught.)这就是编程语言实现(尤其是优化)的黄金准则。
另外,《深入理解Java虚拟机》这本书还是很有节操的,但是它有时候会过度地涉及官方的HotSpot虚拟机的细节。HotSpot是一个JVM,但并不是唯一的JVM。了解它并没有错,如果是HotSpot的常规用户,知道如何调整它的细节(比如垃圾回收的堆大小什么的)是有帮助的,但这些细节并不是“JVM”的东西,而是“这个具体的JVM”的东西。换一个JVM,就都变了。
大概明白了一些,谢谢暖神了~,好感动!
【 在 nuanyangyang 的大作中提到: 】
:
: 不知道。这几句话和执行的关系很模糊,也说不清楚哪句话是对的。
: 现实中的JVM实现可能跟你想象的完全不一样。
: ...................