JVM---分代管理

我们常说的gc,就是垃圾会收集机制,他负责是讲系统中的没有引用的对象回收,也就是主要作用于堆内存和方法区,当然从jdk1.8以后,jvm将元空间替代了方法区,永久带不存在了,并且将静态池和常量池移动到了对内存中。
在java1.7及以前虚拟机中,我们会把java内存分成 新生代 和 老年代,还有方法区。新生代存放刚刚新建的实例对象,老年代存放通过指定次数gc后任然存活的对象或者是实例对象需要很大的空间,而新生代无法存放的对象,而永久代这事存放类的对象信息,常量池和静态变量,而这三个地方的数据,永久代是最难清理的,且清理的条件可可复杂。


1、新生代

新生代存在于对内存中,且分成了三块,分别是eden,和2块幸存区。eden翻译过来就是伊甸园,很形象,表示所有的新生对象多是在这个地方的,其他俩个幸存区,必然有一个是空着的,用来存放minor gc 幸存的对象。
这三块区域初始的比值是8:1:1。他们的gc算法是 复制–清理 算法,而复制-清理算法的大致过程是:新生的对象被放到eden区,但是eden区域是有限的啊,所以,当eden区内存满的时候,触发gc过程。(当然,这发生新生代的gc之前,老年代还需要进行一些处理)
GC触发后,虚拟机首先把eden区和其中一块存放对象的幸存区的所有存活对象 复制 到临时的幸存区,然后,对 eden 和 被复制之后的幸存区进行清理操作,这样会把所有的为存活对象的都清理掉。那么,一次这样的新生代GC就完成了。
这其中,经历了一次gc依旧存活的对象,会在自己对象的存活次数标记上 +1,等到存活次数达到 设置的 值,就从 新生代移动到老年代。

2、老年代

老年代的内存大小和新生代的大小,大致是相同的,而老年代的对象也是从新生代或者是直接放进去的。
那么,新生代的对象怎么晋级到老年代呢?三种途径:

  1. 对象中在新生代中,会有一个属性,记录他经历的GC次数,如果经历了15次,那么,就会直接进入老年代。
  2. 并不是所有的对象都会经历15的GC才会进入老年代,当同一个GC年龄的对象所占的内存大小已经大雨了幸存区的50%了,会进制老年代。
  3. 也不是所有的新生对象都会直接进入新生代,而是看这个对象的大小,如果,该对象太大,新生代的eden区域不足以放置,那么会有老年代的内存进行分担。

对于老年代,JVM一般有2中方法来进行内存的回收,一种是标记–清理,另一种是标记–整理。二者的区别在于,标记–清理算法,会把失活数据标记上,然后利用清理算法把失活对象清理掉了,那么做的结果就是,清理掉引用不可达的对象后,存活的对象不移动内存位置,造成内存不连续。而标记–整理会把引用可达的对象放到一边,引用不可达的对象放到另一次,这样清理后的内存空间就是连续的了。在垃圾回收器中,cms垃圾回收期用到的就是标记–清理;而G1垃圾回收器用的则是标记–整理。
着重说明CMS的gc过程。

  1. 预标记, 标记可达对象,主要是标记直接可达对象,这个工程是单线程,并且会进行stw(STOP THE WORD)
  2. 并发标记, 并发的对见解可达对象进行递归标记
  3. 并发预清理,清理有新生代只想老年代的对象,为重新标记做准备,减少重标记的停顿时间
  4. 重标记
  5. 并发清理,清理
  6. 重置,重置状态,为下次gc做好准备
    老年代垃圾回收的触发条件是,当老年代的内存满了之后,进行垃圾回收;新生代晋升到老年代会进行内存检测。
    大致过程是:当进行新生代的GC时,首先去查看老年代空闲内存,当老年代的可用空间大于新生代对象的空间总和的时候,新生代可以进行GC,为啥?因为,即使新生代的GC过后,所有的对象都是可达的,都是有效的,那么他们都要进入老年代,这样,老年代放不下,势必造成对象丢失。
    如果老年代的可用空间比新生代的所有对象空间综合小的话,那么会看老年代是否进行内存分担,进行分担的话,还要看老年代所能使用的空间和新生代晋升上的对象大小的平均值比较,如果老年代大,可以冒险进行新生代GC,但是如果老年代小,那么,老年代就要进行Full gc,进行垃圾回收了。而冒险的话,有可能,新生代垃圾回收晋级过来的对象太大,那么这是,老年代也要进行full gc。
    (我们说的【新生代晋升上的对象大小的平均值】的意思是:每次gc晋级的综合除以晋级次数,就是晋级对象的平均值)

3、方法区

JVM对方法去的回收效率太低了,方法区也被称为不死区,所以,基本不会进行回收,及时回收,用的算法也是标记–清理。


对象可达

这里涉及到一个问题:怎么知道对象可达?一般是俩中算法:

  1. 引用计数。很好理解,一个对象,有一个引用,对象的这个属性就 + 1,当为0的时候,为不可达。
  2. 对象可达。这种是用图的概念来表示的,没有一个引用指向该对象就为不可达。

类对象的可达

类对象怎么判断不可达:
1、 类对象被卸载了。
2、类实例被回收了。
3、类.class没有别的地方引用了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值