美文网首页java road
JVM-Java对象模型-学习笔记

JVM-Java对象模型-学习笔记

作者: HardWJJ | 来源:发表于2018-06-08 13:51 被阅读34次

    在内存中,一个Java对象包含三部分:对象头、实例数据和对齐填充。

    • oop-klass model

      • oop体系
      • klass体系
    • oop体系(存储实例数据)

      //定义了oops共同基类
      typedef class   oopDesc*                            oop;
      //表示一个Java类型实例
      typedef class   instanceOopDesc*            instanceOop;
      //表示一个Java方法
      typedef class   methodOopDesc*                    methodOop;
      //表示一个Java方法中的不变信息
      typedef class   constMethodOopDesc*            constMethodOop;
      //记录性能信息的数据结构
      typedef class   methodDataOopDesc*            methodDataOop;
      //定义了数组OOPS的抽象基类
      typedef class   arrayOopDesc*                    arrayOop;
      //表示持有一个OOPS数组
      typedef class   objArrayOopDesc*            objArrayOop;
      //表示容纳基本类型的数组
      typedef class   typeArrayOopDesc*            typeArrayOop;
      //表示在Class文件中描述的常量池
      typedef class   constantPoolOopDesc*            constantPoolOop;
      //常量池告诉缓存
      typedef class   constantPoolCacheOopDesc*   constantPoolCacheOop;
      //描述一个与Java类对等的C++类
      typedef class   klassOopDesc*                    klassOop;
      //表示对象头
      typedef class   markOopDesc*                    markOop;
      
    • 上图中每一个子模块对应一个类型,每一个类型的OOP都代表一个在JVM内部使用的特定对象的类型,变量opp的类型是oppDesc,它是OOPS类的共同基类型。
    • 在Java程序运行过程中,每创建一个新的对象,在JVM内部就会相应地创建一个对应类型的OOP对象。在HotSpot中,根据JVM内部使用的对象业务类型,具有多种oopDesc的子类。如下图,图中instanceOopDesc表示类实例,arrayOopDesc表示数组。


      OOP结构.png
    • HotSpot虚拟机中,对象在内存中存储的布局可以分为三块区域:对象头、实例数据和对齐填充。在虚拟机内部,一个Java对象对应一个instanceOopDesc的对象。其中对象头包含了两部分内容:_mark和_metadata,而实例数据则保存在oopDesc中定义的各种field中。
    • 在HotSpot的源码中我们可以找到关于对象头对象的定义,主要包含了GC分代年龄、锁状态标记、哈希码、epoch等信息。
    enum { age_bits                 = 4,
        lock_bits                = 2,
        biased_lock_bits         = 1,
        max_hash_bits            = BitsPerWord - age_bits - lock_bits - biased_lock_bits,
        hash_bits                = max_hash_bits > 31 ? 31 : max_hash_bits,
        cms_bits                 = LP64_ONLY(1) NOT_LP64(0),
        epoch_bits               = 2
    };
    
    • _mark(mark word)

      • 锁标记、GC分代等信息
      • 下图描述了在32位虚拟机上,在对象不同状态时 mark word各个比特位区间的含义。


        ObjectHead-1024x329.png
      • 有关于对象状态的定义:
        enum { locked_value             = 0,
           unlocked_value           = 1,
           monitor_value            = 2,
           marked_value             = 3,
           biased_lock_pattern      = 5
        };
        
      • 对象状态的定义中包含与锁标记位的关系

        locked_value(00) = 0
        unlocked_value(01) = 1
        monitor_value(10) = 2
        marked_value(11) = 3
        biased_lock_pattern(101) = 5

    • _metadata

      • 指向的是对象所属的类的instanceKlass
    • klass体系(实现虚函数多态)

      //klassOop的一部分,用来描述语言层的类型
      class  Klass;
      //在虚拟机层面描述一个Java类
      class   instanceKlass;
      //专有instantKlass,表示java.lang.Class的Klass
      class     instanceMirrorKlass;
      //专有instantKlass,表示java.lang.ref.Reference的子类的Klass
      class     instanceRefKlass;
      //表示methodOop的Klass
      class   methodKlass;
      //表示constMethodOop的Klass
      class   constMethodKlass;
      //表示methodDataOop的Klass
      class   methodDataKlass;
      //最为klass链的端点,klassKlass的Klass就是它自身
      class   klassKlass;
      //表示instanceKlass的Klass
      class     instanceKlassKlass;
      //表示arrayKlass的Klass
      class     arrayKlassKlass;
      //表示objArrayKlass的Klass
      class       objArrayKlassKlass;
      //表示typeArrayKlass的Klass
      class       typeArrayKlassKlass;
      //表示array类型的抽象基类
      class   arrayKlass;
      //表示objArrayOop的Klass
      class     objArrayKlass;
      //表示typeArrayOop的Klass
      class     typeArrayKlass;
      //表示constantPoolOop的Klass
      class   constantPoolKlass;
      //表示constantPoolCacheOop的Klass
      class   constantPoolCacheKlass;
      
    • 和oopDesc是其他oop类型的父类一样,Klass类是其他klass类型的父类。


      klass.png
    • Klass向JVM提供两个功能:

      • 实现语言层面的Java类
      • 实现Java对象的分发功能
    • instanceKlass

      JVM在运行时,需要一种用来标识Java内部类型的机制。HotSpot为每一个已加载的Java类创建一个instanceKlass对象,用来在JVM层表示Java类。

      • instanceKlass的内部结构:
           //类拥有的方法列表
           objArrayOop     _methods;
           //描述方法顺序
           typeArrayOop    _method_ordering;
           //实现的接口
           objArrayOop     _local_interfaces;
           //继承的接口
           objArrayOop     _transitive_interfaces;
           //域
           typeArrayOop    _fields;
           //常量
           constantPoolOop _constants;
           //类加载器
           oop             _class_loader;
           //protected域
           oop             _protection_domain;
           ....
      
    • 在JVM中,对象在内存中的基本存在形式就是oop。对象所属的类,在JVM中也是一种对象,因此它们实际上也会被组织成一种oop,即klassOop。同样的,对于klassOop,也有对应的一个klass来描述,它就是klassKlass,也是klass的一个子类。klassKlass作为oop的klass链的端点。关于对象和数组的klass链大致如下图:


      400_ac3_932.png
    • 在这种设计下,JVM对内存的分配和回收,都可以采用统一的方式来管理。oop-klass-klassKlass关系如图:


      2579123-5b117a7c06e83d84.png
    • 内存存储

      对象的实例(instantOopDesc)保存在堆上,对象的元数据(instantKlass)保存在方法区,对象的引用保存在栈上。

      • 示例代码
        class Model
      {
        public static int a = 1;
        public int b;
        public Model(int b) {
            this.b = b;
        }
      }
      public static void main(String[] args) {
        int c = 10;
        Model modelA = new Model(2);
        Model modelB = new Model(3);
      }
      
      • 对应的存储结构


        20170615230126453.jpeg
    • 总结

      Java类在被JVM加载的时候,JVM会给类创建一个instanceKlass,保存在方法区,用来在JVM层表示该Java类。使用new创建一个对象的时候,JVM会创建一个instanceOopDesc对象,这个对象中包含了两部分信息,对象头以及实例数据。对象头中有一些运行时数据,其中就包括和多线程相关的锁的信息。对象头中的_metadata中的_klass是普通指针,_compressed_klass是压缩类指针,它们同时指向的是对象所属的类的instanceKlass。

    • 参考资料

    相关文章

      网友评论

        本文标题:JVM-Java对象模型-学习笔记

        本文链接:https://www.haomeiwen.com/subject/zuxssftx.html