有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

在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) 个答案