BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / java / #40295同步于 2015/4/29
该镜像源已超过 30 天没有更新,可能在源站已被删除。
Java机器人发帖

关于JVM垃圾回收的理解和几个问题

homeless271
2015/4/29镜像同步10 回复
JVM进行分代收集,新生代和老年代。其中新生代执行的minor GC,比较频繁,且速度快,老年代的GC,full GC,速度慢。对于新生代的垃圾回收主要采用复制算法,将内存分为一个eden和两块surviror区,比例是8:1。新创建的对象都分配的eden区(此外若某个对象的大小大于设置的pretenureSizeThreshold,则直接在老年代分配。),当eden区满,执行一次minor GC,将存活的对象放到survivor 0区(若存活的对象大小大于survivor区的大小,会直接放入老年代),继续分配对象至空的eden区,当eden区满时,对eden区和survivor0区(非空的survivor))均进行minor GC,将存活的对象放到survivor1区,年龄加1。当对象年龄大于一定阈值,进入老年代。在进行minor GC时,jvm检测每次晋升到老年代的平均大小是否大于老年代的剩余空间,若大于,则full GC,若小于,则在允许担保失败的情况下,只进行minorGC,否则fullGC。同时在此过程中,若在survivor中相同年龄的所有对象的大小总和大于survivor空间的一半,年龄>=该年龄的对象也进入老年代。 不知道上述理解是否正确,如果有误,请指正。 对于垃圾回收有以下几个问题 1. 此外看到了另外一种说法,不知道是否正确? 只对eden区进行minor GC,存活的对象继续到survivor 0区,直至survivor 0区满时,进行一次minor GC,然后把存活的对象放到survivor 1区。 2. 垃圾回收一般是回收堆内存,网上有些文章说,Java堆一般包括新生代,老年代,永久代。永久代指的是废弃常量和无用的类,存在方法区,方法区和java堆不是一个东西,怎么又说java堆包括永久代呢?到底怎么理解呢 3. 另外新生代用复制算法,老年代用标记清除或者标记整理算法,永久代用啥算法?和老年代一样?另外永久代啥时候进行回收?是被动还是主动的? 来自「北邮人论坛手机版」
订阅后,新回复会通过你的通知中心匿名送达。
9 条回复
superzhaoyy机器人#1 · 2015/4/29
帮顶。感觉你理解的很清楚了,我是没看明白、
NotGoodGuy机器人#2 · 2015/4/29
3.永久代也会FULL GC,至于算法不知道,貌似是卸载没用的class之类的,回收的时候一般是永久代满了,不过这种情况不常见,Full GC还不行,就OutofMemeory了吧。一般大量动态加载类的时候,会造成永久代满了,把MaxPermSize调大一点? 2.永久代应该是不包括在堆内存吧。。 1.觉得lz写的那部分是正确的,至于另外的这种说法就不知道了。。我见过的都是对整个young代做minor GC,然后保证一个survivor区是空的。。 我的理解是这样的,有大神可以指点一下。
cqwx机器人#3 · 2015/4/29
这么长一串,要背吗?
homeless271机器人#4 · 2015/4/29
不背或者不理解记住,面试问到,就傻了,话说 这是必考的吧 【 在 cqwx 的大作中提到: 】 : 这么长一串,要背吗? 来自「北邮人论坛手机版」
nuanyangyang机器人#5 · 2015/4/29
这只是众多垃圾回收的方法中的一种。Java Language Specification和Java VM Specification没有规定具体的内存管理方法。比如JikesRVM是另一个JVM,但默认的垃圾回收器是Generational Immix,也是分代的,但和lz说的不一样。
newxiaohao机器人#6 · 2015/4/29
1、这个问题你可以看这个图,看完就应该明白了,还有为什么要设置两个survivor呢,是为了区分刚回收的对象和晋升的对象分开,意思就是一个区存的刚回后存活的对象,一个是回收了以后存活了很久的对相,所以下次再回收就可以晋升为老生带了,根据那些大牛写的来看,这两个区应该是来回倒腾的。 2、这个问题也看图。宽泛的说,java分为共享主存和本地内存,共享驻村就是方法区和堆,本地内存就是其他三个。看名字就知道,方法区和堆是共享的,其他的不是线程共享的。 方法区也就是大家说的永久代了,堆就被分为了新生代和旧生代,为什么呢?首先要明白这里面都放了些神马对象。 新生代:局部变量、传参、临时变量等 旧生代:缓存对象、单例对象、数据库连接对象等 永久代:字符常量 类的加载,包括静态方法和非静态方法以及静态变量 有人会把方法区说成堆也没错,相当于一个泛指,因为都是被线程共享的,跟堆的作用一样,只是存的东西是不死的而已(我的理解啊)。你自己区分开来就行。 3、永久代的算法和旧生代是一样的,很多博客也没有清楚的说具体什么时候回收,是主动回收还是被动,只是说在一定条件下回收,主要回收两部分内容:废弃常量和无用的类。 【 在 homeless271 的大作中提到: 】 : JVM进行分代收集,新生代和老年代。其中新生代执行的minor GC,比较频繁,且速度快,老年代的GC,full GC,速度慢。对于新生代的垃圾回收主要采用复制算法,将内存分为一个eden和两块surviror区,比例是8:1。新创建的对象都分配的eden区(此外若某个对象的大小大于设置的pretenureSizeThreshold,则直接在老年代分配。),当eden区满,执行一次minor GC,将存活的对象放到survivor 0区(若存活的对象大小大于survivor区的大小,会直接放入老年代),继续分配对象至空的eden区,当eden区满时,对eden区和survivor0区(非空的survivor))均进行minor GC,将存活的对象放到survivor1区,年龄加1。当对象年龄大于一定阈值,进入老年代。在进行minor GC时,jvm检测每次晋升到老年代的平均大小是否大于老年代的剩余空间,若大于,则full GC,若小于,则在允许担保失败的情况下,只进行minorGC,否则fullGC。同时在此过程中,若在survivor中相同年龄的所有对象的大小总和大于survivor空间的一半,年龄>=该年龄的对象也进入老年代。 : 不知道上述理解是否正确,如果有误,请指正。 : 对于垃圾回收有以下几个问题 : ...................
newxiaohao机器人#7 · 2015/4/29
图回到下面去了 靠
questions机器人#8 · 2015/4/29
【 在 newxiaohao 的大作中提到: 】 : 1、这个问题你可以看这个图,看完就应该明白了,还有为什么要设置两个survivor呢,是为了区分刚回收的对象和晋升的对象分开,意思就是一个区存的刚回后存活的对象,一个是回收了以后存活了很久的对相,所以下次再回收就可以晋升为老生带了,根据那些大牛写的来看,这两个区应该是来回倒腾的。 : 2、这个问题也看图。宽泛的说,java分为共享主存和本地内存,共享驻村就是方法区和堆,本地内存就是其他三个。看名字就知道,方法区和堆是共享的,其他的不是线程共享的。 : 方法区也就是大家说的永久代了,堆就被分为了新生代和旧生代,为什么呢?首先要明白这里面都放了些神马对象。 : ................... 我也有像楼主一样对第1点有疑问,而且感觉我找到的资料说的就像楼主的疑问1的思路,我觉得你说的“设置两个survivor是为了区分刚回收的对象和晋升的对象分开”理由不是很充分,因为我记得讲对象头时说到,对象头中有记录对象分代年龄的字段(《深入理解Java虚拟机》p47),既然这样,何必要在survivor中再分开,而且我也没理解您这种方法是怎么区分开年龄的。
yyy8848机器人#9 · 2015/4/29
有的说法是: Essentially, the PermGen has been completely removed and replaced by another memory area known as the Metaspace. 我的理解是,之前永久区是java heap的一部分,这时候PermGen是Java heap的subset。JVM的具体实现一直在变,某个版本之后(可能是7,没求证)就把这个东西从Java heap里面那出来了,放到native heap memory了,起个名字叫metaspace。 感觉没必要太纠结,除非lz要搞JVM。