| Pods restart with exit code 137 and the heap is not full | The container memory limit against the heap setting (-Xmx or MaxRAMPercentage), then everything outside the heap. We switch on Native Memory Tracking and read jcmd VM.native_memory, then count threads (stack size times threads), direct buffers, metaspace and the code cache. An OutOfMemoryError never appears because the kernel, not the JVM, ended the process. | Heap as a percentage of the limit with headroom, and caps on threads and direct memory |
|---|
| java.lang.OutOfMemoryError: Java heap space | A heap dump taken at the failure (-XX:+HeapDumpOnOutOfMemoryError), read by retained size to see what holds the memory. We separate a leak that grows without bound from a heap that is too small for the working set and from one request that loads far too much. | Fix the retaining reference or the query, or size the heap to the working set |
|---|
| OutOfMemoryError: Metaspace after redeploys | Class loader statistics from jcmd and the class count over time. On application servers and hot-redeploy setups the usual cause is an old class loader kept alive by a thread, a driver registration or a static cache, so each redeploy leaks the whole application's classes. | Remove the reference that pins the old loader, then set a metaspace cap |
|---|
| Latency spikes and long garbage collection pauses | GC logs (-Xlog:gc* on JDK 9 and later, -XX:+PrintGCDetails on Java 8) lined up against request latency. We compare pause length with allocation rate and look for humongous allocations on G1. We also check which collector the JVM actually picked, since Java 8 defaults to Parallel and JDK 9 and later to G1. | Heap and region sizing, or a change of collector |
|---|
| The JVM dies with a fatal error and an hs_err_pid file | The crashing frame in hs_err_pid: native library, JIT-compiled code or the JVM itself, plus the signal, the loaded libraries and the operating system and glibc level. A crash inside a JNI library points at that library; a crash in compiled code points at a JDK defect. | Native library update, or a JDK update or compiler workaround |
|---|
| SSLHandshakeException or PKIX path building failed after a JDK change | Which truststore the process really loads. A new JDK ships its own cacerts, so certificates imported into the old one are gone, and newer updates disable older protocols and algorithms through jdk.tls.disabledAlgorithms. We trace with -Djavax.net.debug=ssl:handshake. | Import the certificate into the right truststore, or update the peer that offers a disabled protocol |
|---|
| Startup fails after 8 to 17: InaccessibleObjectException or ClassNotFoundException for javax.xml.bind | Whether the failure is strong encapsulation or a removed module. JDK 17 denies reflective access to JDK internals that Java 8 allowed, and JAXB, JAX-WS and other Java EE modules left the JDK in 11. The stack trace names the package or class, and the dependency tree shows who needs it. | Upgrade the library, add the dependency, or --add-opens as a stopgap |
|---|
| High CPU with the application idle, or one core pegged | Repeated thread dumps (jcmd Thread.print) to separate application threads from GC and JIT compiler threads, then the container CPU quota against what availableProcessors reports. A runaway loop, a collector with too many threads for the quota and compilation churn look the same in top. | Fix the loop, or set the CPU count and GC threads to match the quota |
|---|