Я профилирую поведение мусора 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.0_37)
EDIT1: я немного изменил код, чтобы было ясно, что интернализация строк здесь не виновата, по крайней мере, так не выглядит.
EDIT2: Если вы замените String на Object во всем коде, вы получите тот же мусор, поэтому я предполагаю, что это связано с тем, как в Java происходит выделение объектов через new. При первом размещении объекта в классе вы получаете мусор. Второй раз нет. Странно, это для каждого класса.
EDIT3: я написал статья в блоге, где я рассказываю о том, как заставить сборщик мусора профилировать ваши приложения для создания мусора, как я делаю в приведенном выше коде.
new String("julia")
можно и нужно заменить на"julia"
. - person Tomasz Nurkiewicz   schedule 22.11.2012