Comportamiento de recolección de basura para String.intern ()

Si utilizo String.intern () para mejorar el rendimiento ya que puedo usar “==” para comparar cadenas internas, ¿me encontraré con problemas de recolección de elementos no utilizados? ¿Cómo difiere el mecanismo de recolección de basura de cadenas internas de las cadenas normales?

De hecho, esto no es una optimización de la recolección de basura, sino más bien una optimización de agrupación de cadenas. Cuando llama a String.intern() , reemplaza la referencia a su cadena inicial con su referencia base (la referencia de la primera vez que se encontró esta cadena, o esta referencia si aún no se conoce).

Sin embargo, se convertirá en un problema para el recolector de basura una vez que la cadena ya no tenga uso en la aplicación, ya que el grupo de cadenas internas es un miembro estático de la clase String y nunca se recolectará basura.

Como regla general, considero preferible nunca usar este método interno y dejar que el comstackdor lo use solo para cadenas constantes, aquellas declaradas así:

 String myString = "a constant that will be interned"; 

Esto es mejor, en el sentido de que no te dejará hacer la suposición falsa == podría funcionar cuando no lo haga.

Además, el hecho es que String.equals subyace llamadas == como una optimización, por lo que es seguro que las cadenas internas de optimización se utilizan bajo el capó. Esta es una evidencia más == nunca debe usarse en Strings.

String.intern() administra un grupo interno, implementado String.intern() , que tiene algunas características especiales relacionadas con GC. Este es código antiguo, pero si se implementara de nuevo, usaría java.util.WeakHashMap . Las referencias débiles son una forma de mantener un puntero a un objeto sin impedir que se recopile. Justo lo correcto para un grupo unificador como cadenas internas.

Que las cadenas internas son basura recolectada se puede demostrar con el siguiente código Java:

 public class InternedStringsAreCollected { public static void main(String[] args) { for (int i = 0; i < 30; i ++) { foo(); System.gc(); } } private static void foo() { char[] tc = new char[10]; for (int i = 0; i < tc.length; i ++) tc[i] = (char)(i * 136757); String s = new String(tc).intern(); System.out.println(System.identityHashCode(s)); } } 

Este código crea 30 veces la misma cadena, internando cada vez. Además, usa System.identityHashCode() para mostrar qué código hash Object.hashCode() habría devuelto en esa cadena interna. Cuando se ejecuta, este código imprime valores enteros distintos, lo que significa que no obtiene la misma instancia cada vez.

De todos modos, el uso de String.intern() se desaconseja un tanto. Es un grupo estático compartido, lo que significa que se convierte fácilmente en un cuello de botella en sistemas multi-core. Use String.equals() para comparar cadenas, y vivirá más tiempo y más feliz.

Este artículo proporciona la respuesta completa.

En Java 6, el grupo de cadenas reside en PermGen, ya que java 7, el grupo de cadenas reside en la memoria del montón.

Las cadenas internados manualmente serán recogidos basura.
Los literales de cadena serán solo basura recolectada si la clase que los define está descargada.

El grupo de cadenas es un HashMap con un tamaño fijo que era pequeño en java 6 y versiones anteriores de java 7, pero aumentó a 60013 desde java 7u40.
Se puede cambiar con -XX: StringTableSize = y se puede ver con -XX: + PrintFlagsFinal java options.

Por favor, lea: http://satukubik.com/2009/01/06/java-tips-memory-optimization-for-string/

La conclusión que puedo obtener de su información es: Intercedió demasiadas cadenas . Si realmente necesita internar tantas cadenas para la optimización del rendimiento, aumente la memoria de la memoria permanente , pero si yo fuera usted, primero comprobaré si realmente necesito tantas cadenas internas.