Mi informacion de contacto
Correo[email protected]
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
El formato de configuración de parámetros JVM del programa Spring Boot (el inicio de Tomcat se agrega directamente al archivo catalina.sh en el directorio bin):
java -Xms2048M -Xmx2048M -Xmn1024M -Xss512K -XX:TamañoMetaespacio=256M -XX:TamañoMáximoMetaespacio=256M -jar microservicio-eureka-server.jar
en conclusión:
Cuanto menor sea la configuración -Xss, menor será el valor de recuento, lo que significa que se pueden asignar menos marcos de pila en una pila de subprocesos, pero la cantidad de subprocesos que se pueden abrir será mayor para la JVM en su conjunto.
-Xss: tamaño de pila de cada hilo, predeterminado 1M
-Xms: establece el tamaño inicial disponible del montón, el valor predeterminado es 1/64 de la memoria física
-Xmx: establece el tamaño máximo disponible del montón, el valor predeterminado es 1/4 de la memoria física
-Xmn: tamaño de nueva generación
-XX: NewRatio: el valor predeterminado 2 significa que la nueva generación representa la mitad de la generación anterior y 1/3 de toda la memoria del montón.
-XX: SurvivorRatio: el valor predeterminado 8 significa que un área de superviviente ocupa 1/8 de la memoria de Eden, es decir, 1/10 de la memoria de nueva generación.
Hay dos parámetros JVM sobre metaspace: -XX:MetaspaceSize=N y -XX:MaxMetaspaceSize=N
-XX: MaxMetaspaceSize: establece el tamaño máximo del metaespacio. El valor predeterminado es -1, lo que significa que no hay límite o solo está limitado por el tamaño de la memoria local.
-XX: MetaspaceSize: especifique el umbral inicial para que el metaespacio active Fullgc (no hay un tamaño inicial fijo para el metaespacio), en bytes. El valor predeterminado es aproximadamente 21 M. Cuando se alcance este valor, se activará el gc completo para la descarga de tipos. el recopilador ajustará este valor: si se libera una gran cantidad de espacio, reduzca el valor de forma adecuada; si se libera una pequeña cantidad de espacio, aumente el valor de forma adecuada sin exceder -XX:MaxMetaspaceSize (si está configurado). Esto tiene un significado diferente al parámetro -XX:PermSize en versiones anteriores de jdk. -XX:PermSize representa la capacidad inicial de la generación permanente.
Dado que cambiar el tamaño del metaespacio requiere GC completo, esta es una operación muy costosa. Si se produce una gran cantidad de GC completo cuando se inicia la aplicación, generalmente se debe al cambio de tamaño de la generación permanente o metaespacio. generalmente se recomienda En los parámetros de JVM, establezca MetaspaceSize y MaxMetaspaceSize en el mismo valor y configúrelos en un valor mayor que el valor inicial. Para una máquina con memoria física de 8G, generalmente configuro ambos valores en 256M.
En la máquina virtual HotSpot, el diseño de los objetos almacenados en la memoria se puede dividir en tres áreas: encabezado del objeto (Encabezado), datos de instancia (Datos de instancia) y relleno de alineación (Relleno). El encabezado del objeto de la máquina virtual HotSpot incluye dos partes de información. La primera parte se utiliza para almacenar los datos de tiempo de ejecución del objeto en sí, como el código hash (HashCode), la edad de generación del GC, el indicador de estado del bloqueo y el bloqueo retenido por el hilo. , ID de hilo sesgado, marcas de tiempo favoritas, etc. La otra parte del encabezado del objeto es el puntero de tipo, que es el puntero del objeto a los metadatos de su clase. La máquina virtual usa este puntero para determinar de qué clase es una instancia el objeto.
1. El uso de punteros de 32 bits (el almacenamiento real usa 64 bits) en HotSpot en una plataforma de 64 bits utilizará aproximadamente 1,5 veces más memoria. El uso de punteros más grandes para mover datos entre la memoria principal y el caché ocupa un ancho de banda mayor. Al mismo tiempo, GC también estará bajo mayor presión.
2. Para reducir el consumo de memoria en plataformas de 64 bits, habilite la función de compresión de puntero
3. En jvm, las direcciones de 32 bits admiten hasta 4G de memoria (2 elevado a 32), que se puede optimizar comprimiendo y codificando el puntero del objeto cuando se almacena en la memoria del montón y decodificando después de sacarlo. al registro de la CPU (el puntero del objeto está en el montón. Tiene 32 bits, 35 bits en el registro, 2 elevado a 35 = 32G), lo que permite que jvm admita configuraciones de memoria más grandes (menor o igual a 32G) usando solo direcciones de 32 bits
4. Cuando la memoria del montón es inferior a 4G, no es necesario habilitar la compresión del puntero. La jvm eliminará directamente la dirección alta de 32 bits, es decir, utilizará el espacio de direcciones virtuales bajo.
5. Cuando la memoria del montón es mayor que 32G, el puntero de compresión dejará de ser válido y se forzará a 64 bits (es decir, 8 bytes) para direccionar el objeto Java. Esto causará el problema de 1, por lo que es mejor no tenerlo. la memoria del montón es superior a 32G.
En este caso, la JVM puede optimizar la ubicación de asignación de memoria del objeto activando el parámetro de análisis de escape (-XX: + DoEscapeAnalysis), de modo que se asigne primero en la pila mediante reemplazo escalar (la asignación en la pila es el análisis de escape). activado de forma predeterminada después de JDK7. Si desea desactivarlo mediante parámetros (-XX:-DoEscapeAnalysis).
Reemplazo escalar: cuando se determina mediante el análisis de escape que no se accederá al objeto externamente y que el objeto se puede descomponer aún más, la JVM no creará el objeto, pero descompondrá las variables miembro del objeto en varias variables miembro utilizadas por este método y reemplácelas. Estas variables miembro de reemplazo asignan espacio en el marco de la pila o en el registro, de modo que no haya una asignación de memoria insuficiente para el objeto porque no hay un gran espacio contiguo. Habilite los parámetros de reemplazo escalar (-XX:+EliminateAllocations), que está habilitado de forma predeterminada después de JDK7.
Cantidades escalares y agregadas: un escalar es una cantidad que no se puede descomponer más, y el tipo de datos básico de JAVA es un escalar (como int, long y otros tipos de datos básicos y tipos de referencia, etc.). es una cantidad que se puede descomponer aún más y esta cantidad se denomina cantidad de polimerización. En JAVA, los objetos son agregados que pueden descomponerse aún más.
Los objetos grandes son objetos que requieren una gran cantidad de espacio de memoria continuo (como cadenas y matrices). Parámetro JVM -XX: PretenureSizeThreshold puede establecer el tamaño de objetos grandes. Si el objeto excede el tamaño establecido, ingresará directamente a la generación anterior y no ingresará a la generación joven. Este parámetro solo es válido en los dos recopiladores Serial y ParNew.
Por ejemplo, configure los parámetros de JVM: -XX:PretenureSizeThreshold=1000000 (la unidad es bytes) -XX:+UseSerialGC Si ejecuta el primer programa anterior, encontrará que el objeto grande ingresa directamente a la generación anterior.
¿Por qué tiene que ser así?
Para evitar operaciones de copia al asignar memoria para objetos grandes y reducir la eficiencia.
En el área de Survivor donde se coloca actualmente el objeto (una de las áreas, el área s donde se coloca el objeto), el tamaño total de un lote de objetos es mayor que el 50% del tamaño de la memoria de esta área de Survivor (-XX :Se puede especificar TargetSurvivorRatio), entonces en este momento es mayor que Los objetos que son iguales a la edad máxima de este lote de objetos pueden ingresar directamente a la antigüedad. Por ejemplo, hay un lote de objetos en el área Survivor. La suma de múltiples objetos de edad con edad 1 + edad 2 + edad n excede el 50% del área de Superviviente. En este momento, todos los objetos con edad n (inclusive) y superiores se colocarán en la generación anterior. En realidad, esta regla espera que los objetos que pueden sobrevivir durante mucho tiempo entren en la vejez lo antes posible. El mecanismo de determinación de edad dinámica del objeto generalmente se activa después de un gc menor.
Antes de cada gc menor en la generación joven, la JVM calculará el espacio libre restante en la generación anterior.
Si el espacio disponible es menor que la suma de los tamaños de todos los objetos existentes en la generación joven (incluidos los objetos basura)
Verificará si el parámetro "-XX:-HandlePromotionFailure" (establecido de forma predeterminada en jdk1.8) está configurado.
Si este parámetro está presente, verificará si el tamaño de memoria disponible en la generación anterior es mayor que el tamaño promedio de los objetos que ingresaron a la generación anterior después de cada gc menor anterior.
Si el resultado del paso anterior es menor o los parámetros mencionados anteriormente no están configurados, se activará un gc completo y se reunirán la generación anterior y la generación joven si aún no hay suficiente espacio para almacenar la nueva. objetos después del reciclaje, se producirá "OOM".
Por supuesto, si el tamaño de los objetos supervivientes restantes que deben trasladarse a la generación anterior después del gc menor es aún mayor que el espacio disponible en la generación anterior, también se activará el gc completo después del gc completo, si lo hay. Todavía no hay espacio para los objetos supervivientes después del gc menor, también se producirá "OOM".
Varios cargadores de clases principales de Tomcat:
commonLoader: el cargador de clases más básico de Tomcat puede acceder a las clases en la ruta de carga mediante el propio contenedor de Tomcat y cada aplicación web;
catalinaLoader: el cargador de clases privado del contenedor Tomcat. Las clases en la ruta de carga no son visibles para la aplicación web;
SharedLoader: un cargador de clases compartido por cada aplicación web. Las clases en la ruta de carga son visibles para todas las aplicaciones web, pero no para el contenedor Tomcat;
WebappClassLoader: el cargador de clases privado de cada aplicación web. Las clases en la ruta de carga solo son visibles para la aplicación web actual, como cargar clases relacionadas en un paquete de guerra. Cada aplicación del paquete de guerra tiene su propio WebappClassLoader para lograr un aislamiento mutuo, como un paquete de guerra diferente. Se introducen diferentes versiones de resortes para que la implementación pueda cargar sus respectivas versiones de resortes.