2013-03-10 4 views
17

Я читаю о сборке мусора, и я получаю запутывающие результаты поиска, когда я ищу коллекции струнных литеральных мусора.Сбор мусора из строковых литералов

мне нужно разъяснение по следующим пунктам:

  1. Если строка определяется как буквальное во время компиляции [например: String str = "java"], то это будет мусора?

  2. Если используется метод intern [например: String str = new String("java").intern()], то это будет сбор мусора? Также будет рассматриваться иначе, чем строковый литерал в пункте 1.

  3. В некоторых местах упоминается, что литералы будут собирать мусор только тогда, когда класс String будет выгружен? Это имеет смысл, потому что я не думаю, что класс String будет выгружен.

+2

1 - http://stackoverflow.com/questions/2202162/garbage-collection-and-strings; 2 - http://stackoverflow.com/questions/6470651/creating-a-memory-leak-with-java; 3 - String a = new String («asd») -> «a» ссылка будет собрана мусором, но это просто ссылка на «asd» и «asd» будет навсегда. – user1050755

+0

Если вы ищете больше, вы найдете места, упоминающие, что строковые литералы, созданные с использованием intern, могут быть собраны в мусор, поскольку они используют слабую ссылку, но я не могу подтвердить это, и именно по этой причине я опубликовал ее, так как есть много смешанных ответов. – Lokesh

ответ

18

Если строка во время компиляции определена как литерал [например: String str = "java";], то будет ли это сбор мусора?

Возможно, нет. Объекты кода будут содержать одну или несколько ссылок на объекты String, которые представляют литералы. До тех пор, пока объекты кода достижимы, объекты String будут.

Возможно, объекты кода станут недоступными, но только если они были динамически загружены ... и их загрузчик классов уничтожен.

Если я использую метод intern [e.g: String str = new String("java").intern()], тогда это будет сбор мусора?

Объект, возвращенный intern вызов будет тот же объект, который представляет собой "java" строка символов. (The "java" буквальным интернирован во время загрузки класса. Когда вы затем стажер недавно построенный String объект в фрагмент кода, он будет искать и возвращать ранее интернирован "java" строку.)

Однако интернированные строки, которые не совпадают с строковые литералы может быть собранным мусором, как только они становятся недоступными. Местом PermGen является мусор, собранный на всех последних JSM HotSpot. (До Java 8 ... который падает PermGen полностью.)

Также он будет относиться по-разному из строкового литерала в пункте 1.

... Нет, потому что это тот же объект, строковый литерал.

И действительно, как только вы поймете, что происходит, ясно, что струнные литералы также не обрабатываются специально. Это просто применение «достижимость» правила ...

В некоторых местах упоминаются, что литералы будут мусор только тогда, когда String класса будет выгружен? Имеет ли смысл, потому что я не думаю, что класс String будет выгружен.

Вы правы. Это не имеет смысла. Источники, которые сказали, что неверны. (Было бы полезно, если бы вы разместили URL-адрес, чтобы мы могли прочитать, что они говорят для себя ...)

+1

За # 1, Когда вы говорите объекты кода, содержащие ссылки на строковые литералы, на что вы ссылаетесь? – Mercenary

+4

Где-то в объектах кода (байт-код или собственный скомпилированный) будут выполняться команды, которые должны получить ссылку на объект String, соответствующий литералу. Либо ссылка встроена в сам код, либо хранится в частном фрейме, который связан с кодом. В любом случае эта ссылка является «достижимой», если код * может быть выполнен. –

+0

Спасибо. И, является ли строка внутри пула частью области метода в JVM? – Mercenary

9

В нормальных условиях, строковые литералы и классы все выделяются в постоянное поколение в JVM (в «PermGen»), и, как правило, никогда не будут собраны. Строки, которые интернированы (например, mystring.intern()), хранятся в пуле памяти, принадлежащем классу String, в пермгене, и когда-то это было так, что агрессивное интернирование могло вызвать утечку пространства, поскольку сам пул строк содержал ссылку на каждую строку, даже если других ссылок не было. По-видимому, это уже не так, по крайней мере, от JDK 1.6 (см., Например, here).

Подробнее о permgen, this является достойным обзором темы. (Примечание: эта ссылка относится к блогу, связанному с продуктом. У меня нет связи с блогом, компанией или продуктом, но запись в блоге полезна и не имеет большого отношения к продукту.)

+2

Это неверно. Пространство PermGen >> является << сборкой мусора. –

+0

Вы, конечно, правы. Мое намерение состояло в том, чтобы просто сказать, что данные, помещенные в пермг, не будут получать GC'ed при нормальных обстоятельствах, но я ошибочно. Немного перефразировано. – jacobm

+0

На самом деле, копая глубже, я обнаружил, что уже не так, что интернированные строки не собирают мусор. (Это происходит не из-за пространства пермгенов, это связано с реализацией 'String # intern'.) Изменение моего ответа, чтобы отразить это. – jacobm

0
  1. Литеральная строка останется в памяти, пока программа находится в памяти.
  2. str будет собирать мусор, но буквальный он создан из не будет.
  3. Это имеет смысл, поскольку класс строки выгружается при разгрузке программы.
+0

Можете ли вы привести пример, где String можно выгрузить? Поскольку я считаю, что литералы String также должны использоваться в классах Java, а также, поскольку литералы String являются константами, разгрузка может потребовать разгрузки CLassLoader, насколько мне известно. Вы согласны? – Lokesh

+0

Строковый литерал не может, насколько мне известно, программно разгружаться. Они будут выгружены или уничтожены, когда программа завершится. – fredrik

+1

@fredrik - они также могут быть собраны в мусор, если класс, который был динамически загружен, выгружается. И это может случиться, когда JVM работает нормально. –

-3

intern() метод проверяет доступность объекта в пуле строк. Если объект/литерал доступен, ссылка будет возвращена. Если литерала нет в пуле, тогда объект загружается в области perm (пул строк), а затем ссылка на него будет возвращена. Мы должны использовать метод intern() разумно.

+0

Литерал всегда находится в бассейне, по определению. – EJP

Смежные вопросы