锁定老帖子 主题:java栈帧中的对象引用
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-09-12
openjdk中的java栈帧是如何布置的呢,在java栈中如果确定变量是一个引用呢,先复习《深入java虚拟机第二版》有关栈帧的内容。 “栈帧由三部分组成:局部变量区、操作数栈和栈数据区。局部变量区和操作数栈要视对应的方法而定,他们是按字长计算的。编译器在编译时就确定了这些值并放在class文件中,而栈数据区的大小依赖于具体实现。 当虚拟机调用一个java方法时,它从对应的类的类型信息得到局部变量区和操作数栈的大小,并据此分配栈帧内存,并压入java栈中。 局部变量区 java栈帧的局部变量区被组织成一个以字长为单位、从0开始计数的数组。字节码指令通过以0开始的索引来使用其中的数据。类型为int、float、refence和returnAdress的值在数组内只占据一项。而类型为byte、short、char的值在存入数组时都先转换为int值,因此同样只占据一项。而类型为long和double的值在数组中却占据了连续两项。 局部变量区包含了对应的方法参数和局部变量。” 现在的问题是在垃圾回收算法遍历java线程堆栈时候,它是如何确定局部变量是基本类型还是对象引用呢? openjdk对局部变量区解释有两种方法,通过TaggedStackInterpreter这个设置来区分。从英文意思上面来看应该是一个通过在栈中打上标志,另外一个则是在其他地方做标志。在栈上打标志,则应该是每个变量多压入一个标志头(为一个字长),猜测是否正确呢,看看解释器将引用压栈的代码。 void BytecodeInterpreter::astore(intptr_t* tos, int stack_offset, local_index_at代码 { stackElementWords() 代码 { return TaggedStackInterpreter ? 2 : 1; //如果是在栈打标志,字长为2,否则是1,在这可以肯定每个变量前都会多压入一个字长的标志头,虚拟机会通过这个标志头来确定是否是对象引用 } 上面分析对象在栈中打标志来区分基本类型和引用类型,这种方法每个变量起码多了一个字的内存空间,空间浪费严重。如果能用位图表示岂不更好?再看另外一种方案。 从上面的压栈代码看不到另外的操作,openjdk是如何做的呢,还是从上篇gc代码中看看。 void frame::oops_interpreted_do(OopClosure* f, const RegisterMap* map, bool query_oop_map_cache) { ........ jint bci = interpreter_frame_bci(); methodHandle m (thread, interpreter_frame_method()); InterpreterFrameClosure blk(this, max_locals, m->max_stack(), f); InterpreterOopMap mask; } void InterpreterOopMap::iterate_oop(OffsetClosure* oop_closure) { void InterpreterFrameClosure::offset_do(int offset) { oop* addr; 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |
发表时间:2008-09-14
这么好的文章,居然没有人留言
|
|
返回顶楼 | |
浏览 2352 次