糖尿病康复,内容丰富有趣,生活中的好帮手!
糖尿病康复 > 《深入理解java虚拟机》读书笔记:Java对象的内存布局

《深入理解java虚拟机》读书笔记:Java对象的内存布局

时间:2019-04-02 12:59:56

相关推荐

《深入理解java虚拟机》读书笔记:Java对象的内存布局

一个int类型4占4个字节的内存,一个byte一个字节。但是他们的封装类型Integer,Byte对象内存损耗还是一样的吗?并不是,而且差距十分大。

HotSpot虚拟机中,一个普通的Java对象由3部分构成

对象头类内定义的实例数据内存对齐

2不必多说,Java对象不存定义好的实例字段存啥。

对象头又分两部分,Mark Word和类型指针。Mark Word存储对象运行时数据,如对象的hashcode,对象的分代年龄,锁状态等等。对象的分代年龄完全是为了JVM的Young GC设计的,每经历一次Young GC且存活下来的新生代对象,对象的分代年龄变会加一。直到这个字段增长到阈值,这个对象便会晋升到老年代(tenured generation)。这个字段给的是4个bit,也就是说一个java对象最多经历16次Young GC并且没被回收,那么它将进入老年代。hashcode占25bit,锁标志位占2bit,一个bit固定为0.也就是说整个Mark Word占4个字节。

每种对象实例在方法区都会与一个Class对象与之相对应。对象头的类型指针便是用来定位它的类的元数据。为何要存这个数据?原因之一便是,方法区也要GC(确切的说是Full GC),如果没有一个类实例指向方法区的Class对象,那么这个Class对象便会被卸载回收。不知道大家有没有经历过java.lang.OutOfMemoryError: PermGen space 这样的错误。如果类一直在加载,永久代必然会被打爆。32位的JDK,类类型指针占4个字节。

现在说说内存对齐。内存对齐可不是jvm的专利,C/C ++ 下,类对象也是会内存对齐的。HotSpot要求对象的起止地址必须是8的倍数,由于对象头正好8个字节,因此当类字段没对齐时,就需要通过填充来对齐。为何要对齐呢?数据不是占内存越小越好吗?这个时候就得提提我们的cpu高速缓存了(L1 cache, L2 cache),这些缓存都是64字节一行。

最后来回答开头的问题,Integer大小是int的4倍(用了额外的4Byte补齐),Byte是byte的16倍(用了额外的7Byte补齐)。你算出来了吗?

下面通过程序和Jprofiler来验证一下

package jvm;// 创建一个只有char字段的类public class CharWrapper {private char c = 'a';public static void main(String[] args) throws IOException {// 生成一个对象CharWrapper charWrapper = new CharWrapper();System.out.println(charWrapper);System.in.read();}}

运行程序,并用JProfiler查看堆的对象。一个对象占用了16字节的堆内存。验证完毕。

两年前看《effective java》,有一个章节提到尽量用8大原生类型,那个时候对java对象内存布局完全没概念。现在回想起来,这个suggesstion是很有建设意义的。能节约很多堆内存啊,尤其是在从DB读取大量字段的时候。

如果觉得《《深入理解java虚拟机》读书笔记:Java对象的内存布局》对你有帮助,请点赞、收藏,并留下你的观点哦!

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。