Jeff Mesnil
Weblog · Dev · Photos · Books

jmx4r, a JMX Libary for JRuby

June 11, 2007

Just in time for the release of JRuby 1.0 and following my experiments with writing JRuby scripts to manage remote applications using JMX (part I & II), I created jmx4r, a simple library which makes it super easy to write such scripts.

For example, to trigger a Garbage Collection on a remote Java application , the whole script is:

require 'java'
require 'jmx4r'    

memory = JMX::MBean.find_by_name "java.lang:type=Memory"
memory.verbose = true
memory.gc

Simple enough, isn't it?

JMX Connection

By default, jmx4r expects to connect to the remote MBean Server on localhost using the standard JMX Service URL. Otherwise, it is possible to set the host and port of the remote MBean Server:

JMX::MBean.establish_connection :host => "localhost", :port => 3000

Attributes & Operations naming convention

JMX attributes are available on the JRuby objects but their names are changed to be snake_cased instead of CamelCased.
For example, the LoadedClassCount attribute of the java.lang:type=ClassLoading MBean is available as the loaded_class_count attribute on the corresponding JRuby object.

Ditto for the operations:

logging = JMX::MBean.find_by_name "java.util.logging:type=Logging"
logging.logger_names.each do |logger_name|
    logging.set_logger_level logger_name, "INFO"
end

The set_logger_level method corresponds to the setLoggerLevel MBean operations.

Features List

For now, the features of jmx4r are:

  • read MBean attributes:
memory = JMX::MBean.find_by_name "java.lang:type=Memory"
puts "verbose : #{memory.verbose}"
  • write MBean attributes (provided they are writable):
memory = JMX::MBean.find_by_name "java.lang:type=Memory"
memory.verbose != memory.verbose
  • invoke MBean operations (provided the parameters types are simple):
memory = JMX::MBean.find_by_name "java.lang:type=Memory"
memory.gc

logging = JMX::MBean.find_by_name "java.util.logging:type=Logging"
logging.set_logger_level "global", "INFO"
  • query for MBeans:
memory_pools = JMX::MBean.find_all_by_name "java.lang:type=MemoryPool,*"
memory_pools.each { |mem_pool| puts mem_pool.name }
  • get the ObjectName correponding to a MBean:

memory_pools = JMX::MBean.find_all_by_name "java.lang:type=MemoryPool,*"
memory_pools.each { |mem_pool| puts mem_pool.object_name }

Next steps are:

  • provide comprehensive tests
  • document the library
  • make a gem to simplify its deployment