blob: 97d53a6dc00d13799580daa8caffcd603be57de7 [file] [log] [blame]
<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
<title>Chapter&nbsp;14.&nbsp;Java Management Extensions (JMX)</title><link rel="stylesheet" type="text/css" href="css/docbook.css"><meta name="generator" content="DocBook XSL Stylesheets V1.79.1"><meta name="keywords" content="jetty, servlet, servlet-api, cometd, http, websocket, eclipse, maven, java, server, software"><link rel="home" href="index.html" title="Jetty"><link rel="up" href="jetty-admin-guide.html" title="Part&nbsp;III.&nbsp;Jetty Administration Guide"><link rel="prev" href="using-annotations-embedded.html" title="Using Annotations with Jetty Embedded"><link rel="next" href="jetty-jmx-annotations.html" title="Jetty JMX Annotations"><link xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" rel="shortcut icon" href="images/favicon.ico"><link rel="stylesheet" href="css/highlighter/foundation.css"><script src="js/highlight.pack.js"></script><script>
hljs.initHighlightingOnLoad();
</script><link type="text/css" rel="stylesheet" href="css/font-awesome/font-awesome.min.css"></head><body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF"><table xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><tr><td style="width: 25%"><a href="http://www.eclipse.org/jetty"><img src="images/jetty-header-logo.png" alt="Jetty Logo"></a><br><span style="font-size: small">
Version: 9.4.28-SNAPSHOT</span></td><td style="width: 50%"></td></tr></table><div xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" class="navheader"><table width="100%" summary="Navigation header"><tr><th colspan="3" align="center">Chapter&nbsp;14.&nbsp;Java Management Extensions (JMX)</th></tr><tr><td width="20%" align="left"><a accesskey="p" href="using-annotations-embedded.html"><i class="fa fa-chevron-left" aria-hidden="true"></i> Previous</a>&nbsp;</td><th width="60%" align="center">Part&nbsp;III.&nbsp;Jetty Administration Guide<br><a accesskey="p" href="index.html"><i class="fa fa-home" aria-hidden="true"></i> Home</a></th><td width="20%" align="right">&nbsp;<a accesskey="n" href="jetty-jmx-annotations.html">Next <i class="fa fa-chevron-right" aria-hidden="true"></i></a></td></tr></table><hr></div><div xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" class="jetty-callout"><h5 class="callout"><a href="http://www.webtide.com/">Contact the core Jetty developers at
<span class="website">www.webtide.com</span></a></h5><p>
private support for your internal/customer projects ... custom extensions and distributions ... versioned snapshots for indefinite support ...
scalability guidance for your apps and Ajax/Comet projects ... development services for sponsored feature development
</p></div><div class="chapter"><div class="titlepage"><div><div><h2 class="title"><a name="jmx-chapter"></a>Chapter&nbsp;14.&nbsp;Java Management Extensions (JMX)</h2></div></div></div><div class="toc"><p><b>Table of Contents</b></p><dl class="toc"><dt><span class="section"><a href="jmx-chapter.html#using-jmx">Using JMX with Jetty</a></span></dt><dt><span class="section"><a href="jetty-jmx-annotations.html">Jetty JMX Annotations</a></span></dt><dt><span class="section"><a href="jetty-jconsole.html">Managing Jetty with JConsole and JMC</a></span></dt></dl></div><p>The <a class="link" href="http://java.sun.com/products/JavaManagement/" target="_top">Java Management Extensions (JMX) API</a> is a standard API for managing and monitoring resources such as applications, devices, services, and the Java virtual machine.</p><p>Typical uses of the JMX technology include:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Consulting and changing application configuration</li><li class="listitem">Accumulating and making available statistics about application behavior</li><li class="listitem">Notifying of state changes and erroneous conditions</li></ul></div><p>The JMX API includes remote access, so a remote management program can interact with a running application for these purposes.</p><div class="section"><div class="titlepage"><div><div><h2 class="title" style="clear: both"><a name="using-jmx"></a>Using JMX with Jetty</h2></div></div></div><div class="toc"><dl class="toc"><dt><span class="section"><a href="jmx-chapter.html#configuring-jmx">Configuring JMX</a></span></dt><dt><span class="section"><a href="jmx-chapter.html#accessing-jetty-mbeans">Using JConsole or Java Mission Control to Access Jetty MBeans</a></span></dt><dt><span class="section"><a href="jmx-chapter.html#jmx-remote-access">Enabling JMX Remote Access</a></span></dt></dl></div><p>Jetty&#8217;s architecture is based on POJO components (see <a class="xref" href="architecture.html#basic-architecture" title="Jetty Architecture">Jetty Architecture</a>).
These components are organized in a tree and each component may have a lifecycle that spans the <code class="literal">Server</code> lifetime, or a web application lifetime, or even shorter lifetimes such as that of a TCP connection.</p><p>Every time a component is added or removed from the component tree, an event is emitted, and <a class="link" href="http://www.eclipse.org/jetty/javadoc/9.4.28-SNAPSHOT/org/eclipse/jetty/util/component/Container.html" target="_top"><code class="literal">Container.Listener</code></a> implementations can listen to those events and perform additional actions.</p><p>One such <code class="literal">Container.Listener</code> is <code class="literal">MBeanContainer</code> that uses <code class="literal">ObjectMBean</code> to create an MBean from an arbitrary POJO, and register/unregister the MBean to/from the platform <code class="literal">MBeanServer</code>.</p><p>Jetty components are annotated with <a class="xref" href="jetty-jmx-annotations.html" title="Jetty JMX Annotations">Jetty JMX Annotations</a> and provide specific JMX details so that <code class="literal">ObjectMBean</code> can build a more precise representation of the JMX metadata associated with the component POJO.</p><p>Therefore, when a component is added to the component tree, <code class="literal">MBeanContainer</code> is notified, it creates the MBean from the component POJO and registers it to the <code class="literal">MBeanServer</code>.
Similarly, when a component is removed from the tree, <code class="literal">MBeanContainer</code> is notified, and unregisters the MBean from the <code class="literal">MBeanServer</code>.</p><p>The Jetty MBeans can be accessed via any JMX console such as Java Mission Control (JMC), VisualVM, JConsole or others.</p><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="configuring-jmx"></a>Configuring JMX</h3></div></div></div><p>This guide describes the various ways to initialize and configure the Jetty JMX integration.
Configuring the Jetty JMX integration only registers the Jetty MBeans into the platform <code class="literal">MBeanServer</code>, and therefore the MBeans can only be accessed locally (from the same machine), not from remote machines.</p><p>This means that this configuration is enough for development, where you have easy access (with graphical user interface) to the machine where Jetty runs, but it is typically not enough when the machine Jetty where runs is remote, or only accessible via SSH or otherwise without graphical user interface support.
In these cases, you have to enable <a class="link" href="jmx-chapter.html#jmx-remote-access" title="Enabling JMX Remote Access">JMX Remote Access</a>.</p><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="jmx-standalone-jetty"></a>Standalone Jetty Server</h4></div></div></div><p>JMX is not enabled by default in the Jetty distribution.
To enable JMX in the Jetty distribution run the following, where <code class="literal">{$jetty.home}</code> is the directory where you have the Jetty distribution installed, and <code class="literal">${jetty.base}</code> is the directory where you have your Jetty configuration (see <a class="link" href="startup-base-and-home.html" title="Managing Jetty Base and Jetty Home">the documentation for Jetty base vs. home examples</a>):</p><div class="screenexample"><pre class="screen">$ cd ${jetty.base}
$ java -jar {$jetty.home}/start.jar --add-to-start=jmx</pre></div><p>Running the above command will append the available configurable elements of the <code class="literal">jmx</code> module to the <code class="literal">{$jetty.base}/start.ini</code> file, or create the <code class="literal">${jetty.base}/start.d/jmx.ini</code> file.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="jmx-embedded-jetty"></a>Embedded Jetty Server</h4></div></div></div><p>When running Jetty embedded into an application, create and configure an <code class="literal">MBeanContainer</code> instance as follows:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>Server server = new Server();
// Setup JMX.
MBeanContainer mbeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
server.addBean(mbeanContainer);
// Export the loggers as MBeans.
server.addBean(Log.getLog());</code></pre><p>Because logging is initialized prior to the <code class="literal">MBeanContainer</code> (even before the <code class="literal">Server</code> itself), it is necessary to register the logger manually via <code class="literal">server.addBean()</code> so that the loggers may show up in the JMX tree as MBeans.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="jmx-jetty-maven-plugin"></a>Using the Jetty Maven Plugin with JMX</h4></div></div></div><p>If you are using the <a class="link" href="jetty-maven-plugin.html" title="Configuring the Jetty Maven Plugin">Jetty Maven plugin</a> you should copy the <code class="literal">${jetty.home}/etc/jetty-jmx.xml</code> file into your webapp project somewhere, such as <code class="literal">src/main/config/etc/</code>, then add a <code class="literal">&lt;jettyXml&gt;</code> element to the <code class="literal">&lt;configuration&gt;</code> element of the Jetty Maven Plugin:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>&lt;plugin&gt;
&lt;groupid&gt;org.eclipse.jetty&lt;/groupid&gt;
&lt;artifactid&gt;jetty-maven-plugin&lt;/artifactid&gt;
&lt;version&gt;9.4.28-SNAPSHOT&lt;/version&gt;
&lt;configuration&gt;
&lt;scanintervalseconds&gt;10&lt;/scanintervalseconds&gt;
&lt;jettyXml&gt;src/main/config/etc/jetty-jmx.xml&lt;/jettyXml&gt;
&lt;/configuration&gt;
&lt;/plugin&gt;</code></pre></div></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="accessing-jetty-mbeans"></a>Using JConsole or Java Mission Control to Access Jetty MBeans</h3></div></div></div><p>The simplest way to access the MBeans that Jetty publishes is to use <a class="link" href="jetty-jconsole.html" title="Managing Jetty with JConsole and JMC">Java Mission Control (JMC) or JConsole.</a></p><p>Both these tools can connect to local or remote JVMs to display the MBeans.</p><p>For local access, you just need to start JConsole or JMC and then choose from their user interface the local JVM you want to connect to.</p><p>For remote access, you need first to enable JMX Remote Access in Jetty.</p></div><div class="section"><div class="titlepage"><div><div><h3 class="title"><a name="jmx-remote-access"></a>Enabling JMX Remote Access</h3></div></div></div><p>There are two ways of enabling remote connectivity so that JConsole or JMC can connect to the remote JVM to visualize MBeans.</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">Use the <code class="literal">com.sun.management.jmxremote</code> system property on the command line.
Unfortunately, this solution does not work well with firewalls and is not flexible.</li><li class="listitem">Use Jetty&#8217;s <code class="literal">jmx-remote</code> module or - equivalently - the <code class="literal">ConnectorServer</code> class.</li></ul></div><p><code class="literal">ConnectorServer</code> will use by default RMI to allow connection from remote clients,
and it is a wrapper around the standard JDK class <code class="literal">JMXConnectorServer</code>, which is the class that provides remote access to JMX clients.</p><p>Connecting to the remote JVM is a two step process:</p><div class="itemizedlist"><ul class="itemizedlist" style="list-style-type: disc; "><li class="listitem">First, the client will connect to the RMI <span class="emphasis"><em>registry</em></span> to download the RMI stub for the <code class="literal">JMXConnectorServer</code>; this RMI stub contains the IP address and port to connect to the RMI server, i.e. the remote <code class="literal">JMXConnectorServer</code>.</li><li class="listitem">Second, the client uses the RMI stub to connect to the RMI <span class="emphasis"><em>server</em></span> (i.e. the remote <code class="literal">JMXConnectorServer</code>) typically on an address and port that may be different from the RMI registry address and port.</li></ul></div><p>The configuration for the RMI registry and the RMI server is specified by a <code class="literal">JMXServiceURL</code>.
The string format of an RMI <code class="literal">JMXServiceURL</code> is:</p><div class="screenexample"><pre class="screen">service:jmx:rmi://&lt;rmi_server_host&gt;:&lt;rmi_server_port&gt;/jndi/rmi://&lt;rmi_registry_host&gt;:&lt;rmi_registry_port&gt;/jmxrmi</pre></div><p>Default values are:</p><div class="screenexample"><pre class="screen">rmi_server_host = localhost
rmi_server_port = 1099
rmi_registry_host = localhost
rmi_registry_port = 1099</pre></div><p>With the default configuration, only clients that are local to the server machine can connect to the RMI registry and RMI server - this is done for security reasons.
With this configuration it would still be possible to access the MBeans from remote using a <a class="link" href="jmx-chapter.html#jmx-remote-access-ssh-tunnel" title="JMX Remote Access with Port Forwarding via SSH Tunnel">SSH tunnel.</a></p><p>By specifying an appropriate <code class="literal">JMXServiceURL</code>, you can fine tune the network interfaces the RMI registry and the RMI server bind to, and the ports that the RMI registry and the RMI server listen to.
The RMI server and RMI registry hosts and ports can be the same (as in the default configuration) because RMI is able to multiplex traffic arriving to a port to multiple RMI objects.</p><p>If you need to allow JMX remote access through a firewall, you must open both the RMI registry and the RMI server ports.</p><p>Examples:</p><div class="screenexample"><pre class="screen">service:jmx:rmi:///jndi/rmi:///jmxrmi
rmi_server_host = local host address
rmi_server_port = randomly chosen
rmi_registry_host = local host address
rmi_registry_port = 1099
service:jmx:rmi://0.0.0.0:1099/jndi/rmi://0.0.0.0:1099/jmxrmi
rmi_server_host = any address
rmi_server_port = 1099
rmi_registry_host = any address
rmi_registry_port = 1099
service:jmx:rmi://localhost:1100/jndi/rmi://localhost:1099/jmxrmi
rmi_server_host = loopback address
rmi_server_port = 1100
rmi_registry_host = loopback address
rmi_registry_port = 1099</pre></div><div xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times" class="note" style="margin-left: 0.5in; margin-right: 0.5in;"><h3 class="title"><i class="fa fa-asterisk" aria-hidden="true"></i> Note</h3><p>When <code class="literal">ConnectorServer</code> is started, its RMI stub is exported to the RMI registry.
The RMI stub contains the IP address and port to connect to the RMI object, but the IP address is typically the machine host name, not the host specified in the <code class="literal">JMXServiceURL</code>.</p><p>To control the IP address stored in the RMI stub you need to set the system property <code class="literal">java.rmi.server.hostname</code> with the desired value.
This is especially important when binding the RMI server host to the loopback address for security reasons. See also <a class="link" href="jmx-chapter.html#jmx-remote-access-ssh-tunnel" title="JMX Remote Access with Port Forwarding via SSH Tunnel">JMX Remote Access via SSH Tunnel.</a></p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_enabling_jmx_remote_access_in_standalone_jetty_server"></a>Enabling JMX Remote Access in Standalone Jetty Server</h4></div></div></div><p>Similarly to <a class="link" href="jmx-chapter.html#jmx-standalone-jetty" title="Standalone Jetty Server">enabling JMX in a standalone Jetty server</a>, you enable the <code class="literal">jmx-remote</code> module:</p><div class="screenexample"><pre class="screen">$ cd ${jetty.base}
$ java -jar {$jetty.home}/start.jar --add-to-start=jmx-remote</pre></div></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_enabling_jmx_remote_access_in_embedded_jetty"></a>Enabling JMX Remote Access in Embedded Jetty</h4></div></div></div><p>When running Jetty embedded into an application, create and configure a <code class="literal">ConnectorServer</code>:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>Server server = new Server();
// Setup JMX
MBeanContainer mbeanContainer = new MBeanContainer(ManagementFactory.getPlatformMBeanServer());
server.addBean(mbeanContainer);
// Setup ConnectorServer
JMXServiceURL jmxURL = new JMXServiceURL("rmi", null, 1999, "/jndi/rmi:///jmxrmi");
ConnectorServer jmxServer = new ConnectorServer(jmxURL, "org.eclipse.jetty.jmx:name=rmiconnectorserver");
server.addBean(jmxServer);</code></pre><p>The <code class="literal">JMXServiceURL</code> above specifies that the RMI server binds to the wildcard address on port 1999, while the RMI registry binds to the wildcard address on port 1099 (the default RMI registry port).</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="jmx-remote-access-authorization"></a>JMX Remote Access Authorization</h4></div></div></div><p>The standard <code class="literal">JMXConnectorServer</code> provides several options to authorize access.
For a complete guide to controlling authentication and authorization in JMX, see <a class="link" href="https://blogs.oracle.com/lmalventosa/entry/jmx_authentication_authorization" target="_top">Authentication and Authorization in JMX RMI connectors</a>.</p><p>To authorize access to the <code class="literal">JMXConnectorServer</code> you can use this configuration, where the <code class="literal">jmx.password</code> and <code class="literal">jmx.access</code> files have the format specified in the blog entry above:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>&lt;New id="ConnectorServer" class="org.eclipse.jetty.jmx.ConnectorServer"&gt;
&lt;Arg&gt;
&lt;New class="javax.management.remote.JMXServiceURL"&gt;
&lt;Arg type="java.lang.String"&gt;rmi&lt;/Arg&gt;
&lt;Arg type="java.lang.String" /&gt;
&lt;Arg type="java.lang.Integer"&gt;1099&lt;/Arg&gt;
&lt;Arg type="java.lang.String"&gt;/jndi/rmi:///jmxrmi&lt;/Arg&gt;
&lt;/New&gt;
&lt;/Arg&gt;
&lt;Arg&gt;
&lt;Map&gt;
&lt;Entry&gt;
&lt;Item&gt;jmx.remote.x.access.file&lt;/Item&gt;
&lt;Item&gt;
&lt;New class="java.lang.String"&gt;&lt;Arg&gt;&lt;Property name="jetty.base" default="." /&gt;/resources/jmx.access&lt;/Arg&gt;&lt;/New&gt;
&lt;/Item&gt;
&lt;/Entry&gt;
&lt;Entry&gt;
&lt;Item&gt;jmx.remote.x.password.file&lt;/Item&gt;
&lt;Item&gt;
&lt;New class="java.lang.String"&gt;&lt;Arg&gt;&lt;Property name="jetty.base" default="." /&gt;/resources/jmx.password&lt;/Arg&gt;&lt;/New&gt;
&lt;/Item&gt;
&lt;/Entry&gt;
&lt;/Map&gt;
&lt;/Arg&gt;
&lt;Arg&gt;org.eclipse.jetty.jmx:name=rmiconnectorserver&lt;/Arg&gt;
&lt;Call name="start" /&gt;
&lt;/New&gt;</code></pre><p>Similarly, in code:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>JMXServiceURL jmxURL = new JMXServiceURL("rmi", null, 1099, "/jndi/rmi:///jmxrmi");
Map&lt;String, Object&gt; env = new HashMap&lt;&gt;();
env.put("jmx.remote.x.access.file", "resources/jmx.access");
env.put("jmx.remote.x.password.file", "resources/jmx.password");
ConnectorServer jmxServer = new ConnectorServer(jmxURL, env, "org.eclipse.jetty.jmx:name=rmiconnectorserver");
jmxServer.start();</code></pre><p>Calling <code class="literal">ConnectorServer.start()</code> may be explicit as in the examples above, or can be skipped when adding the <code class="literal">ConnectorServer</code> as a bean to the <code class="literal">Server</code>, so that starting the <code class="literal">Server</code> will also start the <code class="literal">ConnectorServer</code>.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="_securing_jmx_remote_access_with_tls"></a>Securing JMX Remote Access with TLS</h4></div></div></div><p>The JMX communication via RMI happens by default in clear-text.</p><p>It is possible to configure the <code class="literal">ConnectorServer</code> with a <code class="literal">SslContextFactory</code> so that the JMX communication via RMI is encrypted:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>&lt;New id="ConnectorServer" class="org.eclipse.jetty.jmx.ConnectorServer"&gt;
&lt;Arg&gt;
&lt;New class="javax.management.remote.JMXServiceURL"&gt;
&lt;Arg type="java.lang.String"&gt;rmi&lt;/Arg&gt;
&lt;Arg type="java.lang.String" /&gt;
&lt;Arg type="java.lang.Integer"&gt;1099&lt;/Arg&gt;
&lt;Arg type="java.lang.String"&gt;/jndi/rmi:///jmxrmi&lt;/Arg&gt;
&lt;/New&gt;
&lt;/Arg&gt;
&lt;Arg /&gt;
&lt;Arg&gt;org.eclipse.jetty.jmx:name=rmiconnectorserver&lt;/Arg&gt;
&lt;Arg&gt;&lt;Ref refid="sslContextFactory" /&gt;&lt;/Arg&gt;
&lt;/New&gt;</code></pre><p>Similarly, in code:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>SslContextFactory.Server sslContextFactory = new SslContextFactory.Server();
sslContextFactory.setKeyStorePath("/path/to/keystore");
sslContextFactory.setKeyStorePassword("secret");
JMXServiceURL jmxURL = new JMXServiceURL("rmi", null, 1099, "/jndi/rmi:///jmxrmi");
ConnectorServer jmxServer = new ConnectorServer(jmxURL, null, "org.eclipse.jetty.jmx:name=rmiconnectorserver", sslContextFactory);</code></pre><p>It is possible to use the same <code class="literal">SslContextFactory</code> used to configure the Jetty <code class="literal">ServerConnector</code> that supports TLS for the HTTP protocol.
This is used in the XML example above: the <code class="literal">SslContextFactory</code> configured for the TLS <code class="literal">ServerConnector</code> is registered with an id of <code class="literal">sslContextFactory</code> which is referenced in the XML via the <code class="literal">Ref</code> element.</p><p>The keystore must contain a valid certificate signed by a Certification Authority.</p><p>The RMI mechanic is the usual one: the RMI client (typically a monitoring console) will connect first to the RMI registry (using TLS), download the RMI server stub that contains the address and port of the RMI server to connect to, then connect to the RMI server (using TLS).</p><p>This also mean that if the RMI registry and the RMI server are on different hosts, the RMI client must have available the cryptographic material to validate both hosts.</p><p>Having certificates signed by a Certification Authority simplifies by a lot the configuration needed to get the JMX communication over TLS working properly.</p><p>If that is not the case (for example the certificate is self-signed), then you need to specify the required system properties that allow RMI (especially when acting as an RMI client) to retrieve the cryptographic material necessary to establish the TLS connection.</p><p>For example, trying to connect using the JDK standard <code class="literal">JMXConnector</code> with both the RMI server and the RMI registry to <code class="literal">domain.com</code>:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>// System properties necessary for an RMI client to trust a self-signed certificate.
System.setProperty("javax.net.ssl.trustStore", "/path/to/trustStore");
System.setProperty("javax.net.ssl.trustStorePassword", "secret");
JMXServiceURL jmxURL = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://domain.com:1100/jmxrmi")
Map&lt;String, Object&gt; clientEnv = new HashMap&lt;&gt;();
// Required to connect to the RMI registry via TLS.
clientEnv.put(ConnectorServer.RMI_REGISTRY_CLIENT_SOCKET_FACTORY_ATTRIBUTE, new SslRMIClientSocketFactory());
try (JMXConnector client = JMXConnectorFactory.connect(jmxURL, clientEnv))
{
Set&lt;ObjectName&gt; names = client.getMBeanServerConnection().queryNames(null, null);
}</code></pre><p>Similarly, to launch JMC:</p><pre xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><code>$ jmc -vmargs -Djavax.net.ssl.trustStore=/path/to/trustStore -Djavax.net.ssl.trustStorePassword=secret</code></pre><p>Note that these system properties are required when launching the <code class="literal">ConnectorServer</code> too, on the server, because it acts as an RMI client with respect to the RMI registry.</p></div><div class="section"><div class="titlepage"><div><div><h4 class="title"><a name="jmx-remote-access-ssh-tunnel"></a>JMX Remote Access with Port Forwarding via SSH Tunnel</h4></div></div></div><p>You can access JMX MBeans on a remote machine when the RMI ports are not open, for example because of firewall policies, but you have SSH access to the machine using local port forwarding via a SSH tunnel.</p><p>In this case you want to configure the <code class="literal">ConnectorServer</code> with a <code class="literal">JMXServiceURL</code> that binds the RMI server and the RMI registry to the loopback interface only: <code class="literal">service:jmx:rmi://localhost:1099/jndi/rmi://localhost:1099/jmxrmi</code>.</p><p>Then you setup the local port forwarding with the SSH tunnel:</p><div class="screenexample"><pre class="screen">$ ssh -L 1099:localhost:1099 &lt;user&gt;@&lt;machine_host&gt;</pre></div><p>Now you can use JConsole or JMC to connect to <code class="literal">localhost:1099</code> on your local computer.
The traffic will be forwarded to <code class="literal">machine_host</code> and when there, SSH will forward the traffic to <code class="literal">localhost:1099</code>, which is exactly where the <code class="literal">ConnectorServer</code> listens.</p><p>When you configure <code class="literal">ConnectorServer</code> in this way, you must set the system property <code class="literal">-Djava.rmi.server.hostname=localhost</code>, on the server.</p><p>This is required because when the RMI server is exported, its address and port are stored in the RMI stub. You want the address in the RMI stub to be <code class="literal">localhost</code> so that when the RMI stub is downloaded to the remote client, the RMI communication will go through the SSH tunnel.</p></div></div></div></div><script type="text/javascript">
SyntaxHighlighter.all()
</script><div class="navfooter"><hr><table width="100%" summary="Navigation footer"><tr><td width="40%" align="left"><a accesskey="p" href="using-annotations-embedded.html"><i class="fa fa-chevron-left" aria-hidden="true"></i> Previous</a>&nbsp;</td><td width="20%" align="center"><a accesskey="u" href="jetty-admin-guide.html"><i class="fa fa-chevron-up" aria-hidden="true"></i> Top</a></td><td width="40%" align="right">&nbsp;<a accesskey="n" href="jetty-jmx-annotations.html">Next <i class="fa fa-chevron-right" aria-hidden="true"></i></a></td></tr><tr><td width="40%" align="left" valign="top">Using Annotations with Jetty Embedded&nbsp;</td><td width="20%" align="center"><a accesskey="h" href="index.html"><i class="fa fa-home" aria-hidden="true"></i> Home</a></td><td width="40%" align="right" valign="top">&nbsp;Jetty JMX Annotations</td></tr></table></div><p xmlns:jfetch="java:org.eclipse.jetty.xslt.tools.JavaSourceFetchExtension" xmlns:fetch="java:org.eclipse.jetty.xslt.tools.SourceFetchExtension" xmlns:d="http://docbook.org/ns/docbook" xmlns:l="http://docbook.sourceforge.net/xmlns/l10n/1.0" xmlns:xslthl="http://xslthl.sf.net" xmlns:gcse="http://www.google.com" xmlns:date="http://exslt.org/dates-and-times"><div class="jetty-callout">
See an error or something missing?
<span class="callout"><a href="http://github.com/eclipse/jetty.project">Contribute to this documentation at
<span class="website"><i class="fa fa-github" aria-hidden="true"></i> Github!</span></a></span><span style="float: right"><i>(Generated: 2020-03-10)</i></span></div></p></body></html>