2010-08-10 18 views
17

Inspirado por los comentarios en this question, estoy bastante seguro de que Java String s están internados en tiempo de ejecución en lugar de compilar - seguramente el hecho de que las clases se pueden compilar en diferentes momentos, pero aún apuntan a la misma referencia en tiempo de ejecución .¿Cuándo se interrumpe Java Strings?

Parece que no puedo encontrar ninguna evidencia que respalde esto. ¿Alguien puede justificar esto?

Respuesta

16

La optimización sucede (o al menos puede suceder) en ambos lugares:

  • Si dos referencias a la misma constante de cadena aparecen en la misma clase, yo esperaría que el archivo de clase que sólo contienen una constante entrada de la piscina. Esto no es estrictamente requerido con el fin de garantizar que haya solo un objeto String creado en la JVM, pero es una optimización obvia para hacer. Esto no es en realidad pasantía como tal, solo optimización constante.
  • Cuando se cargan las clases, el grupo de cadenas para la clase se agrega al grupo interno. Esta es una pasantía "real".

(Tengo un vago recuerdo que uno de los bits de trabajo para Java 7 en torno a "pequeños archivos jar" incluía un único grupo de cadena para todo el archivo jar ... pero podría ser muy mal.)

EDIT: Sección 5.1 de la especificación JVM, "The Runtime Constant Pool" entra en detalles sobre esto:

para derivar una cadena literal, la máquina virtual de Java examina la secuencia de caracteres dadas por la estructura CONSTANT_String_info.

  • Si el método String.intern ha previamente ha llamado en una instancia de la clase String que contiene una secuencia de caracteres Unicode idénticas a que la dada por la estructura CONSTANT_String_info , entonces el resultado de cadena literal derivación es una referencia a que la misma instancia de clase String.

  • De lo contrario, una nueva instancia de la clase cadena se crea que contiene la secuencia de caracteres Unicode dadas por la estructura CONSTANT_String_info ; esa instancia de clase es el resultado de derivación literal de cadena. Finalmente, se invoca el método interno de la nueva instancia de String .

+0

Recuerdo que en algún lugar que leí dijo que el grupo de cadenas tiene un alcance por paquetes. No puedo recordar la fuente del mismo –

+0

@Dennis: Eso me parece inexacto. La Sección 3.10.5 del JLS no menciona eso por lo que puedo ver. –

+0

(+1) Seguí el enlace en los [comentarios que conducen a esta pregunta] (http://stackoverflow.com/questions/3450604/why-is-there-no-string-empty-in-java/3450623# 3450623) para responder con referencias a la misma documentación, solo para descubrir que Jon Skeet ya estaba en el caso. : P –

0

tiempo de ejecución.

Las especificaciones JLS y JVM especifican la compilación javac para los archivos de clase que contienen declaraciones constantes (en el grupo de constantes) y uso constante en el código (que javac puede alinear como valores de referencia primitivos/objetos). Para las constantes de cadena en tiempo de compilación, el compilador genera código para construir instancias de cadena y para llamar a String.intern() para ellas, de modo que la JVM haga un interrogatorio de las constantes de cadena automáticamente.Se trata de un comportamiento requisito de JLS: expresiones constantes

http://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.28

tiempo de compilación de tipo String son siempre "internados" con el fin de compartir instancias únicas, utilizando el método String.intern.

Pero estas especificaciones no tienen ni el concepto ni la definición de cualquier cadena en particular estructuras piscina pasante/referencias/manetas si el tiempo de compilación o en tiempo de ejecución. (Por supuesto, en general, la especificación de JVM no exige ninguna estructura interna particular para los objetos: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-2.html#jvms-2.7)

La razón por la que no se mencionan estructuras internas de grupos es porque se manejan completamente con la clase String. El grupo interno es una estructura privada estática/de nivel de clase de la clase String (no especificada por JLS & JVM especificaciones & javadoc).

Los objetos se agregan al grupo interno cuando se invoca String.intern() en tiempo de ejecución. El grupo interno se aprovecha de forma privada por la clase String: cuando el código crea nuevas instancias String y llama a String.intern(), la clase String determina si se reutilizarán los datos internos existentes. La optimización puede ser llevada a cabo por el compilador JIT en tiempo de ejecución.

Aquí no hay ninguna contribución en tiempo de compilación, salvo la vainilla en línea de valores constantes.

+0

"Como el código intenta crear nuevas instancias' String' ". De Verdad? ¿O solo los literales 'String'? – Raedwald

+0

Han aclarado: String.intern() es el desencadenante de la clase String para intentar reutilizar internamente el elemento del grupo. Por supuesto, eso se llama implícitamente para las constantes de cadena en tiempo de compilación (literales y expresiones fijas). También puede ser llamado explícitamente por el desarrollador. –