Guía de los parámetros de JVM más importantes

1. Información general

En este tutorial rápido, exploraremos las opciones más conocidas que se pueden usar para configurar la máquina virtual Java.

2. Memoria de montón explícita: opciones de Xms y Xmx

Una de las prácticas relacionadas con el rendimiento más comunes es inicializar la memoria dinámica según los requisitos de la aplicación.

Es por eso que debemos especificar el tamaño de pila mínimo y máximo. Los siguientes parámetros se pueden utilizar para lograrlo:

-Xms[unit] -Xmx[unit]

Aquí, unidad denota la unidad en la que se inicializará la memoria (indicada por el tamaño del montón ). Las unidades se pueden marcar como 'g' para GB, 'm' para MB y 'k' para KB.

Por ejemplo, si queremos asignar un mínimo de 2 GB y un máximo de 5 GB a JVM, necesitamos escribir:

-Xms2G -Xmx5G

A partir de Java 8, el tamaño de Metaspace no está definido. Una vez que alcanza el límite global, JVM lo aumenta automáticamente.Sin embargo, para superar cualquier inestabilidad innecesaria, podemos establecer el tamaño de Metaspace con:

-XX:MaxMetaspaceSize=[unit]

Aquí, el tamaño del metaespacio denota la cantidad de memoria que queremos asignar a Metaspace .

Según las pautas de Oracle, después de la memoria total disponible, el segundo factor más influyente es la proporción del montón reservada para la generación joven. De forma predeterminada, el tamaño mínimo de YG es 1310 MB y el tamaño máximo es ilimitado .

Podemos asignarlos explícitamente:

-XX:NewSize=[unit] -XX:MaxNewSize=[unit]

3. Recolección de basura

Para una mejor estabilidad de la aplicación, es fundamental elegir el algoritmo de recolección de basura adecuado.

JVM tiene cuatro tipos de implementaciones de GC :

  • Recolector de basura en serie
  • Recolector de basura paralelo
  • Recolector de basura CMS
  • Recolector de basura G1

Estas implementaciones se pueden declarar con los siguientes parámetros:

-XX:+UseSerialGC -XX:+UseParallelGC -XX:+USeParNewGC -XX:+UseG1GC

Puede encontrar más detalles sobre las implementaciones de recolección de basura aquí.

4. Registro de GC

Para monitorear estrictamente el estado de la aplicación, siempre debemos verificar el rendimiento de recolección de basura de la JVM . La forma más sencilla de hacer esto es registrar la actividad de GC en formato legible por humanos.

Usando los siguientes parámetros, podemos registrar la actividad de GC :

-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles= -XX:GCLogFileSize=[ unit ] -Xloggc:/path/to/gc.log

UseGCLogFileRotation especifica la política de transferencia de archivos de registro, al igual que log4j, s4lj, etc. NumberOfGCLogFiles indica el número máximo de archivos de registro que se pueden escribir para un solo ciclo de vida de la aplicación. GCLogFileSize especifica el tamaño máximo del archivo. Finalmente, loggc denota su ubicación.

El punto a tener en cuenta aquí es que hay dos parámetros más de JVM disponibles ( -XX: + PrintGCTimeStamps y -XX: + PrintGCDateStamps ) que se pueden usar para imprimir la fecha y hora en el registro de GC .

Por ejemplo, si queremos asignar un máximo de 100 archivos de registro de GC , cada uno con un tamaño máximo de 50 MB y queremos almacenarlos en la ubicación ' / home / user / log /' , podemos usar la siguiente sintaxis:

-XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=10 -XX:GCLogFileSize=50M -Xloggc:/home/user/log/gc.log

Sin embargo, el problema es que siempre se usa un subproceso de demonio adicional para monitorear la hora del sistema en segundo plano. Este comportamiento puede crear algún cuello de botella en el rendimiento; por eso siempre es mejor no jugar con este parámetro en producción.

5. Manejo de memoria

Es muy común que una aplicación grande se enfrente a un error de memoria insuficiente que, a su vez, provoca el bloqueo de la aplicación. Es un escenario muy crítico y muy difícil de replicar para solucionar el problema.

