This article describes the steps required to analyze memory usage of a Java application running inside a Docker container. Although some AWS-specific references are included, the procedure is cloud-agnostic and applicable to any environment where Docker containers are deployed.
JVM Memory Categories
The Java Virtual Machine (JVM) allocates memory across several distinct areas. The following categories are commonly analyzed when troubleshooting or profiling memory usage:
- Heap Memory – Used for object allocation and garbage collection.
- Metaspace (non-heap) – Stores class metadata.
- Code Cache – Holds compiled bytecode generated by the Just-In-Time (JIT) compiler.
- Thread Stacks – Memory allocated per thread for execution stacks.
- Off-heap Allocations – Memory allocated directly outside the heap.
- Native Memory (JVM & Libraries) – Memory consumed by the JVM itself and linked native libraries.
- JVM Overhead & Internal Allocations – Additional memory reserved for internal operations.
Step 1: Connect to the Host
Since the application is running in a Docker container, access to the host system is required. For example, on AWS EC2:
ssh @
Step 2: Check Container Memory Usage
Once logged into the host, run the following command to monitor memory consumption at the container level:
docker stats
This command outputs memory usage, CPU utilization, and other runtime statistics. The container ID of the application will also be displayed.
Step 3: Access the Container
To interact directly with the application inside the container, open an interactive shell:
docker exec -it /bin/bash
This session enables execution of commands as if they were run directly within the container environment.
Step 4: Identify JVM Process
Inside the container, use the jcmd utility to list Java processes and their corresponding process IDs (PIDs):
jcmd
Typically, the application will be associated with a single PID.
Step 5: Analyze JVM Memory
5.1 Heap Memory Information
jcmd GC.heap_info
This command provides details regarding:
1. Maximum heap size
2. Committed memory
3. Currently used memory
5.2 Native Memory Summary
jcmd VM.native_memory summary
This command generates a detailed breakdown of native memory usage, which is particularly valuable for analyzing allocations outside the heap.
Step 6: Enable Native Memory Tracking (if required)
If native memory tracking is not enabled, the above command may return an error. To enable it, configure the JVM with the following option:
{"name": "JAVA_TOOL_OPTIONS", "value": "-XX:NativeMemoryTracking=summary"}
This setting enables summary-level tracking of native memory allocations.
By following these steps, developers can accurately profile heap, non-heap, and native memory usage of Java applications running inside Docker containers, thereby gaining insights into performance and potential memory-related issues.
Top comments (0)