How to Manage Java Applications from the Terminal with Jmxterm
Monitoring and managing Java applications often involves graphical tools like JConsole or VisualVM. However, these tools are not always practical. Production environments frequently run on headless servers without a graphical user interface (GUI). Setting up secure remote desktop access or X11 forwarding just to check a Java Management Extensions (JMX) attribute can be a security and administrative hassle.
This is where Jmxterm becomes invaluable. Jmxterm is an open-source, command-line utility that allows you to interact with JMX MBeans directly from the terminal. It provides an interactive CLI or a scriptable interface, making it perfect for both quick manual checks and automated DevOps workflows.
Here is a comprehensive guide on how to install, configure, and use Jmxterm to manage your Java applications from the command line. Prerequisites To follow along with this guide, you will need:
A Java Development Kit (JDK) or Java Runtime Environment (JRE) installed. A running Java application with JMX ports enabled.
If you need a quick way to enable JMX on a Java application for testing, append the following system properties when starting your application:
java -Dcom.sun.management.jmxremote-Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -jar your-application.jar Use code with caution.
(Note: Disabling authentication and SSL is only recommended for local testing. Always secure production JMX connections with passwords and SSL/TLS). Downloading and Launching Jmxterm
Jmxterm is distributed as an executable JAR file, meaning it requires no formal installation.
Download the JAR: You can download the latest stable release of the jmxterm-X.X.X-uber.jar from its official website or directly via the command line using wget or curl: wget https://github.com -O jmxterm.jar Use code with caution.
Launch Interactive Mode: Open your terminal and run the JAR using java -jar: java -jar jmxterm.jar Use code with caution. You will be greeted by a prompt that looks like this: Welcome to Jmxterm silent mode \(> </code> Use code with caution. Connecting to Your Java Application</p> <p>Jmxterm can connect to local Java processes using their Process ID (PID) or to remote instances via a JMX URL. Connecting Locally via PID</p> <p>To see a list of running Java processes on your local machine, use the <code>jvms</code> command inside Jmxterm: <code>\)> jvms 12345 (your-application.jar) 67890 (jmxterm.jar) Use code with caution.
Once you identify the target PID, connect to it using the open command: \(> open 12345 #Connection to 12345 is opened </code> Use code with caution. Connecting Remotely via JMX URL</p> <p>If your application is running on another server with JMX exposed, connect using the standard JMX Service URL: <code>\)> open localhost:9999 Use code with caution.
If your server requires authentication, pass the credentials using the -u (username) and -p (password) flags: \(> open localhost:9999 -u admin -p secretPassword </code> Use code with caution. Exploring MBeans and Domains</p> <p>JMX organizes management objects into <strong>Domains</strong>, which contain individual <strong>MBeans</strong> (Managed Beans). 1. List Available Domains</p> <p>To see which frameworks and subsystems are exposing data, list the domains:</p> <p><code>\)> domains #following domains are available Catalina java.lang java.util.logging JMImplementation Use code with caution. 2. Select a Domain Set your active domain using the domain command: \(> domain java.lang #domain is set to java.lang </code> Use code with caution. 3. List MBeans within the Domain</p> <p>Now, view the specific MBeans available inside the <code>java.lang</code> domain:</p> <p><code>\)> beans #following beans are available java.lang:type=ClassLoading java.lang:type=Compilation java.lang:type=GarbageCollector,name=G1 Young Generation java.lang:type=Memory java.lang:type=Runtime java.lang:type=Threading Use code with caution. 4. Select a Target Bean
To interact with a specific bean, lock it in focus using the bean command:
\(> bean java.lang:type=Memory #bean is set to java.lang:type=Memory </code> Use code with caution. Inspecting and Modifying Attributes</p> <p>Once an MBean is selected, you can query its attributes (variables) or modify them if they are writable. View Available Attributes</p> <p>Run the <code>info</code> command to see the selected bean's attributes, operations, and notifications:</p> <p><code>\)> info # attributes %0 - HeapMemoryUsage (javax.management.openmbean.CompositeData, r) %1 - NonHeapMemoryUsage (javax.management.openmbean.CompositeData, r) %2 - ObjectPendingFinalizationCount (int, r) %3 - Verbose (boolean, rw) Use code with caution. (Note: r means read-only, rw means read-write). Get an Attribute Value To check the current value of an attribute, use get: \(> get Verbose #value of Verbose = false; </code> Use code with caution.</p> <p>For complex data types like <code>HeapMemoryUsage</code> (which returns a CompositeData object), Jmxterm elegantly formats the nested properties:</p> <p><code>\)> get HeapMemoryUsage #value of HeapMemoryUsage = { committed = 268435456; init = 268435456; max = 4294967296; used = 54321048; }; Use code with caution. Set an Attribute Value
If an attribute is marked as rw, you can change it on the fly using set: \(> set Verbose true #value of Verbose is set to true </code> Use code with caution. Executing JMX Operations</p> <p>MBeans often expose operations—essentially methods you can call to trigger actions like forcing garbage collection, rotating logs, or resetting statistics.</p> <p>To run an operation, use the <code>run</code> command followed by the operation name. For example, to trigger a manual Garbage Collection, switch to the <code>Memory</code> bean and execute <code>gc</code>:</p> <p><code>\)> bean java.lang:type=Memory \(> run gc #operation returns value is null </code> Use code with caution.</p> <p>If an operation requires arguments, pass them sequentially after the method name:</p> <p><code>\)> bean java.util.logging:type=Logging $> run setLoggerLevel MyLoggerName INFO Use code with caution. Automating with Scripting and Non-Interactive Mode
One of Jmxterm’s greatest strengths is its ability to bypass the interactive prompt completely. This allows you to embed JMX queries into bash scripts, cron jobs, or monitoring alerts. 1. Piping Commands via Standard Input (stdin) You can pipe a string of commands directly into Jmxterm:
echo “open localhost:9999 get -b java.lang:type=Memory HeapMemoryUsage” | java -jar jmxterm.jar -n Use code with caution.
(The -n flag tells Jmxterm not to print the welcome prompt or input symbols). 2. Executing a Script File
Alternatively, write your commands into a text file (e.g., jmx_query.txt):
open localhost:9999 bean java.lang:type=Threading get ThreadCount close Use code with caution. Then, execute the file using the -i flag: java -jar jmxterm.jar -i jmx_query.txt Use code with caution.
This scriptable approach makes it trivial to write a bash script that periodically logs JVM memory usage, checks thread counts, or restarts internal application services via JMX. Conclusion
Jmxterm bridges the gap between powerful JMX instrumentation and the constraints of a Linux terminal. By eliminating the dependency on GUI applications, it empowers system administrators and DevOps engineers to inspect, fine-tune, and automate Java applications directly from the command line. Whether you are debugging a live memory leak on a production server or building a custom monitoring script, Jmxterm belongs in every Java developer’s terminal toolkit. If you’d like to dive deeper, let me know:
What specific Java application (e.g., Tomcat, Kafka, Spring Boot) you are managing.
If you need help writing a custom automated bash script for your setup.
If you need guidance on configuring secure SSL/TLS JMX connections.
Leave a Reply