[JVM] Trece, tabla de cadenas

Hola a todos, soy un cerdo dominado por el repollo.

Una persona que ama estudiar, que no duerme y se olvida de comer, está obsesionada con el chico guapo de codificación chic, tranquilo e indiferente de la chica.

Si te gusta mi texto, sigue la cuenta pública "Deja ir este repollo y déjame venir".

Este artículo combina [Preparación de la entrevista] con algunos detalles sobre String, y el efecto de lectura es mejor.

Mesa de 13 cuerdas

Uno, las características básicas de String

  • Cadena: una cadena de caracteres, representada por un par de "".

  • Cadena declarada como final y no se puede heredar

  • String implementa la interfaz serializable: admite la serialización cuando representa una cadena.

    Implementó la interfaz Comparable: esa cadena se puede comparar en tamaño

  • Cadena de caracteres final definida internamente [] valor en jdk8 y antes para almacenar datos de cadena. Cuando jdk 9 se cambia a byte []

Cambios en la estructura de almacenamiento de cadenas en jdk9

Veamos que dice el documento oficial

http://openjdk.java.net/jeps/254

## Motivation

The current implementation of the `String` class stores characters in a `char` array, using two bytes (sixteen bits) for each character. Data gathered from many different applications indicates that strings are a major component of heap usage and, moreover, that most `String` objects contain only Latin-1 characters. Such characters require only one byte of storage, hence half of the space in the internal `char` arrays of such `String` objects is going unused.

## Description

We propose to change the internal representation of the `String` class from a UTF-16 `char` array to a `byte` array plus an encoding-flag field. The new `String` class will store characters encoded either as ISO-8859-1/Latin-1 (one byte per character), or as UTF-16 (two bytes per character), based upon the contents of the string. The encoding flag will indicate which encoding is used.

Lo que quiere decir es que usamos char para almacenar dos bytes, pero la mayoría de los caracteres son latinos, y el latín se puede almacenar con un solo byte, por lo que el espacio general se desperdicia. Así que cambiamos a byte para almacenar la cadena, ¿qué pasa con los caracteres que ocupaban dos bytes antes? Al igual que el chino, ocupa dos caracteres. El documento propone utilizar una bandera de codificación y una marca para identificarlo como dos caracteres.

Cambios en la estructura de almacenamiento de cadenas

Conclusión: String ya no usa char [] para almacenarlo, se cambia a byte [] con marca de codificación, lo que ahorra algo de espacio. ¿Siguen siendo StringBuffer y StringBuilder indiferentes? No, también hicieron los cambios correspondientes.

Características básicas de String

  • Cadena: representa una secuencia inmutable de caracteres. Abreviatura: inmutabilidad.
    • Al reasignar una cadena, debe reescribir la asignación en el área de memoria designada y no puede usar el valor original para la asignación.
    • Al concatenar cadenas existentes, también debe volver a especificar el área de memoria para la asignación y no puede utilizar el valor original para la asignación.
    • Al llamar al método replace () de String para modificar el carácter o la cadena especificada, también necesita volver a especificar el área de memoria para la asignación, y no puede usar el valor original para la asignación.
  • Asigne un valor a una cadena literalmente (diferente de nuevo), y el valor de la cadena en este momento se declara en el grupo constante de creación de caracteres.

  • Las cadenas con el mismo contenido no se almacenarán en el grupo de constantes de cadenas.
    • El conjunto de cadenas de cadenas es una tabla hash de tamaño fijo y el valor predeterminado es 1009. Si se colocan muchas cadenas en el conjunto de cadenas, se producirán graves conflictos de hash, lo que provocará que la lista vinculada sea muy larga y la lista larga enlazada causará directamente El impacto es que el rendimiento caerá significativamente cuando se llame a String.intern.
    • Utilice -XX: StringTableSize para establecer la longitud de StringTable
    • StringTable está fijo en jdk6, que tiene una longitud de 1009, por lo que si hay demasiadas cadenas en el grupo constante, la eficiencia disminuirá rápidamente. La configuración de StringTableSize no es necesaria
    • En jdk7, la longitud predeterminada de StringTable es 60013, y no hay ningún requisito para la configuración de StringTableSize
    • A partir de jdk8, si establece la longitud de StringTable, 1009 es el valor mínimo que se puede establecer.

Dos, asignación de memoria de cadena

  • Hay 8 tipos de datos básicos y un tipo especial String en el lenguaje Java. Estos tipos proporcionan un concepto de agrupación constante para hacerlos más rápidos y más eficientes en memoria durante la operación.
  • El grupo de constantes es similar a un caché proporcionado por el nivel del sistema Java. Los grupos de constantes de los ocho tipos de datos básicos están coordinados por el sistema, y ​​el grupo de constantes del tipo String es especial. Hay dos formas principales de utilizarlo.
    • Los objetos de cadena declarados directamente usando comillas dobles se almacenarán directamente en el grupo constante.
      • 比如 : String info = "ljl es un chico guapo";
    • Si no es un objeto String declarado con comillas dobles, puede utilizar el método intern () proporcionado por String. Concéntrate en esto más tarde
  • En Java 6 y antes, el grupo de constantes de cadena se almacena en la generación permanente.
  • En Java 7, los ingenieros de Oracle realizaron un gran cambio en la lógica del grupo de cadenas, es decir, ajustaron la ubicación del grupo de constantes de cadenas al montón de Java.
    • Todas las cadenas se almacenan en el montón (Heap), como otros objetos ordinarios, por lo que solo necesita ajustar el tamaño del montón al ajustar las aplicaciones.
    • El concepto de grupo constante de cadenas se usó más originalmente, pero este cambio nos da suficientes razones para reconsiderar el uso de String.intern () en Java 7.
  • Metaspace Java8, las constantes de cadena están en el montón

