Подтвердить что ты не робот

Когда строка будет мусором, собранным в java

В Java, когда объект не имеет живой ссылки, он имеет право на сбор мусора. Теперь в случае строки это не так, потому что строка войдет в пул строк, а JVM сохранит объект для повторного использования. Итак, это означает, что некогда созданная строка будет "никогда" не собирать мусор?

4b9b3361

Ответ 1

  Теперь в случае строки это не так, потому что строка попадет в пул строк, а JVM сохранит объект для повторного использования. Значит, однажды созданная строка "никогда" не будет собираться мусором?

Во-первых, только строковые литералы (см. примечания) автоматически интернируются/добавляются в пул строк. String объекты, созданные приложением во время выполнения, не интернируются... если только ваше приложение явно не вызывает String.intern().

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

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

Тем не менее, это не всегда так. Если строковый литерал был определен в классе, который был динамически загружен (например, с помощью Class.forName(...)), то можно договориться о том, чтобы класс был выгружен. Если это произойдет, тогда объект String, соответствующий литералу, может быть недоступным и, в конечном счете, может быть GC-кодом.

См. также: Когда и как мусор классов собирается в Java?


Примечания:

  1. Строковый литерал (JLS 3.10.5) - это строка, которая появляется в исходном коде Java; например,

      "abc"            // string literal
      new String(...)  // not a string literal
    
  2. Строка, полученная вычислением константного выражения (во время компиляции) (JLS 15.28), также может быть интернирована.

      "abc" + 123                   // 123 is a constant expression
      "abc" + Integer.valueOf(123)  // Integer.valueOf(123) is also
                                    // a constant expression
    
  3. Строго говоря, не все строковые литералы интернированы. Если литерал String появляется только в исходном коде как подвыражение константного выражения, этот литерал может не отображаться в файле ".class" ни в какой форме. Такой литерал не будет интернирован, потому что он не будет существовать во время выполнения.

Ответ 2

Вы правы; строки в пуле пользователя никогда не будут GC'd.

Однако большинство строк не интернированы.
Строковые литералы интернированы, а строки, переданные в String.intern(), интернированы, но все остальные строки не интернированы и могут быть GC'd в обычном режиме.

Ответ 3

Строковые объекты, которые находятся в пуле строк, не будут собираться мусором. Другие объекты String будут собираться мусором, если у вас нет ссылки на него при выполнении вашей программы.

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

  • Литералы времени компиляции (например, String s1 = "123";)

  • Объекты Interned String во время выполнения (например, String s2 = new String("test").intern();)

И s1, и s2 ссылаются на строковый объект в пуле строк.

Любые объекты, которые создаются во время выполнения и не являются внутренними, будут действовать как обычный объект и хранятся в динамической памяти. Эти объекты можно собирать мусором.

Примером этого может быть: String s3 = s1 + s2;

Здесь s3 ссылается на строковый объект, который находится в памяти кучи вместе с другими объектами (не в пуле строк).