`
xieyj
  • 浏览: 99924 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

java栈帧中的对象引用

阅读更多

        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,
                          intptr_t* locals, int locals_offset) {
                 if (TaggedStackInterpreter) {
                          frame::Tag t = (frame::Tag) tos[Interpreter::expr_tag_index_at(-stack_offset)];
                          locals[Interpreter::local_tag_index_at(-locals_offset)] = (intptr_t)t;
                 }
                 intptr_t value = tos[Interpreter::expr_index_at(-stack_offset)];
                 locals[Interpreter::local_index_at(-locals_offset)] = value;
       }

      local_index_at代码   

      {
                return stackElementWords() * i + (value_offset_in_bytes()/wordSize);
       }

       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;
                if (query_oop_map_cache) { //传入true
                     m->mask_for(bci, &mask);  //从oopMapCache中填充mask变量
                } else {
                     OopMapCache::compute_one_oop_map(m, bci, &mask);
                }
               mask.iterate_oop(&blk);

     }

     void InterpreterOopMap::iterate_oop(OffsetClosure* oop_closure) {
               int n = number_of_entries();
               int word_index = 0;
               uintptr_t value = 0;
               uintptr_t mask = 0;
               // 遍历每项
               for (int i = 0; i < n; i++, mask <<= bits_per_entry) {
                        if (mask == 0) {
                                value = bit_mask()[word_index++];
                                mask = 1;
                        }
                       // 判断是否是对象引用?
                       if ((value & (mask << oop_bit_number)) != 0) oop_closure->offset_do(i);
              }
      }

     void InterpreterFrameClosure::offset_do(int offset) {

              oop* addr;
              if (offset < _max_locals) {
                     addr = (oop*) _fr->interpreter_frame_local_at(offset);
                     assert((intptr_t*)addr >= _fr->sp(), "must be inside the frame");
                     _f->do_oop(addr);  //进行标记和压栈
              }
     }
     从上面来看,采用位图来区分对象引用基本上是肯定的,具体如何实现还有待于细读。

2
0
分享到:
评论
2 楼 Mr_lee_2012 2011-12-08  
是啊,好文章,谢过。
1 楼 mercyblitz 2008-09-14  
这么好的文章,居然没有人留言

相关推荐

    大厂真题之京东-Java实习生

    1)虚拟机栈(栈帧中的本地变量表)中引用的对象; 2)方法区中的类静态属性引用的对象,常量引用的对象; 3)本地方法栈中 JNI(Native 方法)引用的对象; 1.2 对象不可达,一定会被垃圾收集器回收么? 即使不可达...

    深入Java虚拟机(原书第2版).pdf【附光盘内容】

    2.3.7 java平台实现中的bug 2.3.8 测试 2.4 平台无关的七个步骤 2.5 平台无关性的策略 2.6 平台无关性和网络移动对象 2.7 资源页 第3章 安全 3.1 为什么需要安全性 3.2 基本沙箱 3.3 类装载器...

    深入Java虚拟机

    2.3.7 Java平台实现中的bug 2.3.8 测试 2.4 平台无关的七个步骤 2.5 平台无关性的策略 2.6 平台无关性和网络移动对象 2.7 资源页 第3章 安全 3.1 为什么需要安全性 3.2 基本沙箱 3.3 类装载器...

    Java常见面试问题整理.docx

    引入了一种基于通道(Channel)与缓冲区(Buffer)的I/O 方式,它可以使用native 函数库直接分配堆外内存,然后通过一个存储在Java堆中的DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著...

    深入java虚拟机第二版

    2.3.7 Java平台实现中的bug 2.3.8 测试 2.4 平台无关的七个步骤 2.5 平台无关性的策略 2.6 平台无关性和网络移动对象 2.7 资源页 第3章 安全 3.1 为什么需要安全性 3.2 基本沙箱 3.3 类装载器体系结构 ...

    深入JAVA虚拟机(第2版)

    2.3.7 Java平台实现中的bug 2.3.8 测试 2.4 平台无关的七个步骤 2.5 平台无关性的策略 2.6 平台无关性和网络移动对象 2.7 资源页 第3章 安全 3.1 为什么需要安全性 3.2 基本沙箱 3.3 类装载器...

    高级java开发并发问题

    虽然Java中万物皆对象,但是new Thread() 创建一个线程和 new Object()还是有区别的。 new Object()过程如下: 1.JVM分配一块内存 M 2.在内存 M 上初始化该对象 3.将内存 M 的地址赋值给引用变量 obj 创建线程的过程...

    深入理解_Java_虚拟机 JVM_高级特性与最佳实践

    / 342 13.1 概述 / 342 13.2 线程安全 / 343 13.2.1 Java语言中的线程安全 / 343 13.2.2 线程安全的实现方法 / 348 13.3 锁优化 / 356 13.3.1 自旋锁与自适应自旋 / 356 13.3.2 锁消除 / 357 13.3.3 锁粗化 ...

    【jvm】01- java内存结构分析

    java内存结构分析java内存结构java栈结构分析:栈帧局部变量表操作数栈动态连接返回地址运行时常量池对象的创建过程类加载的执行流程图对象创建的过程:对象内存分配方式指针碰撞空闲列表栈上分配:内存逃逸:对象...

    Java虚拟机

    原子性、可见性和有序性在Java内存模型中的体现;先行发生原则的规则和使用;线程在Java语言中的实现原理;虚拟机实现高效并发所做的一系列锁优化措施。 前言 第一部分 走近Java 第1章 走近Java 1.1 概述 1.2 ...

    Java 虚拟机面试题全面解析(干货)

    Java中对象访问是如何进行的? Object ob j new Object( 对于上述最简单的访问,也会涉及到Java栈、Java堆、方法区这三个最重要内存区域。 Object obj 如果出现在方法体中,则上述代码会反映到Java栈的本地变量表中,...

    CMS垃圾收集器1

    1. 虚拟机栈中的引用的对象(栈帧中的本地变量表) 2. 方法区中的类静态属性引用的对象 3. 方法区中的常量引用的对象 4. 本地方法栈中JNI的引用的对象

    Java值传递的代码讲解,包含基本类型,引用类型

    顾名思义,就是值的传递,基本类型,引用类型,在创建出来,就是存在于当前方法所在的栈帧,就是调用其他方法,传的是引用地址,不是真实对象(看代码的输出就懂了) 2.引用类型传引用? 这是坑,Java只有值传递,学...

    java8源码-jvm-study:jvm-study

    栈:栈帧(对象的引用,方法) 类加载 执行方法 创建对象 堆空间分代划分 outOfMemory异常 https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html 可以看jvm参数查看网址 Direct buffer memory : ...

    Android中的内存泄露

    可以作为GCROOT节点的对象虚拟机栈的栈帧的局部变量表引用的对象本地方法栈JNI引用的对象方法区的静态变量和常量所引用的对象引用计数法内存图1.step1:GcObject实例1的引用计数+1,目前为12.step2:Gc

    深入理解Java虚拟机视频教程(jvm性能调优+内存模型+虚拟机原理)视频教程

    第29节对象在内存中的布局-对象的创建00:21:19分钟 | 第30节探究对象的结构00:13:47分钟 | 第31节深入理解对象的访问定位00:08:01分钟 | 第32节垃圾回收-概述00:06:20分钟 | 第33节垃圾回收-判断对象是否存活...

    JVM面试题1

    1.遇到new指令 1.虚拟机栈(存储指针引用)、2.元空间方法区(存储类 1.虚拟机栈 (栈帧中的本地方法表) 中引用的对象 2.方法区中类静态属性引用的对象

    Java虚拟机规范(Java SE 7)

    2.8.1 Java虚拟机和IEEE 754中的浮点算法 .......................... 35 2.8.2 浮点模式 ................................................. 36 2.8.3 数值集合转换 ...............................................

    Java虚拟机规范(Java SE 7).pdf

    2.8.1 Java虚拟机和IEEE 754中的浮点算法 .......................... 35 2.8.2 浮点模式 ................................................. 36 2.8.3 数值集合转换 ...............................................

Global site tag (gtag.js) - Google Analytics