3.2.1 引用计数算法
/**
* testGC()方法执行后,objA和objB会不会被GC呢?
*VM Args:-verbose:gc: -Xms20M -Xmx20M -Xmn10M -verbose:gc -XX:+PrintGCDetails -XX:SurvivorRatio=8
* @author huangh
*/
package cn.chapter3;
public class ReferenceCountingGC {
public Object instance = null;
private static final int _1MB = 1024*1024;
/**
* 这个成员的唯一意义就是占点内存,以便能在GC日志中看清楚是否被回收过
*/
private byte[] bigSize = new byte[2*_1MB];
public static void testGC(){
ReferenceCountingGC objA = new ReferenceCountingGC();
ReferenceCountingGC objB = new ReferenceCountingGC();
objA.instance = objB;
objB.instance = objA;
objA = null;
objB = null;
//假设在这行发生GC,那么objA和objB是否能被回收?
System.gc();
}
public static void main(String[] args){
testGC();
}
}
书本有点坑啊(对新手),没有给出vm args和main函数
运行结果:
[Full GC[Tenured: 0K->375K(10240K), 0.0044187 secs] 4823K->375K(19456K), [Perm : 178K->178K(12288K)], 0.0207159 secs] [Times: user=0.00 sys=0.00, real=0.02 secs]
Heap
def new generation total 9216K, used 166K [0x34000000, 0x34a00000, 0x34a00000)
eden space 8192K, 2% used [0x34000000, 0x34029b50, 0x34800000)
from space 1024K, 0% used [0x34800000, 0x34800000, 0x34900000)
to space 1024K, 0% used [0x34900000, 0x34900000, 0x34a00000)
tenured generation total 10240K, used 375K [0x34a00000, 0x35400000, 0x35400000)
the space 10240K, 3% used [0x34a00000, 0x34a5dd58, 0x34a5de00, 0x35400000)
compacting perm gen total 12288K, used 178K [0x35400000, 0x36000000, 0x39400000)
the space 12288K, 1% used [0x35400000, 0x3542cb90, 0x3542cc00, 0x36000000)
ro space 10240K, 44% used [0x39400000, 0x3987d3a8, 0x3987d400, 0x39e00000)
rw space 12288K, 52% used [0x39e00000, 0x3a449a18, 0x3a449c00, 0x3aa00000)
4823K->375K(19456K)表明,GC发生前,该内存已使用4823K,GC发生后,该内存使用了375K,表明对象已被回收,从而表明JVM没有使用引用计数算法。Java中使用了可达性分析算法来来判定对象是否存活
3.2.4 生存还是死亡
代码清单3-2 一次对象自我拯救的演示
/**
* 此代码演示了两点
* 1,对象可以在被GC时自我拯救
* 2,这种自救的机会只有一次,因为一个对象的finalize()方法最多只会被系统自动调用一次
* @author huangh
*/
package cn.chapter3;
public class FinalizeEscapeGC {
public static FinalizeEscapeGC SAVE_HOOK = null;
public void isAlive(){
System.out.println("yes, i am still alive:)");
}
@Override
protected void finalize() throws Throwable{
super.finalize();
System.out.println("finalize method executed!");
FinalizeEscapeGC.SAVE_HOOK = this;
}
public static void main(String[] args) throws Throwable {
SAVE_HOOK = new FinalizeEscapeGC();
//对象第一次成功拯救自己
SAVE_HOOK = null;
System.gc();
//因为finalizer方法优先级很低,暂停0.5秒,以等待它
Thread.sleep(500);
if(SAVE_HOOK != null){
SAVE_HOOK.isAlive();
}else{
System.out.println("no, i am dead:(");
}
//下面这段代码与上面完全相同,但是这次自救却失败了
SAVE_HOOK = null;
System.gc();
//因为finalizer方法优先级很低,暂停0.5秒,以等待它
Thread.sleep(500);
if(SAVE_HOOK != null){
SAVE_HOOK.isAlive();
}else{
System.out.println("no, i am dead:(");
}
}
}
运行 结果:
finalize method executed!
yes, i am still alive:)
no, i am dead:(
3.5.1 对象优先在Eden分配
书本上的vm args不全,少了-verbose:gc -XX:+PrintGCDetails,并且没有main函数
/**
* 代码清单3-3, 新生代Minor GC
* VM Args:-verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8
* @author huangh
*/
package cn.chapter3;
public class MinorGC {
private static final int _1MB = 1024*1024;
public static void testAllocation(){
byte[] allocation1, allocation2, allocation3, allocation4;
allocation1 = new byte[2*_1MB];
allocation2 = new byte[2*_1MB];
allocation3 = new byte[2*_1MB];
allocation4 = new byte[4*_1MB]; //出现一次Minor GC
}
public static void main(String[] args){
testAllocation();
}
}
运行结果:
[GC[DefNew: 6871K->376K(9216K), 0.0069608 secs] 6871K->6520K(19456K), 0.0070398 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
def new generation total 9216K, used 4638K [0x34000000, 0x34a00000, 0x34a00000)
eden space 8192K, 52% used [0x34000000, 0x34429810, 0x34800000)
from space 1024K, 36% used [0x34900000, 0x3495e098, 0x34a00000)
to space 1024K, 0% used [0x34800000, 0x34800000, 0x34900000)
tenured generation total 10240K, used 6144K [0x34a00000, 0x35400000, 0x35400000)
the space 10240K, 60% used [0x34a00000, 0x35000030, 0x35000200, 0x35400000)
compacting perm gen total 12288K, used 178K [0x35400000, 0x36000000, 0x39400000)
the space 12288K, 1% used [0x35400000, 0x3542caf0, 0x3542cc00, 0x36000000)
ro space 10240K, 44% used [0x39400000, 0x3987d3a8, 0x3987d400, 0x39e00000)
rw space 12288K, 52% used [0x39e00000, 0x3a449a18, 0x3a449c00, 0x3aa00000)
3.5.2 大对象直接进入老年代
书本上的vm args不全,少了-verbose:gc -XX:+PrintGCDetails,并且没有main函数
/**
* -verbose:gc -Xms20M -Xmx20M -Xmn10M -verbose:gc -XX:+PrintGCDetails -XX:SurvivorRatio=8 -XX:PretenureSizeThreshold=3145728
* 3145728B表示3M,但是不能写成3M
* @author huangh
*/
package cn.chapter3;
public class BigInstance {
private static final int _1MB = 1024*1024;
public static void testPretenureSizeThreshold(){
byte[] allocation;
allocation = new byte[4 * _1MB];//直接分配在老年代中
}
public static void main(String[] args) {
testPretenureSizeThreshold();
}
}
运行结果:
Heap
def new generation total 9216K, used 891K [0x34000000, 0x34a00000, 0x34a00000)
eden space 8192K, 10% used [0x34000000, 0x340def78, 0x34800000)
from space 1024K, 0% used [0x34800000, 0x34800000, 0x34900000)
to space 1024K, 0% used [0x34900000, 0x34900000, 0x34a00000)
tenured generation total 10240K, used 4096K [0x34a00000, 0x35400000, 0x35400000)
the space 10240K, 40% used [0x34a00000, 0x34e00010, 0x34e00200, 0x35400000)
compacting perm gen total 12288K, used 178K [0x35400000, 0x36000000, 0x39400000)
the space 12288K, 1% used [0x35400000, 0x3542cab0, 0x3542cc00, 0x36000000)
ro space 10240K, 44% used [0x39400000, 0x3987d3a8, 0x3987d400, 0x39e00000)
rw space 12288K, 52% used [0x39e00000, 0x3a449a18, 0x3a449c00, 0x3aa00000)
3.5.3 长期存活的对象将进入老年代
书本上的vm args不全,少了-verbose:gc -XX:+PrintGCDetails,并且没有main函数
/**
* -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+PrintTenuringDistribution -XX:+PrintGCDetails
*/
package cn.chapter3;
public class LongSurvivor {
private static final int _1MB = 1024*1024;
@SuppressWarnings("unused")
public static void testTenuringThreshold(){
byte[] allocation1, allocation2, allocation3;
allocation1 = new byte[_1MB/4]; //什么时候进入老年代取决于XX:MaxTenuringThreshold设置
allocation2 = new byte[4*_1MB];
allocation3 = new byte[4*_1MB];
allocation3 = null;
allocation3 = new byte[4*_1MB];
}
public static void main(String[] args) {
testTenuringThreshold();
}
}
以MaxTenuringThreshold=1的参数设置类运行的结果
[GC[DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 1)
- age 1: 647384 bytes, 647384 total
: 5079K->632K(9216K), 0.0048008 secs] 5079K->4728K(19456K), 0.0048604 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC[DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 1)
- age 1: 136 bytes, 136 total
: 4812K->0K(9216K), 0.0010879 secs] 8908K->4727K(19456K), 0.0011262 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 4260K [0x34000000, 0x34a00000, 0x34a00000)
eden space 8192K, 52% used [0x34000000, 0x34428fd8, 0x34800000)
from space 1024K, 0% used [0x34800000, 0x34800088, 0x34900000)
to space 1024K, 0% used [0x34900000, 0x34900000, 0x34a00000)
tenured generation total 10240K, used 4727K [0x34a00000, 0x35400000, 0x35400000)
the space 10240K, 46% used [0x34a00000, 0x34e9dec0, 0x34e9e000, 0x35400000)
compacting perm gen total 12288K, used 178K [0x35400000, 0x36000000, 0x39400000)
the space 12288K, 1% used [0x35400000, 0x3542caf0, 0x3542cc00, 0x36000000)
ro space 10240K, 44% used [0x39400000, 0x3987d3a8, 0x3987d400, 0x39e00000)
rw space 12288K, 52% used [0x39e00000, 0x3a449a18, 0x3a449c00, 0x3aa00000)
以MaxTenuringThreshold=15的参数设置类运行的结果
[GC[DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 15)
- age 1: 647384 bytes, 647384 total
: 5079K->632K(9216K), 0.0042640 secs] 5079K->4728K(19456K), 0.0043323 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC[DefNew
Desired survivor size 524288 bytes, new threshold 15 (max 15)
- age 1: 136 bytes, 136 total
: 4812K->0K(9216K), 0.0009837 secs] 8908K->4727K(19456K), 0.0010050 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 4260K [0x34000000, 0x34a00000, 0x34a00000)
eden space 8192K, 52% used [0x34000000, 0x34428fd8, 0x34800000)
from space 1024K, 0% used [0x34800000, 0x34800088, 0x34900000)
to space 1024K, 0% used [0x34900000, 0x34900000, 0x34a00000)
tenured generation total 10240K, used 4727K [0x34a00000, 0x35400000, 0x35400000)
the space 10240K, 46% used [0x34a00000, 0x34e9dec0, 0x34e9e000, 0x35400000)
compacting perm gen total 12288K, used 178K [0x35400000, 0x36000000, 0x39400000)
the space 12288K, 1% used [0x35400000, 0x3542caf0, 0x3542cc00, 0x36000000)
ro space 10240K, 44% used [0x39400000, 0x3987d3a8, 0x3987d400, 0x39e00000)
rw space 12288K, 52% used [0x39e00000, 0x3a449a18, 0x3a449c00, 0x3aa00000)
怎么运行结果时和书上不一样,没有出现age = 2的情况?这是什么原因???待解决。。。。
3.5.4 动态对象年龄判定
/**
* -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:MaxTenuringThreshold=15 -XX:+PrintTenuringDistribution -XX:+PrintGCDetails
*/
package cn.chapter3;
public class LongSurvivor2 {
private static final int _1MB = 1024*1024;
@SuppressWarnings("unused")
public static void testTenuringThreshold2(){
byte[] allocation1, allocation2, allocation3,allocation4;
allocation1 = new byte[_1MB/4]; //allocation1 + allocation2大于survivor空间的一半
allocation2 = new byte[_1MB/4];
allocation3 = new byte[4*_1MB];
allocation4 = new byte[4*_1MB];
allocation4 = null;
allocation4 = new byte[4*_1MB];
}
public static void main(String[] args) {
testTenuringThreshold2();
}
}
运行结果:
[GC[DefNew
Desired survivor size 524288 bytes, new threshold 1 (max 15)
- age 1: 909552 bytes, 909552 total
: 5335K->888K(9216K), 0.0043895 secs] 5335K->4984K(19456K), 0.0044696 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC[DefNew
Desired survivor size 524288 bytes, new threshold 15 (max 15)
- age 1: 136 bytes, 136 total
: 5068K->0K(9216K), 0.0012928 secs] 9164K->4983K(19456K), 0.0013303 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 4260K [0x34000000, 0x34a00000, 0x34a00000)
eden space 8192K, 52% used [0x34000000, 0x34428fd8, 0x34800000)
from space 1024K, 0% used [0x34800000, 0x34800088, 0x34900000)
to space 1024K, 0% used [0x34900000, 0x34900000, 0x34a00000)
tenured generation total 10240K, used 4983K [0x34a00000, 0x35400000, 0x35400000)
the space 10240K, 48% used [0x34a00000, 0x34edded0, 0x34ede000, 0x35400000)
compacting perm gen total 12288K, used 178K [0x35400000, 0x36000000, 0x39400000)
the space 12288K, 1% used [0x35400000, 0x3542cb08, 0x3542cc00, 0x36000000)
ro space 10240K, 44% used [0x39400000, 0x3987d3a8, 0x3987d400, 0x39e00000)
rw space 12288K, 52% used [0x39e00000, 0x3a449a18, 0x3a449c00, 0x3aa00000)
运行结果和书上的解释有误差
3.5.5 空间分配担保
/**
* -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:SurvivorRatio=8 -XX:HandlePromotionFailure=false -XX:+PrintGCDetails
*/
package cn.chapter3;
public class handle_Promotion {
private static final int _1MB = 1024*1024;
@SuppressWarnings("unused")
public static void testHandlePromotion(){
byte[] allocation1, allocation2, allocation3,allocation4,allocation5,allocation6,allocation7;
allocation1 = new byte[2*_1MB];
allocation2 = new byte[2*_1MB];
allocation3 = new byte[2*_1MB];
allocation1 = null;
allocation4 = new byte[2*_1MB];
allocation5 = new byte[2*_1MB];
allocation6 = new byte[2*_1MB];
allocation1 = null;
allocation2 = null;
allocation3 = null;
allocation7 = new byte[2*_1MB];
}
public static void main(String[] args) {
testHandlePromotion();
}
}
以HandlePromotionFailure=false的参数设置来运行的结果
Java HotSpot(TM) Client VM warning: ignoring option HandlePromotionFailure=false; support was removed in 6.0_24
[GC[DefNew: 6871K->376K(9216K), 0.0043879 secs] 6871K->4472K(19456K), 0.0044752 secs] [Times: user=0.00 sys=0.02, real=0.02 secs]
[GC[DefNew (promotion failed) : 6692K->6691K(9216K), 0.0036908 secs][Tenured: 8192K->6518K(10240K), 0.0046860 secs] 10788K->6518K(19456K), [Perm : 178K->178K(12288K)], 0.0084553 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
Heap
def new generation total 9216K, used 2130K [0x34000000, 0x34a00000, 0x34a00000)
eden space 8192K, 26% used [0x34000000, 0x34214828, 0x34800000)
from space 1024K, 0% used [0x34800000, 0x34800000, 0x34900000)
to space 1024K, 0% used [0x34900000, 0x34900000, 0x34a00000)
tenured generation total 10240K, used 6518K [0x34a00000, 0x35400000, 0x35400000)
the space 10240K, 63% used [0x34a00000, 0x3505dab8, 0x3505dc00, 0x35400000)
compacting perm gen total 12288K, used 178K [0x35400000, 0x36000000, 0x39400000)
the space 12288K, 1% used [0x35400000, 0x3542cb58, 0x3542cc00, 0x36000000)
ro space 10240K, 44% used [0x39400000, 0x3987d3a8, 0x3987d400, 0x39e00000)
rw space 12288K, 52% used [0x39e00000, 0x3a449a18, 0x3a449c00, 0x3aa00000)
以HandlePromotionFailure=true的参数设置来运行的结果
Java HotSpot(TM) Client VM warning: ignoring option HandlePromotionFailure=true; support was removed in 6.0_24
[GC[DefNew: 6871K->376K(9216K), 0.0038882 secs] 6871K->4472K(19456K), 0.0039691 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]
[GC[DefNew (promotion failed) : 6692K->6691K(9216K), 0.0037950 secs][Tenured: 8192K->6518K(10240K), 0.0047771 secs] 10788K->6518K(19456K), [Perm : 178K->178K(12288K)], 0.0086326 secs] [Times: user=0.02 sys=0.00, real=0.02 secs]
Heap
def new generation total 9216K, used 2130K [0x34000000, 0x34a00000, 0x34a00000)
eden space 8192K, 26% used [0x34000000, 0x34214828, 0x34800000)
from space 1024K, 0% used [0x34800000, 0x34800000, 0x34900000)
to space 1024K, 0% used [0x34900000, 0x34900000, 0x34a00000)
tenured generation total 10240K, used 6518K [0x34a00000, 0x35400000, 0x35400000)
the space 10240K, 63% used [0x34a00000, 0x3505dab8, 0x3505dc00, 0x35400000)
compacting perm gen total 12288K, used 178K [0x35400000, 0x36000000, 0x39400000)
the space 12288K, 1% used [0x35400000, 0x3542cb58, 0x3542cc00, 0x36000000)
ro space 10240K, 44% used [0x39400000, 0x3987d3a8, 0x3987d400, 0x39e00000)
rw space 12288K, 52% used [0x39e00000, 0x3a449a18, 0x3a449c00, 0x3aa00000)
运行结果应该时不一样的,但是运行时说好像被移除了,所以暂时看不出来区别。