DEV Community

Amit Ranjan
Amit Ranjan

Posted on

Analyzing JVM Memory Usage Inside a Docker Container

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:

  1. Heap Memory – Used for object allocation and garbage collection.
  2. Metaspace (non-heap) – Stores class metadata.
  3. Code Cache – Holds compiled bytecode generated by the Just-In-Time (JIT) compiler.
  4. Thread Stacks – Memory allocated per thread for execution stacks.
  5. Off-heap Allocations – Memory allocated directly outside the heap.
  6. Native Memory (JVM & Libraries) – Memory consumed by the JVM itself and linked native libraries.
  7. 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
Enter fullscreen mode Exit fullscreen mode

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)