Знам "a"
и new String("b")
и двете ще създадат "a"
или "b"
в постоянен басейн
Но защо следната програма не хвърля outOfMemoryError
?
Прави new String("b")
не създавате нищо в постоянен басейн?
List<String> s = new ArrayList<String>();
// -XX:PermSize=5M
// -XX:MaxPermSize=5M
// why no oom:pergen space throw???? "i" isn"t in constant pool????
for (;;) {
for (int i = 0; i < 1000000; i++) {
s.add(new String("" + i));
}
}
Отговори:
4 за отговор № 1нов низ (...) създава обект в нормална грамада, така че ограничаването на постоянно поколение няма да запали OOME. С по-стара версия на Java можете да симулирате, като се обадите на .intern () на получения низ, но дори това се е променило наскоро (моля, прочетете http://java-performance.info/string-intern-in-java-6-7-8/ за детайли).
В java 8 изглежда, че перм поколението изглежда напълно изчезнало http://www.infoq.com/articles/Java-PERMGEN-Removed така че, освен ако не се насочите конкретно към по-старите версии, може да се окаже контрапродуктивно да се опитате да намерите своите граници и вместо това да се опитате да разберете Metaspace.
1 за отговор № 2
Знам
"a"
иnew String("b")
и двете ще създадат"a"
или"b"
в постоянен басейн
Вашето "знание" е неправилно:
Всъщност говорите за струнния пул тук. (Постоянният пул е част от формата на файловете на класа и там нещата се „създават“ от компилатора и т.н.)
Докато
"a"
и"b"
ще бъде поставен в низовия пул, изразътnew String("b")
не създава (или използва повторно) низ в пула с низове. Той създава нов String обект в обичайната грамада.
Точка 2 обяснява защо не можете да запълвате permgen (на JVM, където съществува), като просто създавате низове, като използвате new String(...)
.
Ако искате да форсирате струни в низбасейн, трябва да използвате String.intern. Ако сте променили кода си на следното, трябва да можете да задействате OOME в купчината на permgen (Java 7 и по-стари):
for (;;) {
for (int i = 0; i < 1000000; i++) {
s.add((new String("" + i)).intern());
}
}