OutOfMemoryError in Java
OutOfMemoryError (OOME) is a runtime error thrown when the Java Virtual Machine cannot allocate an object because it is out of memory and no more memory could be made available by the garbage collector.
Common causes
- Heap exhaustion: too many objects or very large objects exceed the JVM heap (-Xmx).
- PermGen/Metaspace exhaustion: too many or too-large class metadata (PermGen in older JVMs, Metaspace in newer) due to excessive dynamic class loading.
- Native memory shortage: insufficient native memory for JNI, direct ByteBuffers, thread stacks, or JVM internals.
- Memory leak: long-lived references (static collections, caches) prevent garbage collection.
- Excessive thread creation: each thread consumes stack/native memory; many threads can exhaust memory.
- Large temporary allocations: creating huge arrays or concatenating strings can spike memory use.
Typical symptoms / error messages
- java.lang.OutOfMemoryError: Java heap space
- java.lang.OutOfMemoryError: Metaspace (or PermGen)
- java.lang.OutOfMemoryError: Direct buffer memory
- java.lang.OutOfMemoryError: GC overhead limit exceeded
Diagnosis steps
- Check JVM options: confirm -Xmx, -Xms, -XX:MaxMetaspaceSize, -Xss settings.
- Enable GC logging: e.g., -Xlog:gc* (JDK9+) or -verbose:gc and -XX:+PrintGCDetails.
- Capture heap dump on OOME: -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/path.
- Analyze heap dump: use Eclipse MAT, VisualVM, or YourKit to find largest objects and retained paths.
- Profile memory: run profiler to identify leaks and allocation hotspots.
- Inspect thread count / native usage: jstack, ps, pmap, lsof for native allocations and thread stacks.
Remediation strategies
- Fix leaks: remove unnecessary strong references, use weak/soft references or caches with eviction.
- Tune JVM memory: increase -Xmx, -Xms, or Metaspace if appropriate and host has capacity.
- Reduce memory footprint: optimize data structures, use primitives, stream/process large data in chunks.
- Limit concurrency: reduce thread count or use thread pools to cap parallelism.
- Use off-heap storage carefully: for large buffers prefer pooled direct buffers and monitor Direct buffer memory.
- Improve GC: choose a GC algorithm suited to workload (G1, ZGC, Shenandoah) and tune GC flags.
- Avoid loading many classes dynamically or ensure proper classloader cleanup.
Top comments (0)