Files
awesome-kubernetes/docs/java-and-java-performance-optimization.md
Inaki Fernandez 2f234a2448 update
2020-06-04 17:31:01 +02:00

18 KiB
Raw Blame History

Java and Memory Management

Java

Existing Java Implementations

Use Java 11

Java Programming Models (Java Frameworks)

  • Best Java Frameworks Solutions The best Java Frameworks vendors are Apache Spark, Spring Boot, Oracle Application Development Framework (Oracle ADF), Jakarta EE, and Open Liberty. Apache is the top solution according to IT Central Station reviews and rankings. One reviewer writes: "Fast performance and has an easy initial setup", and another reviewer writes: "Easy to use and is capable of processing large amounts of data". The 2nd best product is Spring Boot. A user writes: "Very smooth implementation; excellent features for monitoring and tracking network calls ", and another reviewer writes: "Makes it difficult to support a specific functionality in a user-friendly manner, but simplifies application deployment".
Framework / Java Ecosystem Technology Cloud Native Platform
Java EE
Java EE at a Glance
Frontend + Backend
Java EE Monoliths
No Java EE Middleware Servers (WAS, WebLogic, JBoss EAP, etc)
Jakarta EE (Java EE renamed) Frontend + Backend Yes OpenShift, Kubernetes, etc
MicroProfile Frontend+Backend Yes OpenShift, Kubernetes, etc
SpringBoot (Spring) Backend (RESTful) Yes OpenShift, Kubernetes, etc
Spring Cloud (Spring) Backend (RESTful) Yes OpenShift, Kubernetes, etc
Quarkus Backend (RESTful) Yes OpenShift, Kubernetes, etc
etc

Spring and MicroProfile frameworks for microservices development (open source microservices frameworks)

Spring
Eclipse MicroProfile Project
  • Eclipse MicroProfile Project The Eclipse MicroProfile project is aimed at optimizing Enterprise Java for the microservices architecture.
    • Many innovative "microservice" Enterprise Java environments and frameworks already exist in the Java ecosystem. These projects are creating new features and capabilities to address microservice architectures -- leveraging both Java EE and non-Java EE technologies.
    • The goal of the Eclipse MicroProfile project is to iterate and innovate in short cycles to propose new common APIs and functionality, get community approval, release, and repeat. Eventually, the outputs of this project could be submitted to the Eclipse Jakarta EE, JCP, OpenJDK or any relevant standards body.
  • MicroProfile.io Optimizing Enterprise Java for a Microservices Architecture
  • developers.redhat.com: Eclipse MicroProfile for Spring Boot developers
Spring Boot VS MicroProfile

Java Performance Optimization

Relevant JVM Metrics

Metric Details / Reference
GC Throughput Repeated Full GC happens way before OutOfMemoryError
ref1
ref2
etc

Common JVM Errors

JVM Error Details / Reference
OutOfMemoryError Repeated Full GC happens way before OutOfMemoryError
ref1
ref2
StackOverflowError ref
etc

Tuning Jenkins GC

Tuning Java Containers

Debugging java applications on OpenShift and Kubernetes

List of Performance Analysis Tools

Threadumps, Heapdumps and GC Analysis Tools

Capturing a Java Thread Dump

Garbage Collection and Heap Offloading

Cambios importantes en la gestión de memoria de Java 8 de Oracle (2014)

PermGen no pertenece al heap y los objetos no son promocionados a esta sección de memoria gestionada durante un GC. Como bien dices es un espacio contiguo al heap, pero también se limpia cada vez que la tenured/old generation procede a un GC. No es una generación separada del mismo modo que es la young generation, y no hay un mecanismo específico para un GC separado de PermGen. La tenured/old generation y la permanent generation proceden a un GC cuando una de las dos se llena.

De todos modos no me queda claro si incorporaron PermGen dentro del heap en Java 7, aunque poco importa ya con los cambios en Java 8.