Es por eso que JVM viene con algunos parámetros que vuelcan la memoria del montón en un archivo físico que se puede usar más adelante para encontrar fugas:

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./java_pid.hprof -XX:OnOutOfMemoryError=";" -XX:+UseGCOverheadLimit

Un par de puntos a tener en cuenta aquí:

  • HeapDumpOnOutOfMemoryError indica a la JVM que vuelque el montón en un archivo físico en caso de OutOfMemoryError
  • HeapDumpPath denota la ruta donde se escribirá el archivo; se puede dar cualquier nombre de archivo; sin embargo, si JVM encuentra unetiqueta en el nombre, el ID de proceso del proceso actual que causa el error de memoria insuficiente se agregará al nombre del archivo con formato .hprof
  • OnOutOfMemoryError se utiliza para emitir comandos de emergencia que se ejecutarán en caso de error de falta de memoria; el comando apropiado debe usarse en el espacio de cmd args. Por ejemplo, si queremos reiniciar el servidor tan pronto como se agote la memoria, podemos configurar el parámetro:
-XX:OnOutOfMemoryError="shutdown -r"
  • UseGCOverheadLimit es una política que limita la proporción del tiempo de la VM que se pasa en GC antes de que se produzca unerror OutOfMemory

6. 32/64 bits

En el entorno del sistema operativo donde se instalan paquetes de 32 y 64 bits, la JVM elige automáticamente los paquetes de entorno de 32 bits.

Si queremos configurar el entorno a 64 bits manualmente, podemos hacerlo usando el siguiente parámetro:

-d

El bit del sistema operativo puede ser 32 o 64 . Puede encontrar más información sobre esto aquí.

7. Varios

  • -servidor : habilita "Server Hotspot VM"; este parámetro se utiliza por defecto en JVM de 64 bits
  • -XX: + UseStringDeduplication : Java 8u20 ha introducido este parámetro de JVM para reducir el uso innecesario de memoria al crear demasiadas instancias de la misma cadena; esto optimiza la memoria del montón al reducir losvalores de cadena duplicadosa una única matriz global char []
  • -XX: + UseLWPSynchronization : establece lapolítica de sincronización basada en LWP ( proceso ligero ) en lugar de la sincronización basada en subprocesos
  • -XX: LargePageSizeInBytes : establece el tamaño de página grande utilizado para el montón de Java; toma el argumento en GB / MB / KB; con tamaños de página más grandes, podemos hacer un mejor uso de los recursos de hardware de la memoria virtual; Sin embargo, esto puede causar tamaños de espacio más grandes para PermGen , lo que a su vez puede obligar a reducir el tamaño del espacio de almacenamiento dinámico de Java.
  • -XX: MaxHeapFreeRatio : establece el porcentaje máximo de montón libre después de GC para evitar que se reduzca.
  • -XX: MinHeapFreeRatio : establece el porcentaje mínimo de montón libre después de GC para evitar la expansión; para monitorear el uso de la pila, puede usar VisualVM incluido con JDK.
  • -XX: SurvivorRatio : Relación del tamaño del espacio de eden / superviviente ; por ejemplo, -XX: SurvivorRatio = 6 establece la relación entre cada espacio de superviviente y el espacio de eden en 1: 6,
  • -XX: + UseLargePages : usa memoria de página grande si es compatible con el sistema; tenga en cuenta que OpenJDK 7 tiende a fallar si usa este parámetro de JVM

  • -XX: + UseStringCache : habilita el almacenamiento en caché de las cadenas asignadas comúnmente disponibles en elgrupo de cadenas

  • -XX: + UseCompressedStrings : use un tipo byte [] para losobjetos String que se pueden representar en formato ASCII puro
  • -XX: + OptimizeStringConcat : optimiza lasoperaciones de concatenación de cadenas siempre que sea posible

8. Conclusión

En este artículo rápido, aprendimos sobre algunos parámetros importantes de JVM, que pueden usarse para ajustar y mejorar el rendimiento general de la aplicación.

Algunos de estos también se pueden utilizar con fines de depuración.

Si desea explorar los parámetros de referencia con más detalle, puede comenzar aquí.