我尝试收集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
为什么会这样?
答案 0 :(得分:1)
通过多次运行相同的程序获得相同的结果并不奇怪。对象分配在很大程度上是确定性的,并且在相同的JVM配置中,您应该期望跨运行的非常相似的身份哈希码。
每次执行GC时,都会收集Eden空间并将实时对象传输到其中一个Survivor空间(每个GC循环使用另一个Survivor空间,即上次无效的空间)。在几个GC循环后保持活动的对象获得终身(转移到老一代)。鉴于代码中GC周期的频率,这种情况很快就会发生。所有这些都为你的对象的排列带来了更多的复杂性,所以再次更多的方差是一个非常期望的结果(虽然我仍然期望远离随机行为)。