Это Sun JDK 1.6u21, x64.
У меня есть класс для экспериментов с использованием perm gen, который содержит только одну большую строку (512k символов):
public class Big0 {
public String bigString =
"A string with 2^19 characters, should be 1 MB in size";
}
Я проверяю использование perm gen с помощью getUsage().toString()
на объекте MemoryPoolMXBean
для постоянного поколения (называемого «PS Perm Gen» в u21, хотя он имеет немного разные имена с разными версиями или с разными сборщиками мусора.
Когда я впервые ссылаюсь на класс, скажем, при чтении Big0.class
, perm gen перескакивает на ~ 500 КБ - этого я ожидал, поскольку кодировка строки константного пула - UTF-8, а я использую только символы ASCII.
Однако, когда я действительно создаю экземпляр этого класса, perm gen подскакивает на ~ 2 МБ. Поскольку это строка в памяти размером 1 МБ (2 байта на символ UTF16, конечно, без суррогатов), я не понимаю, почему использование памяти удваивается.
Тот же эффект произойдет, если я сделаю строку статичной. Если бы я использовал final, он не компилируется, поскольку я превышаю предел для элементов постоянного пула в 65535 байт (не уверен, почему отключение final также позволяет избежать этого - считайте, что это бонусный вопрос).
Любое понимание ценится!
Изменить: я также должен указать, что это происходит с нестатическими, конечными нестатическими и статическими строками, но не с конечными статическими строками. Поскольку это уже лучшая практика для строковых констант, возможно, это представляет в основном академический интерес.