JVM中的内存管理
2019-02-26 16:56:28 36 举报
AI智能生成
java虚拟机中的内存管理
作者其他创作
大纲/内容
垃圾收集策略
判断哪些对象需要回收
1.引用计数法【可能导致循环引用】
每个对象都有一个引用计数器,当这个对象被一个变量或者另一个对象引用一次,该计数器加一;若引用失效则计数器减一,当计数器为0时,就认为该对象是无效对象
2.可达性分析法【一般使用】
所有和GC Roots直接或者间接关联的对象都是有效对象,和GC Roots没有关联的对象就是无效对象
GC ROOTS说明
1.java虚拟机栈中的所引用的对象。(栈帧中局部变量表中引用类型的变量所引用的对象。)
2.方法区中静态属性引用的对象。
3.方法区中常量所引用的对象。
4.本地方法栈所引用的对象
特别的:GC Roots不包括堆中的对象所引用的对象,这样就不会出现循环引用
回收无效对象的过程
1.判断该对象是否覆盖了finalize()方法
1.如果已经覆盖该方法,且该对象的finalize方法还没有被执行过,那么就将finalize方法扔到F-Queue队列中。
2.若果没有覆盖该方法,则直接释放对象内存
2.执行F-Queue队列中的finalize方法,
虚拟机会以较低的优先级去执行这些finalize方法们,也不会确保所有的finalize方法都会执行,如果finalize方法中出现耗时操作,虚拟机就直接停止执行,将该对象清除。
虚拟机会以较低的优先级去执行这些finalize方法们,也不会确保所有的finalize方法都会执行,如果finalize方法中出现耗时操作,虚拟机就直接停止执行,将该对象清除。
3.对象重生或死亡
如果执行finalize时,将this赋给了某一引用,那么该对象就重生了,如果没有,那么就会被垃圾收集器清除
垃圾收集算法
1.标记清除法
首先判断需要清除哪些数据,并给他们作上标记,然后清除被标记的数据
分析:
这种算法标记和清除的效率都很低,而且清除后存在大量的碎片空间,导致无法存储大对象,降低了空间利用率。
这种算法标记和清除的效率都很低,而且清除后存在大量的碎片空间,导致无法存储大对象,降低了空间利用率。
2.复制算法
将内存分成两份,只将数据存储在其中一块上。当需要垃圾回收时,也是标记出废弃的数据,然后将有用数据复制到另一块内存上,最后将第一块内存全部清除
分析:
这个算法避免了碎片空间,但内存被缩小了一半。而且每次都需要将有用的内存复制到另一块上,效率不高
这个算法避免了碎片空间,但内存被缩小了一半。而且每次都需要将有用的内存复制到另一块上,效率不高
3.标记整理算法
在垃圾回收之前,首先将所有废弃的对象作上标记,然后将所有未被标记的对象移到一边,最后清除另一边区域即可。
分析:
他是一种老年代的垃圾回收算法,老年代中的对象一般生命周期较长,因此每次垃圾回收时会有大量对象存活,因此如果使用复制算法,每次需要复制大量存活的对象,会导致效率很低,而且新生代中使用复制算法,而且老年代中
没有其他内存可以使用分配担保,因此老年代中一般使用标记-整理算法
他是一种老年代的垃圾回收算法,老年代中的对象一般生命周期较长,因此每次垃圾回收时会有大量对象存活,因此如果使用复制算法,每次需要复制大量存活的对象,会导致效率很低,而且新生代中使用复制算法,而且老年代中
没有其他内存可以使用分配担保,因此老年代中一般使用标记-整理算法
4.分代收集算法
将内存分为老年代和新生代,老年代中存放寿命较长的对象,新生代中存放“朝生夕死”的对象,然后在不同的区域使用不同的垃圾收集算法
新生代老年代主流使用回收算法
新生代:复制算法
老年代:标记整理法
对象内存分配策略
说明:目前,主流的垃圾回收器都采用分代回收算法,因此需要将堆内存分为新生代和老年代
1.对象优先在Eden中区中分配
在新生代中为了防止内存碎片问题,因此垃圾收集器都采用复制算法,因此堆内存的新生代被分为Eden+Survior1 + Survior2
每次创建对象,首先会在Eden区中分配
若Eden区已满,则在Survior1区中分配
若Eden + Survior1区剩余内存太少,导致对象无法放入改区时,就会启用“分配担保”将Eden区+Survior1区中的对象转移到老年代中。然后再将新对象存入Eden中
2.大对象直接进入老年代
所谓的大对象就是指一个占用大量连续存储空间的对象,如数组
一个大对象能够存入Eden+Survior1的几率比较小,发生分配担保的概率较大,而分配担保就需要涉及到大量的复制,就会造成效率低下
一个大对象能够存入Eden+Survior1的几率比较小,发生分配担保的概率较大,而分配担保就需要涉及到大量的复制,就会造成效率低下
因此,对于大对象我们直接把他放到老年代中,就能避免大量的复制操作
3.通过-XX:PretrnureSizeThreshold参数设置大对象
4.生命周期较长的对象进入老年代,使用-XXMaxTenuringThreshold设置新生代的最大年龄。
5.如果当前新生代的Sruvior中,年龄相同的对象内存空间总和超过了Sruvior内存空间的一半,那么所有年龄相同的对象和超过该年龄的对象都被转移到老年代中。无需等待MaxTenuringThreshold超过时再去转移。
特别的分配担保策略详解
当垃圾收集器准备要在新生代发起一次MinorGC时,首先会检查老年代中最大的空闲连续区域大小是否大于新生代中所有对象的大小
若老年代能装下新生代中的所有对象,那么此时就进行MinorGC没有任何风险,然后就进行MinorGC
若老年代不能装下新生代中的所有对象,那么此时进行MinorGC就是有风险的,垃圾收集器会进行一次预测,根据以往MinorGC过后对象的存活数,来预测这次MinorGC后存活的对象数
如果以往存活的平均对象数小于老年代最大的连续空闲空间,那么就进行MinorGC是有风险的
如果以往存活的平均对象数大于老年代最大的连续空闲空间,那么就对老年代进行一次Full GC,通过清除老年代中废弃数据来扩大老年代的空闲空间,以便给新生代做担保。
0 条评论
下一页