jvm内存详解:堆

先记住一句话:几乎所有的对象都在堆上分配。

堆内存结构大致如下图:年轻代(也叫新生代)、老年代,年轻代中又分为Eden区和survivor区,survivor区又细分为from和to。

年轻代和老年代默认比例是1:2,即如果我们设置堆大小为600M(-Xmx:600m -Xms:600m),那么年轻代占200M,老年代占400M。其中,年轻代的Eden和survivor占比默认是8:1:1,那么Eden就大致是160M,from和to各自为20M。

Young GC(minor GC):

在程序运行到一行代码如User user = new User()的时候,new User()产生的新对象大多数情况下是放在Eden区的。那么可以想象一下,在我们日常应用程序中,代码是不断产生对象的,最终会将Eden撑满,所以这个时候java虚拟机通过字节码执行引擎开启一个叫做garbage collect线程来进行young GC,进而回收掉无用的对象,如何判断对象是否无用?这就需要了解gc root以及可达性分析算法的相关概念。

可达性分析算法

通过一系列的“GC Root”的对象作为出发点,向下搜索引用的对象,找到的对象都为非垃圾对象。反之,当一个对象没有任何GC Root的引用链相关联时,则此对象是不可用的。

GC Root:

虚拟机栈所引用的对象

方法区静态属性所引用的对象

方法区常量所引用的对象

本地方法栈JNI(即一般所说的Native方法)所引用的对象

通过上述可达性算法甄别出垃圾对象并清理,把剩余非垃圾对象放入survivor的to区(survivor的from和to区是相互转换的,每次minor gc有对象的那个区为from区,无对象的为to区)。下一次再进行minor gc的时候,把Eden区和from区进行清理,然后把剩余的非垃圾对象放入to区(ps:通过这个操作,大家也能知道新生代使用的算法就是复制算法),并且每次minor gc存活下来的对象的分代年龄+1(下图是Object的详细信息,实例数据就是我们平时关注的如User对象的id,name属性,大家了解即可)。

经历多轮minor gc后,一个对象的分代年龄如果到达了15轮,那么这个对象被认为是一些“老不死”的对象,然后这个对象就晋升到老年代。(ps:所以大家可以思考一下,我们工作平时写的业务代码哪些对象是这些“老不死”的对象?就是如我们spring经常定义的各类bean,如xxService、xxController,这些都是被到处使用,属于“老不死”的对象。)

Full GC:

上述minor gc最终会有对象晋升到老年代,那么在程序运行过程中,老年代的内存也是不断积累的,那么在老年代满了之后,就发生了full gc,这个full gc会发生STW(stop the world)现象,jvm通过关闭用户线程来专注于垃圾收集,所以full gc如果频繁发生是会对应用程序运行造成卡顿现象的。所以gc调优主要就是针对full gc进行调优,尽量减少full gc的次数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值