千家信息网

java对象的内存布局分为哪几个区域

发表于:2024-11-27 作者:千家信息网编辑
千家信息网最后更新 2024年11月27日,本篇内容介绍了"java对象的内存布局分为哪几个区域"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!H
千家信息网最后更新 2024年11月27日java对象的内存布局分为哪几个区域

本篇内容介绍了"java对象的内存布局分为哪几个区域"的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!

HotSpot虚拟机中,对象在内存中的布局分为三块区域:对象头、实例数据和对齐填充。

1)对象头:包括标记字段和类型指针两部分内容(注:如果是数组对象,则包含三部分内容):

1)Mark Word(标记字段):用于存储运行时对象自身的数据。        1>占用内存大小与虚拟机位长一致,在运行期间,考虑到JVM的空间效率,Mark Word被设计成为一个非固定的数据结构,以便存储更多有效的数据。        2>存储运行时对象自身的数据:                        哈希码(hash)                GC分代年龄(age)                锁标识位:                        01      无锁                        01      偏向锁                        00      轻量级锁                        10      重量级锁                偏向锁标识位(biased_lock)                        0       无锁                        1       偏向锁                偏向线程ID(JavaThread*)                偏向时间戳(epoch)                                说明:锁标识位、偏向锁标识位、偏向线程ID等的具体实现均是在monitor对象中完成的。(源码中的ObjectMonitor对象)                3>Mark Word里存储的数据会随着锁标志位的变化而变化,即不同的锁状态,存储着不同的数据:                        锁状态             存储内容                                                    锁标识位            偏向锁标识位(是否是偏向锁)                          --------        ------------------------------          --------                --------                无锁状态    哈希码、GC分代年龄                                      01                              0                偏向锁             线程ID、偏向时间戳、GC分代年龄               01                              1                轻量级锁    指向栈中锁记录的指针                            00                              无                重量级锁    指向monitor的指针                                    10                              无                GC标记            无                                                               11                              无2)Class Metadata Address(类型指针):指向对象的类元数据(方法区的Class数据),虚拟机通过这个指针确定该对象是哪个类的实例。3)如果对象是数组类型,则对象头中还存储着数组的长度。

2)实例数据:存放类的属性数据信息,包括父类的属性信息。

3)对齐填充:由于虚拟机要求对象起始地址必须是8字节的整数倍,填充数据不是必须存在的,仅仅是为了字节对齐。

4)使用JOL(Java Object Layout)工具查看java对象的内存布局:

