在Java中实例化对象时产生奇怪的垃圾
我正在分析java.lang.String
的垃圾行为,看起来每次在任何类中第一次实例化字符串时,它总是生成垃圾。有人知道为什么吗
public abstract class AbstractTest {
protected static String SERGIO = "sergio";
private String someValue;
public void init() {
this.someValue = new String(SERGIO);
}
}
public class Test extends AbstractTest {
private static String JULIA = "julia";
private Runtime runtime = Runtime.getRuntime();
private String anotherValue;
private String yetAnother;
private void gc() throws InterruptedException {
System.gc();
Thread.sleep(100);
}
private long usedMemory() {
return runtime.maxMemory() - runtime.freeMemory();
}
public void test() throws Exception {
gc();
this.anotherValue = new String(SERGIO); // a bunch of garbage is created!
long usedMemory = usedMemory();
gc();
long usedMemoryAfterGC = usedMemory();
System.out.println("Collected: " + (usedMemory - usedMemoryAfterGC));
gc();
this.yetAnother = new String(JULIA); // no more garbage
usedMemory = usedMemory();
gc();
usedMemoryAfterGC = usedMemory();
System.out.println("Collected: " + (usedMemory - usedMemoryAfterGC));
}
public static void main(String[] args) throws Exception {
Test t = new Test();
t.test();
}
输出:
已收集:704336
已收集:0
没关系。第一次创建垃圾时,随后的实例化不会产生垃圾
奇怪的是,当你在超类中强制创建字符串时,当你第一次在子类中实例化字符串时,它仍然会在子类中创建垃圾:
public void test() throws Exception {
gc();
init(); // creates a String in the superclass
gc();
this.yetAnother = new String(JULIA);
long usedMemory = usedMemory();
gc();
long usedMemoryAfterGC = usedMemory();
System.out.println("Collected: " + (usedMemory - usedMemoryAfterGC));
}
输出:
收款:348648
知道为什么吗
(顺便说一句,我在MAC和JDK 1.6.037上运行这个)
EDIT1:我稍微修改了代码,以明确字符串内部化不是罪魁祸首,至少看起来不是
EDIT2:如果在整个代码中将字符串更改为对象,则会得到相同的垃圾,因此我猜这与Java中通过new进行对象分配的方式有关。第一次在类中分配对象时,就会得到垃圾。第二次你没有。奇怪的是每堂课都是
EDIT3:我写了一篇blog article,其中我讨论了如何强制GC分析应用程序以创建垃圾,就像我在上面的代码中所做的那样
共 (0) 个答案