¿Cuánta memoria usa una cadena en Java 8?

Últimamente he leído mucho acerca de la asignación de memoria para Strings y no puedo encontrar ningún detalle si las cosas son las mismas para Java 8.

¿Cuánto espacio de memoria usaría String como "Alexandru Tanasescu" en Java 8? Yo uso la versión de 64 bits.

Java7 o inferior

Mínimo uso de memoria de cadena:

 (bytes) = 8 * (int) ((((no chars) * 2) + 45) / 8) 

Asi que

 80 = 8 * (int) ((((19) * 2) + 45) / 8) 

Comprender el uso de la memoria String ( SOURCE )

Para comprender el cálculo anterior, debemos comenzar mirando los campos en un objeto String. Una cadena contiene lo siguiente:

  • una matriz de caracteres, por lo tanto un objeto separado, que contiene los caracteres reales;
  • un desplazamiento entero en la matriz en la que se inicia la cadena;
  • la longitud de la cuerda;
  • otra int para el cálculo en caché del código hash.

Esto significa que incluso si la cadena no contiene caracteres, requerirá 4 bytes para la referencia de matriz char, más 3 * 4 = 12 bytes para los tres campos int, más 8 bytes de encabezado de objeto. Esto da 24 bytes (que es un múltiplo de 8 por lo que no se necesitan bytes de “relleno”).

Entonces, la matriz de caracteres (vacía) requerirá 12 bytes adicionales (las matrices tienen 4 bytes adicionales para almacenar su longitud), más en este caso 4 bytes de relleno para llevar la memoria utilizada por el objeto de matriz de caracteres hasta un múltiplo de 16. Entonces, en total, una cadena vacía usa 40 bytes.

Si la String contiene, por ejemplo, 19 caracteres, entonces el objeto Cadena en sí mismo aún requiere 24 bytes. Pero ahora la matriz char necesita 12 bytes de encabezado más 19 * 2 = 38 bytes para los diecisiete caracteres. Como 12 + 38 = 50 no es un múltiplo de 8, también tenemos que redondear al siguiente múltiplo de 8 (56). Entonces, en general, nuestra String 19 caracteres usará 56 + 24 = 80 bytes.


Java8.

Java 8 ya no tiene el offset y la length . Solo hash y CharArray .
@Thomas Jungblut

  • una matriz de caracteres, por lo tanto un objeto separado, que contiene los caracteres reales;
  • un desplazamiento entero en la matriz en la que se inicia la cadena;
  • la longitud de la cuerda;
  • otra int para el cálculo en caché del código hash.

Por lo tanto, en Java8 la forma de calcular la memoria para cadenas sigue siendo la misma, pero debe restar 8 bytes menos debido a la length y el offset faltantes.

Si miras las fonts de Oracle Java 8, tienes:

Un char value[] y un int hash . Un char es de 2 bytes, y un int es de 4 bytes.

Entonces, ¿la respuesta no sería yourstring.length * 2 + 4?

No. Todos los objetos tenían sobrecarga. Una matriz almacena sus dimensiones, por ejemplo. Y tanto la matriz (un objeto) como la cadena incurrirán en memoria extra del recolector de basura almacenando información sobre ellos.

No existe una manera confiable de calcular esto, porque AFAIK cada JRE y JDK no tiene ninguna obligación con el tamaño de la sobrecarga del objeto.

“Alexandru Tanasescu” usa 104 bytes. Esta es la forma de obtener el tamaño

  long m0 = Runtime.getRuntime().freeMemory(); String s = new String("Alexandru Tanasescu"); long m1 = Runtime.getRuntime().freeMemory(); System.out.println(m0 - m1); 

Nota: ejecútelo con la opción -XX: -UseTLAB

De acuerdo con el siguiente JEP: http://openjdk.java.net/jeps/254

La implementación actual de la clase String almacena caracteres en una matriz char, utilizando dos bytes (dieciséis bits) para cada carácter.

En Java SE 9 esto podría cambiar.

Sin embargo, tenga en cuenta que, dado que este es un JEP, no un JSR (y menciona la implementación), entiendo que esto es específico de las implementaciones y no está definido por el JLS.