¿Por qué debería ajustarse StringTable?

  • El espacio de generación permanente es relativamente pequeño por defecto
  • Baja frecuencia de recolección de basura de generación permanente

Tres, la operación básica de String

Cuarto, operación de empalme de cuerdas

  • El resultado del empalme de constantes y constantes está en el grupo constante, el principio es la optimización durante el tiempo de compilación
  • No habrá constantes con el mismo contenido en el grupo de constantes.
  • Siempre que uno de ellos sea una variable, el resultado está en el montón. El principio de empalme de variables es StringBuilder
  • Si el resultado del empalme llama al método intern (), el objeto de cadena que no está en el grupo constante se colocará activamente en el grupo y se devolverá la dirección de este objeto.

Cinco, el uso de pasante ()

Si no es un objeto String declarado con comillas dobles, puede utilizar el método interno proporcionado por String: el método interno consultará si la cadena actual existe del grupo constante de cadenas, y si no existe, la cadena actual parecen estar en la piscina constante.

  • Por ejemplo: String info = new String ("Me encanta ljl"). Intern ();

En otras palabras, si se llama al método String.intern en cualquier cadena, la instancia de clase a la que apunta el resultado devuelto debe ser exactamente la misma que la instancia de cadena directamente en forma de constante. Por tanto, el valor de la siguiente expresión debe ser verdadero:

  • ("A" + "b" + "c"). Pasante () == "abc"

En términos sencillos, Interned String asegura que solo haya una copia de la cadena en la memoria, lo que puede ahorrar espacio en la memoria y acelerar la ejecución de tareas de manipulación de cadenas. Tenga en cuenta que este valor se almacenará en String Intern Pool.


Resumir el uso de String intern ()

  • En jdk 1.6, intente poner este objeto de cadena en el grupo de cadenas.
    • Si hay en la piscina de cuerdas, no se colocará. Devuelve la dirección del objeto en el grupo de cadenas existente
    • De lo contrario, hará una copia de este objeto , lo colocará en el grupo de cadenas y devolverá la dirección del objeto en el grupo de cadenas.
  • Desde jdk 1.7, intente poner este objeto de cadena en el grupo de cadenas.
    • Si hay en la piscina de cuerdas, no se colocará. Devuelve la dirección del objeto en el grupo de cadenas existente
    • De lo contrario, se colocará como una copia de una referencia a la dirección , agregará un grupo de cadenas, una cadena y devolverá una referencia al grupo de direcciones.

Las plataformas de sitios web grandes requieren que se almacene una gran cantidad de cadenas en la memoria. Por ejemplo, los sitios de redes sociales, muchas personas almacenan: Beijing, distrito de Haidian y otra información. En este momento, si se llama al método intern () para todas las cadenas, el tamaño de la memoria se reducirá significativamente.

6. Recolección de basura de StringTable

Siete, operación de deduplicación de cadenas en G1

  • Antecedentes: las pruebas realizadas en muchas aplicaciones Java (grandes y pequeñas) arrojaron los siguientes resultados:
    • Los objetos de cadena en la recopilación de datos de supervivencia del montón representan el 25%
    • 13,5% de los objetos String duplicados en el conjunto de datos de supervivencia del montón
    • La longitud promedio de los objetos String es 45
  • El cuello de botella de muchas aplicaciones Java a gran escala es la memoria.Las pruebas han demostrado que en este tipo de aplicaciones, casi el 25% de las colecciones de datos que sobreviven en el montón de Java son objetos String. Además, casi la mitad de los objetos String se repiten, lo que significa: String1.equals (String2) = true. Los objetos String duplicados en el montón deben ser una pérdida de memoria. Este proyecto implementará la deduplicación automática y continua de los objetos String duplicados en el recolector de basura G1, para evitar el desperdicio de memoria.

  • lograr
    • Cuando el recolector de basura esté funcionando, accederá a los objetos que viven en el montón. Para cada objeto al que se accede, se comprueba si es un objeto de cadena candidato para ser deduplicado.
    • Si es así, inserte una referencia a este objeto en la cola y espere el procesamiento posterior. Un subproceso de deduplicación se ejecuta en segundo plano para procesar esta cola. Procesar un elemento de la cola significa eliminar el elemento de la cola y luego intentar desduplicar el objeto de cadena al que se refiere.
    • Utilice una tabla hash para registrar todas las matrices de caracteres únicas utilizadas por los objetos de cadena. Cuando se elimina la duplicación, se verificará la tabla hash para ver si ya existe una matriz de caracteres idéntica en el montón.
    • Si existe, el objeto de cadena se ajustará para hacer referencia a esa matriz, liberará la referencia a la matriz original y, finalmente, el recolector de basura lo reciclará.
    • Si la búsqueda falla, la matriz de caracteres se insertará en la tabla hash para que la matriz se pueda compartir más tarde.
  • Opciones de línea de comando
    • UseStringDeduplication (bool): habilita la deduplicación de cadenas. No está habilitada de forma predeterminada y debe habilitarse manualmente.
    • PrintStringDeduplicationStatistics (bool): imprime estadísticas detalladas de deduplicación
    • StringDeduplicationAgeThreshold (uintx): los objetos String que alcanzan esta edad se consideran candidatos para la deduplicación

Supongo que te gusta

Origin blog.csdn.net/weixin_44226263/article/details/112541554
Recomendado
Clasificación