String Constant Pool

Los tipos de datos String son algo muy común en los desarrollos de aplicaciones, y para poder optimizar la memoria, la máquina virtual de Java reserva un área especial de la memoria donde guarda las referencias a los objetos de tipo String, denominada “String Constant Pool”.

¿Cómo Funciona?
Se trata de una zona de memoria donde se almacenan las referencias a los objetos String. De esta manera, cada vez que se crea un String, la máquina virtual de Java primero comprueba si la cadena se encuentra en el String Constant Pool, si la cadena ya existe devuelve la referencia a la cadena existente, y si la cadena no existe se crea un nuevo objeto String, cuya referencia es colocada en la String Constant Pool.

Gracias a la Pool se evita tener en memoria muchos objetos de tipo String con el mismo contenido. Además,los objetos String apuntados de la String Constant Pool nunca son elegibles por el recolector de basuras, ya que la referencia a estos objetos siempre esta en uso. Gracias a estas dos características se consigo optimizar el rendimiento de las aplicaciones y el uso de memoria.

String Inmutable y Final
Ahora puede entenderse porqué los String son inmutables, puesto que varias referencias podrían apuntar al mismo String sin que lo supieran, propiciando fallos si alguna referencia cambia el valor del String. Al ser los objetos String inmutables se pueden compartir de forma segura y evitando crear varios objetos Strings iguales.

Además, para evitar que alguien sobrescriba la funcionalidad de la clase String y modificar alguno de estos comportamientos, la clase String esta declarada como ‘final’.

Creando Nuevos Strings
Existen dos formas de crear un nuevo String:

Utilizando un literal
La manera de crear un literal es la siguiente:

Creación de lieterales

Cuando se crea un String de esta manera la JVM comprueba si el String existe en la String Constant Pool, si no existe entonces se crea un objeto de tipo String en la heap y la referencia es almacenada en la String Constant Pool. Por último, la referencia es asignada a la variable cadena. Si a continuación se ejecuta la siguiente sentencia:

La JVM comprueba en la pool si existe la cadena y al encontrarlo, coge la referencia y la almacena en cadena2. En este caso no se vuelve a crear un nuevo objeto String sino que se reutiliza el ya existente. Si ejecutamos el siguiente código se puede comprobar que al comparar las dos cadenas usando el operador ==, este devuelve true.

Utilizando el operador new
Cuando creamos un String con el operador new utilizamos la siguiente instrucción:

En este caso, suponiendo que no existe un String con el valor “string” en la String Constant Pool, se crean dos objetos en el heap. Uno de ellos es el objeto referenciado por cadena y, el otro, un objeto String es referenciado por la String Constant Pool.

Creación de String con new

Método Intern
Cuando se crea un String utilizando el operador new, este no apunta a un objeto referenciado por la String Constant Pool. Pero puede conseguirse utilizando el método java.lang.String.intern(). El método devuelve una referencia a un objeto String que se encuentra en la String Constant Pool. Si el String no se encuentra todavía en la pool, se añade. Por ejemplo:

Recolector de Basura

Un objeto es elegible por el recolector de basura cuando no ha sido referenciado durante un largo tiempo. Pero, ¿cómo se comporta el GC con los literales de tipo String?

Después de terminar la ejecución del método podemos pensar que ambos objetos serían elegibles por el GC, pero no es así, únicamente el objeto cadena2 podría ser elegible por el GC. Esto es debido a que la referencia al objeto cadena1 siempre esta en uso, ya que se encuentra almacenada en la String Constant Pool, de esta manera el objeto siempre tendrá una referencia activa y no podrá ser elegible por el GC.

Ventajas

  • Se evita la creación de Strings duplicados, de esta manera se mejora la utilización de la memoria.
  • De esta menra podremos comparar Strings de manera segura utilizando el operador ==, ya que se garantiza que ambos Strings son la misma instancia.

Desventajas

  • Las referencias a Strings que se encuentran en la pool se conservan durante toda la duración del programa. Esto significa que el recolector de basuras nunca actuará sobre ellos. Si se tiene un literal de gran tamaño, que solo se utiliza temporalmente, esto puede incrementar el uso de la memoria.
  • Si creamos un String con new String(“java”) este no será añadido a la String Literal Pool, pero será creado como un nuevo objeto en la heap. Esto significa que no se podrá comparar utilizando el operador ==, necesitaremos utilizar el método equals().

ENLACES |
http://preparandoscjp.wordpress.com/2012/03/27/clasesdecadena/
http://www.javacodegeeks.com/2012/07/string-memory-internals.html
http://theopentutorials.com/tutorials/java/strings/string-literal-pool/