Skip to content

Language management interface

Eclipse OpenJ9™ provides MXBean extensions to the standard java.lang.management API, which can be used to monitor and manage the Java™ virtual machine. These extensions provide access to information about the state of the OpenJ9 VM and the environment in which it is running. The following tables list the MXBeans by package and describe the monitoring or management capabilities.

Package: com.ibm.lang.management

MXBean Description
GarbageCollectorMXBean Discovers Garbage Collection (GC) operations (collection times, compactions, heap memory usage, and freed memory).
JvmCpuMonitorMXBean Discovers CPU consumption by category (GC, JIT, or other threads).
MemoryMXBean Discovers memory usage (minimum and maximum heap sizes, and shared classes cache sizes).
MemoryPoolMXBean Discovers memory pool usage for specific GC policies.
OperatingSystemMXBean Discovers information about the operating system (memory, CPU capacity/utilization).
RuntimeMXBean Discovers information about the runtime environment (CPU load, Java process ID, and VM state)
ThreadMXBean Discovers information about native thread IDs.
UnixOperatingSystemMXBean Discovers information for Unix operating systems (memory, file descriptors, processors, processor usage, and hardware)

Package: com.ibm.virtualization.management

MXBean Description
GuestOSMXBean Discovers CPU and memory statistics of a virtual machine or logical partition as seen by the Hypervisor.
HypervisorMXBean Discovers whether the operating system is running on a hypervisor and provides information about the hypervisor.

Package: openj9.lang.management

MXBean Description
OpenJ9DiagnosticsMXBean Configures and dynamically triggers dump agents.

For more information about using these MXBeans, read the API documentation. For Java 8, see the OpenJ9 Language Management API documentation.

ThreadMXBean and locked synchronizers

Note: From the 0.60.0 release onwards, querying locked synchronizer information triggers a global garbage collection (GC) with compaction. Review this section before using lockedSynchronizers=true in any regularly scheduled monitoring loop.

The VM tracks object-monitor locks (traditional synchronized blocks) natively for deadlock detection. But for deadlock detection that involves java.util.concurrent locks, such as ReentrantLock, the VM's built-in deadlock detector,findDeadlockedThreads(), needs to know which thread owns a ReentrantLock and which threads are waiting for it. This information is available in the locked-sychronizer list. Without the locked-synchronizer list, it can detect deadlocks only in synchronized blocks. The detector would silently miss any deadlock that is built on AbstractOwnableSynchronizer subclasses.

java.lang.management.ThreadMXBean provides runtime thread information, such as state, stack trace, CPU time, and lock contention. Two of its methods accept a lockedSynchronizers boolean parameter.

  • ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers)
  • ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers)

Either of these methods can be used to retrieve the set of java.util.concurrent.locks.AbstractOwnableSynchronizer objects locked by each thread. These methods are useful for deadlock analysis and diagnostic thread dumps.

Behavior change in the 0.60.0 release

Before the 0.60.0 release, OpenJ9 maintained a locked-sychronizer list continuously during GC cycles. Calling these methods with lockedSynchronizers=true was inexpensive because the list was always current.

Starting with the 0.60.0 release, the continuously maintained list is no longer kept. This change improves correctness. With the previous approach, it was difficult to keep the list consistent across all GC policies and concurrent GC phases. Now the list is rebuilt on demand each time the locked-synchronizer information is requested for.

Rebuilding the list requires a walkable heap, a heap in which every live object on the Java heap is reachable and iterable in a single sequential pass. If the heap is not already in a walkable state when lockedSynchronizers=true is requested, OpenJ9 triggers a global stop-the-world (STW) GC with compaction, where compaction is the physical movement of all live objects together into one contiguous block of memory, eliminating the gaps left behind by objects that were collected. Every call to getThreadInfo(ids, lockedMonitors, true) or dumpAllThreads(lockedMonitors, true) might therefore trigger a compacting STW GC pause.

API usage and GC impact

You can choose the appropriate ThreadMXBean variant based on what information you need:

Information needed API to use GC impact
Thread IDs only ThreadMXBean.getAllThreadIds() None
Thread state, no stack ThreadMXBean.getThreadInfo(long id) None
Thread state and bounded stack ThreadMXBean.getThreadInfo(long[] ids, int maxDepth) None
Thread state, stack and locked monitors (no synchronizers) ThreadMXBean.getThreadInfo(long[] ids, true, false) None
Locked synchronizers for diagnostic use ThreadMXBean.getThreadInfo(long[] ids, boolean, true) or dumpAllThreads(boolean, true) Global GC with compaction

Note: ThreadMXBean.findDeadlockedThreads() detects deadlocks that involve java.util.concurrent locks and does not trigger a GC. Use this method for routine deadlock detection instead of querying locked synchronizers.

Guidance for monitoring and APM tools

If your monitoring tool (for example, IBM HealthCenter, OMEGAMON, or a custom APM agent) calls getThreadInfo or dumpAllThreads, apply the following guidance:

  • Audit every call to getThreadInfo and dumpAllThreads and check whether lockedSynchronizers is true. If the call does not explicitly need ownable-synchronizer data, pass false instead.
  • Avoid using lockedSynchronizers=true in high-frequency polling loops. Treat it as a diagnostic operation with a cost comparable to heap dump generation.
  • Use findDeadlockedThreads() for deadlock detection instead.
  • Expect a GC pause whenever lockedSynchronizers=true is used. On IBM z/OS, elevated zIIP CPU utilization is also expected during compaction.

Diagnostic confirmation

To confirm whether a GC pause was caused by a getLockedSynchronizers call, enable verbose GC logging (-verbose:gc) and look for reason="rasdump" in the output. For more information about verbose GC log output, see Verbose GC log examples.