maven依赖:                    org.openjdk.jol            jol-core            0.14        代码:        public class TestClassLayout {            public static void main(String[] args) {                TestClass[] testClassObj = new TestClass[5];                // 查看对象内存布局                System.out.println(ClassLayout.parseInstance(testClassObj).toPrintable());            }        }       结果:        1       [Lcom.jxn.test.TestClass; object internals:        2        OFFSET  SIZE                     TYPE DESCRIPTION                               VALUE        3             0     4                          (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)        4             4     4                          (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)        5             8     4                          (object header)                           82 c1 00 f8 (10000010 11000001 00000000 11111000) (-134168190)        6            12     4                          (object header)                           05 00 00 00 (00000101 00000000 00000000 00000000) (5)        7            16    20   com.jxn.test.TestClass TestClass;.                     N/A        8            36     4                          (loss due to the next object alignment)        9       Instance size: 40 bytes        10      Space losses: 0 bytes internal + 4 bytes external = 4 bytes total        对象头:                第3行+第4行:        Mark Word(标记字段)                第5行:            类型指针                第6行:            数组长度        实例数据:                第7行:            数组中存储了5个TestClass对象的引用(开启指针压缩后,类型引用占4个字节),故占用5*4=20个字节。        对齐填充:                第8行:            对象头+实例数据 占用的内存为36字节(不是8的整数倍),故需要4字节的对齐填充。        对象占用的总空间:                第9行        内存浪费的总空间:                第10行:           对齐填充消耗了4个字节。                说明:若数组的长度改为6,则 对象头+实例数据 占用的内存为40字节(8的整数倍),故不会出现对齐填充:                [Lcom.jxn.test.TestClass; object internals:                 OFFSET  SIZE                     TYPE DESCRIPTION                               VALUE                      0     4                          (object header)                           01 00 00 00 (00000001 00000000 00000000 00000000) (1)                      4     4                          (object header)                           00 00 00 00 (00000000 00000000 00000000 00000000) (0)                      8     4                          (object header)                           82 c1 00 f8 (10000010 11000001 00000000 11111000) (-134168190)                     12     4                          (object header)                           06 00 00 00 (00000110 00000000 00000000 00000000) (6)                     16    24   com.jxn.test.TestClass TestClass;.                     N/A                Instance size: 40 bytes                Space losses: 0 bytes internal + 0 bytes external = 0 bytes total

5)hotspot/src/share/vm/oops/markOop.hpp 源码中的说明:

// The markOop describes the header of an object.//// Note that the mark is not a real oop but just a word.// It is placed in the oop hierarchy for historical reasons.//// Bit-format of an object header (most significant first, big endian layout below):////  32 bits://  --------//             hash:25 ------------>| age:4    biased_lock:1 lock:2 (normal object)//             JavaThread*:23 epoch:2 age:4    biased_lock:1 lock:2 (biased object)//             size:32 ------------------------------------------>| (CMS free block)//             PromotedObject*:29 ---------->| promo_bits:3 ----->| (CMS promoted object)////  64 bits://  --------//  unused:25 hash:31 -->| unused:1   age:4    biased_lock:1 lock:2 (normal object)//  JavaThread*:54 epoch:2 unused:1   age:4    biased_lock:1 lock:2 (biased object)//  PromotedObject*:61 --------------------->| promo_bits:3 ----->| (CMS promoted object)//  size:64 ----------------------------------------------------->| (CMS free block)////  unused:25 hash:31 -->| cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && normal object)//  JavaThread*:54 epoch:2 cms_free:1 age:4    biased_lock:1 lock:2 (COOPs && biased object)//  narrowOop:32 unused:24 cms_free:1 unused:4 promo_bits:3 ----->| (COOPs && CMS promoted object)//  unused:21 size:35 -->| cms_free:1 unused:7 ------------------>| (COOPs && CMS free block)////  - hash contains the identity hash value: largest value is//    31 bits, see os::random().  Also, 64-bit vm's require//    a hash value no bigger than 32 bits because they will not//    properly generate a mask larger than that: see library_call.cpp//    and c1_CodePatterns_sparc.cpp.////  - the biased lock pattern is used to bias a lock toward a given//    thread. When this pattern is set in the low three bits, the lock//    is either biased toward a given thread or "anonymously" biased,//    indicating that it is possible for it to be biased. When the//    lock is biased toward a given thread, locking and unlocking can//    be performed by that thread without using atomic operations.//    When a lock's bias is revoked, it reverts back to the normal//    locking scheme described below.////    Note that we are overloading the meaning of the "unlocked" state//    of the header. Because we steal a bit from the age we can//    guarantee that the bias pattern will never be seen for a truly//    unlocked object.////    Note also that the biased state contains the age bits normally//    contained in the object header. Large increases in scavenge//    times were seen when these bits were absent and an arbitrary age//    assigned to all biased objects, because they tended to consume a//    significant fraction of the eden semispaces and were not//    promoted promptly, causing an increase in the amount of copying//    performed. The runtime system aligns all JavaThread* pointers to//    a very large value (currently 128 bytes (32bVM) or 256 bytes (64bVM))//    to make room for the age bits & the epoch bits (used in support of//    biased locking), and for the CMS "freeness" bit in the 64bVM (+COOPs).////    [JavaThread* | epoch | age | 1 | 01]       lock is biased toward given thread//    [0           | epoch | age | 1 | 01]       lock is anonymously biased////  - the two lock bits are used to describe three states: locked/unlocked and monitor.////    [ptr             | 00]  locked             ptr points to real header on stack//    [header      | 0 | 01]  unlocked           regular object header//    [ptr             | 10]  monitor            inflated lock (header is wapped out)//    [ptr             | 11]  marked             used by markSweep to mark an object not valid at any other time////    We assume that stack/thread pointers have the lowest two bits cleared.

"java对象的内存布局分为哪几个区域"的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识可以关注网站,小编将为大家输出更多高质量的实用文章!

0