Mejor empiezo por introducir qué implementación de JVM es Java 8 de Oracle. Existen numerosas implementaciones de JVM y cada una utiliza diferentes soluciones para la gestión de memoria.

Dos de las soluciones más conocidas y populares de JVM han sido HotSpot de Sun (habitual en Tomcat) y JRockit de BEA (Weblogic). Ambas compañias fueron compradas por Oracle y Java 8 viene a ser la integración definitiva de ambas soluciones.

Históricamente se consideraba que HotSpot es el JVM con mejor rendimiento de las dos, si bien JRockit es valorada como la más escalable.

Originalmente en HotSpot no había generación permanente. Objetos y clases de JVM se almacenaban juntas. Las clases de ésta JVM eran estáticas y prácticamente no se utilizaban 'Class Loaders' (Load y Unload/Collection de Clases). PermGen surgió como una mejora de rendimiento. Por defecto los datos en la generación permanente no se eliminan nunca (son datos de JVM y no de aplicación, pudiendo variar según la pólítica de garbage collection). Esto podía llenar la generación permanente generando un OutOfMemoryErrors si se producía un elevado número de classloading. En muchos casos un problema con una generación permanente implica reiniciar regularmente la JVM y la aplicación Java.

Actualmente las clases de JVM son dinámicas y el espacio requerido para metadatos puede cambiar fácilmente.

A diferencia de HotSpot VM, JRockit carece de generación permanente y en cambio almacena los metadatos 'off the heap' en memoria nativa. Estos buffers de código son liberados constantemente cuando sus ClassLoaders no se utilizan. El problema de OutOfMemory en JRockit no es diferente a HotSpot, excepto por el hecho de ser memoria nativa en lugar de memoria heap. Hay dos diferencias significativas. Primero, en JRockit la limpieza de metadatos está habilitada siempre por defecto y segundo, no hay tamaño límite fijo para el espacio de metadatos. Uno de los principales problemas con HotSpot es su dificultad para seleccionar un tamaño adecuado para la generación permanente. ¿128MB, 256MB? Es muy difícil acertar para cada aplicación. JRockit es dinámico en la gestión de memoria reservada para metadatos y sin límites de tamaño (a excepción de la memoria del sistema). JRockit es también el único JVM con soporte de heaps no contiguos (uso de memoria por encima y por debajo del alojamiento del kernel y otras librerías), importante en el caso de Windows donde su kernel a menudo se ubica en mitad del espacio de direcciones.

Java 8 (HotRockit?) incorpora todas las herramientas de monitorización de HotSpot (Java VisualVM, jstat, jmap) y JRockit (Java Mission Control, Java Flight Recorder). Muy interesante.

Un inconveniente de Java 8 es la fragmentación de la memoria nativa para metadatos, pero probablemente incluya compactación en un futuro próximo.

En el 2016 saldrá Java 9 con la funcionalidad de auto-tuning y soporte de tamaños Heap multi-gigas.

En cualquier caso hay una tendencia al Heap-Offloading. El consumo de memoria en Java tiene un coste y las pausas/latencias causadas por los Full GC son proporcionales al tamaño del heap. Estas pausas son notables en tamaños de heap > 1Gb, con un considerable impacto en aplicaciones de tiempo real donde un proceso que no responde rápido puede ser descartado del cluster. Aún así, los servidores actuales hacen uso de frameworks muy pesados y fácilmente requieren heaps > 4Gb. Una solución a este problema es alojar fuera del heap los objetos poco utilizados mediante técnicas de serialización/deserialización (caché). El heap de memoria se mantiene pequeño y el Full GC se completa en milisegundos. Ejemplos:

  1. caché de sesión de usuarios, donde un fichero mapeado en memoria almacena gigabytes de sesiones de usuarios inactivos. Una vez que el usuario hace log-in, la aplicación dispone de todos sus datos sin ser necesaria una consulta a la BBDD.
  2. caché de resultados computacionales como queries, páginas html, etc (donde el coste computacional es mayor a la deserialización)