## jvm堆

jvm堆

堆的概述

  • 一个jvm只有一个堆内存,是线程共享的
  • 堆的大小是可以调节的,堆可以处于物理上不连续的内存空间中,但是在逻辑上应该认为是连续的
  • 堆还可以划分线程私有的缓冲区TLAB(Thread local allocation buffer)
  • 几乎所有的对象实例和数组在运行时都分配在堆上(逃逸分析)
  • 在方法结束后,堆中的对象不会立马被移除,仅仅在GC的时候才会被回收
  • 堆是GC执行垃圾回收的重点地区

堆的内存划分

  • jdk1.7之前,逻辑上堆划分为年轻代+老年代+永久代。永久代就是方法区的具体的实现
  • jdk1.8开始,逻辑上划分为年轻代+老年代+元空间,元空间是方法区的具体实现
  • 年轻代和老年代的默认比是1:2,年轻代分为伊甸园区,幸存者0区,幸存者1区,默认比是8:1:1

对象分配过程

  1. new的对象放置在伊甸园区,该区是有大小限制
  2. 当eden的空间填满时,程序又需要存放对象,这时候jvm的垃圾回收期将对eden进行垃圾回收(minor gc),将不被引用的对象销毁,加载新的对象
  3. 然后将伊甸园区的剩余对象加载到幸存者区
  4. 如果再次出发垃圾回收,上次幸存者0区没有销毁的对象,会随着eden存活的对象放入幸存者1区,
  5. 如果再次触发垃圾回收,这是重新放回幸存者0区,然后再幸存者1区
  6. 当转移次数达到默认阈值15次时,数据就会被放入老年代。
  7. 当养老区内存不足的时候,再触发major gc 进行垃圾回收,
  8. 若养老区gc完之后依然无法进行内存的保存,则爆oom异常
  9. 特殊的:如果数据很大,可能直接放入老年区。如果在minor gc之后,幸存者区放不下也会放入老年区,
  10. 动态对象年龄判断:如果幸存者区中相同年龄的所有对象大小的总和,大于幸存者区的一半,则年龄大于或者等于该年龄的对象可以直接放入老年代。

逃逸分析和标量替换

  • 逃逸分析: 如果一个对象只在方法中使用,则没有逃逸,如果在其他方法中有引用,则发生了逃逸
  • 栈上分配:如果经过逃逸分析之后,发现对象并没有逃逸出方法,则可能优化成栈上分配,这样就无需放入堆中,则无需进行gc.
  • 同步省略:分析锁对象是否只能被一个线程所使用,如果没有逃逸,则可以吧同步操作去掉
  • 标量替换: java的基本数据类型就是标量,如果经过逃逸分析,发现一个对象没有逃逸,就可以吧这个对象拆解成若干个其中包含的若干个成员变量来代替,这个过程就是标量替换。
  • 虽然有逃逸分析,但是hotspot并没有启用,因为逃逸分析的代价有时比栈上分配更多,所以栈上分配是没有的,标量替换是有的。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值