为什么java生成的哈希id集合每次都几乎相同,但在调用System.gc()后它有更多的变化?

时间:2015-08-06 10:17:50

标签: java garbage-collection

我尝试收集java生成的对象id,然后对它们进行排序以查看模式:

public class Test{
    public static void main(String[] args){
        java.util.ArrayList<Integer> a=new java.util.ArrayList<Integer>();
        for(int i=0;i<16;i++){
            //String obj3=new String();
            //Object obj2=new Object();
            Object obj=new Object();
            a.add(System.identityHashCode(obj));
        }
        java.util.Collections.sort(a);
        for(Integer i:a){
            System.out.println(i);
        }
    }
}

一开始我认为对象id每次都应该不同,因为在我的印象中,对象id应该与对象地址相关,但是在我运行代码几次后它似乎返回相同的对象id集:

205238968
242666487
400535505
424201356
447267976
580487944
592598094
657291792
860080307
1040108132
1165259232
1265744841
1586482837
1608535231
1914494719
2053965899

即使有变化,对象id的集合也非常相似:

205238968
242666487
400535505
424201356
447267976
580487944
592598094
657291792
860080307
1040108132
1165259232
1586482837
1608535231
1914494719
2053965899
2127478981

我尝试通过在收集对象id期间创建一些额外的对象来更改程序:

public class Test{
    public static void main(String[] args){
        java.util.ArrayList<Integer> a=new java.util.ArrayList<Integer>();
        for(int i=0;i<16;i++){
            String obj3=new String();
            Object obj2=new Object();
            Object obj=new Object();
            a.add(System.identityHashCode(obj));
        }
        java.util.Collections.sort(a);
        for(Integer i:a){
            System.out.println(i);
        }
    }
}

但仍然得到非常相似(可能是相同的)结果集:

205238968
242666487
400535505
424201356
447267976
580487944
592598094
657291792
860080307
1040108132
1165259232
1265744841
1586482837
1608535231
1914494719
2053965899

但是当我尝试在创建每个对象之前调用System.gc()时:

public class Test{
    public static void main(String[] args){
        java.util.ArrayList<Integer> a=new java.util.ArrayList<Integer>();
        for(int i=0;i<16;i++){
            System.gc();
            Object obj=new Object();
            a.add(System.identityHashCode(obj));
        }
        java.util.Collections.sort(a);
        for(Integer i:a){
            System.out.println(i);
        }
    }
}

对象id的集合每次都有更多变化(但仍然找到一些与之前相同的值):

242666487
355475160
550670442
582642819
644278293
657291792
764062238
781143987
1165259232
1220081709
1579321858
1697022030
1726858146
1819177159
2065554654
2094048729

为什么会这样?

1 个答案:

答案 0 :(得分:1)

通过多次运行相同的程序获得相同的结果并不奇怪。对象分配在很大程度上是确定性的,并且在相同的JVM配置中,您应该期望跨运行的非常相似的身份哈希码。

每次执行GC时,都会收集Eden空间并将实时对象传输到其中一个Survivor空间(每个GC循环使用另一个Survivor空间,即上次无效的空间)。在几个GC循环后保持活动的对象获得终身(转移到老一代)。鉴于代码中GC周期的频率,这种情况很快就会发生。所有这些都为你的对象的排列带来了更多的复杂性,所以再次更多的方差是一个非常期望的结果(虽然我仍然期望远离随机行为)。