JVM内存是有限的,JVM中有个内存分代
堆内存:年轻代+老年代,统称为堆,可设置大小
年轻代分为三块:年轻代、S1区、S2区(survivor区)
默认情况下,新生代:S1:S2比例是8:1:1
假设年轻代2个G,那么实际上分为1.6G/0.2G/0.2G
|
新生代/年轻代(Eden区)1.6G | |
|
S1区 0.2G |
S2区 0.2G |
2G老年代
对象一开始是放在年轻代中,如果eden区满了,会出YGC,处理没有引用的对象
两种对象不能回收:
(1)正在执行的方法中引用的对象,不能回收(有对象的局部方法引用的)
(2)存活的对象内部引用的静态变量对象,不能回收(被类的静态变量引用的)
其他对象基本上都可以进行回收
【评论区】
1、问题:为什么2个string+然后intern就会返回true,一个string然后intern就会返回false?
String str2 = new String("str")+new String("01");
str2.intern();
String str1 = "str01";
System.out.println(str2==str1);//true
String a = new String("haha");
System.out.println(a.intern() == a);//false
(1)new出来的字符串是在堆中存储,当str2.intern的时候判断str01是否在字符串常量池中存在,存在则直接返回 不存在则添加str01到常量池中 str1即直接取常量池中字符串,所以两者地址值是相等的
(2)a=haha,haha new创建时有在堆中有一个haha字符串对象变量a指向这个对象 当调用a.intern时常量池中不存在haha这个字符串常量,会将haha添加到字符串常量池中这个地址值和堆中haha的地址值是不一样的
2、总结
- 垃圾回收的主要作用区域是堆区,堆区分为年轻代和老年代,其中年轻代又分为eden与两个s区,这样分代的原因主要是方便根据各个区域的对象特点选择更合适的回收算法。
- 在分区清晰后,GC的触发条件是这两个区域对象装不下了,因此就要通过GC回收掉没有引用的对象。
- 可以分为两个区域去总结。年轻代:没有足够的内存去分配给新的对象了。老年代:没有足够的内存去分配给新晋升的对象了,或者是因为分配担保机制导致老年代触发GC。
- 最后的metaspace也会因为内存不足从而触发GC。
本文探讨了JVM内存管理,重点在于理解何时触发垃圾回收。堆内存分为年轻代和老年代,年轻代进一步划分为eden、S1和S2区。对象首先在年轻代分配,当eden区满时触发YGC。无法回收的对象包括正在执行方法中引用的对象和由静态变量引用的对象。垃圾回收主要针对堆区,特别是在年轻代无法分配新对象或老年代无法容纳晋升对象时。此外,元空间的内存不足也会引发GC。评论区讨论了字符串常量池与intern()方法的行为,进一步阐述了对象存储位置对回收的影响。
2万+

被折叠的 条评论
为什么被折叠?



