深入探讨虚拟机运行时的java线程栈帧、Java/JVM沟通(2)
2023-04-29 来源:飞速影视
vframe的Callee-saved寄存器保存了调用者的栈底指针(RBP/EBP),也正是因为它保存了该指针,才能放心地通过当前vframe获取前一个vframe,如此继续,直至迭代完所有栈帧。即便如此,vframe仍显得细节过多,所以虚拟机会在vframe上抽象出javaVFrame用于表示Java栈帧。javaVFrame栈帧还可以细分为解释器栈帧(interpretedVFrame)和编译代码栈帧(compiledVFrame)。这些新的栈帧几乎没有增加数据结构,只是相比frame而言更方便。
后面在第10章会讲到,垃圾回收器从GC Root出发寻找存活对象。
很多地方都属于GC Root,其中之一便是线程栈。垃圾回收器遍历线程上的每个frame(所有frame构成一个线程栈),然后调用frame::oops_do()寻找frame中的所有对象引用,并以它们为起始进行对象标记,如代码清单4-16所示:
代码清单4-16 frame::oops_do
void frmae::oops_do(...) { oops_do_internal(...); }void frame::oops_do_internal(...) {if (is_interpreted_frame()) { // 解释器栈帧oops_interpreted_do(f, map, use_interpreter_oop_map_cache);} else if (is_entry_frame()) { // call_stub调用起始栈帧oops_entry_do(f, map);} else if (CodeCache::contains(pc())) { // 编译后代码栈帧oops_code_blob_do(f, cf, map);} else {ShouldNotReachHere();}}不同类型的栈帧存放引用的位置不同,如解释器栈中monitor区域存在引用、参数区域存在引用、编译后的代码中OopMapSet和参数区存在引用,所以frame::do_oops()需要区分它们并找到所有引用。
Java/JVM沟通
Java代码没有能力创造线程,它必须通过JNI的形式请求虚拟机来创造,而某些情况下JVM也需要调用Java方法,两者需要一种方式来沟通,这种方式便是JNI和JavaCalls,它们是JVM和Java沟通的桥梁,如图4-6所示。
本站仅为学习交流之用,所有视频和图片均来自互联网收集而来,版权归原创者所有,本网站只提供web页面服务,并不提供资源存储,也不参与录制、上传
若本站收录的节目无意侵犯了贵司版权,请发邮件(我们会在3个工作日内删除侵权内容,谢谢。)
www.fs94.org-飞速影视 粤ICP备74369512号