diff options
12 files changed, 156 insertions, 339 deletions
diff --git a/jacoco-maven-plugin/src/org/jacoco/maven/AgentMojo.java b/jacoco-maven-plugin/src/org/jacoco/maven/AgentMojo.java index 6a6932c4..33386d08 100644 --- a/jacoco-maven-plugin/src/org/jacoco/maven/AgentMojo.java +++ b/jacoco-maven-plugin/src/org/jacoco/maven/AgentMojo.java @@ -163,6 +163,13 @@ public class AgentMojo extends AbstractJacocoMojo { */ private File classDumpDir; + /** + * If set to true the agent exposes functionality via JMX. + * + * @parameter expression="${jacoco.jmx}" + */ + private Boolean jmx; + @Override public void executeMojo() { final String vmArgument = StringUtils.quoteAndEscape( @@ -175,7 +182,7 @@ public class AgentMojo extends AbstractJacocoMojo { prependProperty(""); } - private void prependProperty(String vmArgument) { + private void prependProperty(final String vmArgument) { if (isPropertyNameSpecified()) { prependProperty(propertyName, vmArgument); } else if (isEclipseTestPluginPackaging()) { @@ -228,6 +235,9 @@ public class AgentMojo extends AbstractJacocoMojo { if (classDumpDir != null) { agentOptions.setClassDumpDir(classDumpDir.getAbsolutePath()); } + if (jmx != null) { + agentOptions.setJmx(jmx.booleanValue()); + } return agentOptions; } diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java index 495b5cef..8616763d 100644 --- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java +++ b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/AgentTest.java @@ -16,14 +16,19 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.File; import java.io.IOException; +import java.lang.management.ManagementFactory; + +import javax.management.InstanceNotFoundException; +import javax.management.MBeanServer; +import javax.management.ObjectName; import org.jacoco.agent.rt.internal.controller.IAgentController; import org.jacoco.agent.rt.internal.controller.LocalController; -import org.jacoco.agent.rt.internal.controller.MBeanController; import org.jacoco.agent.rt.internal.controller.TcpClientController; import org.jacoco.agent.rt.internal.controller.TcpServerController; import org.jacoco.core.JaCoCo; @@ -74,10 +79,6 @@ public class AgentTest implements IExceptionLogger { options.setOutput(OutputMode.tcpclient); assertEquals(TcpClientController.class, agent.createAgentController() .getClass()); - - options.setOutput(OutputMode.mbean); - assertEquals(MBeanController.class, agent.createAgentController() - .getClass()); } @Test @@ -247,6 +248,35 @@ public class AgentTest implements IExceptionLogger { assertTrue(called[0]); } + @Test + public void testJmx() throws Exception { + options.setJmx(true); + Agent agent = new Agent(options, this); + + agent.startup(); + + ObjectName objectName = new ObjectName("org.jacoco:type=Runtime"); + final MBeanServer server = ManagementFactory.getPlatformMBeanServer(); + assertEquals(JaCoCo.VERSION, server.getAttribute(objectName, "Version")); + + agent.shutdown(); + + try { + server.getMBeanInfo(objectName); + fail("InstanceNotFoundException expected"); + } catch (InstanceNotFoundException expected) { + } + } + + @Test(expected = InstanceNotFoundException.class) + public void testNoJmx() throws Exception { + Agent agent = new Agent(options, this); + agent.startup(); + + ObjectName objectName = new ObjectName("org.jacoco:type=Runtime"); + ManagementFactory.getPlatformMBeanServer().getMBeanInfo(objectName); + } + // === IExceptionLogger === public void logExeption(Exception ex) { diff --git a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/controller/MBeanControllerTest.java b/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/controller/MBeanControllerTest.java deleted file mode 100644 index 3b50c658..00000000 --- a/org.jacoco.agent.rt.test/src/org/jacoco/agent/rt/internal/controller/MBeanControllerTest.java +++ /dev/null @@ -1,170 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Evgeny Mandrikov - initial API and implementation - * - *******************************************************************************/ -package org.jacoco.agent.rt.internal.controller; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; - -import java.io.ByteArrayInputStream; -import java.lang.management.ManagementFactory; -import java.util.List; - -import javax.management.InstanceNotFoundException; -import javax.management.MBeanAttributeInfo; -import javax.management.MBeanInfo; -import javax.management.MBeanOperationInfo; -import javax.management.ObjectName; - -import org.jacoco.agent.rt.internal.controller.MBeanController; -import org.jacoco.core.JaCoCo; -import org.jacoco.core.data.ExecutionDataReader; -import org.jacoco.core.data.ExecutionDataStore; -import org.jacoco.core.data.SessionInfo; -import org.jacoco.core.data.SessionInfoStore; -import org.jacoco.core.runtime.AgentOptions; -import org.jacoco.core.runtime.RuntimeData; -import org.junit.Before; -import org.junit.Test; - -/** - * Unit tests for {@link MBeanController}. - */ -public class MBeanControllerTest { - - private RuntimeData data; - - private MBeanController controller; - - @Before - public void setup() throws Exception { - data = new RuntimeData(); - controller = new MBeanController(); - controller.startup(new AgentOptions(), data); - } - - @Test - public void testStartupAndShutdown() throws Exception { - final ObjectName objectName = new ObjectName("org.jacoco:type=Runtime"); - - final MBeanInfo info = ManagementFactory.getPlatformMBeanServer() - .getMBeanInfo(objectName); - - final MBeanAttributeInfo[] attributes = info.getAttributes(); - assertEquals(2, attributes.length); - - for (MBeanAttributeInfo attribute : attributes) { - if ("SessionId".equals(attribute.getName())) { - assertEquals(String.class.getName(), attribute.getType()); - } else if ("Version".equals(attribute.getName())) { - assertEquals(String.class.getName(), attribute.getType()); - } else { - fail("Unexpected attribute: " + attribute.getName()); - } - } - - final MBeanOperationInfo[] operations = info.getOperations(); - assertEquals(2, info.getOperations().length); - - for (MBeanOperationInfo operation : operations) { - if ("reset".equals(operation.getName())) { - assertEquals(void.class.getName(), operation.getReturnType()); - assertEquals(0, operation.getSignature().length); - } else if ("dump".equals(operation.getName())) { - assertEquals(byte[].class.getName(), operation.getReturnType()); - assertEquals(1, operation.getSignature().length); - assertEquals(boolean.class.getName(), - operation.getSignature()[0].getType()); - } else { - fail("Unexpected operation: " + operation.getName()); - } - } - - controller.shutdown(); - - try { - ManagementFactory.getPlatformMBeanServer().getMBeanInfo(objectName); - fail("MBean was not deregistered"); - } catch (InstanceNotFoundException e) { - } - } - - @Test - public void testDump() throws Exception { - data.getExecutionData(Long.valueOf(0x12345678), "Foo", 42); - data.setSessionId("stubid"); - - final byte[] dump = controller.dump(false); - final ByteArrayInputStream input = new ByteArrayInputStream(dump); - - final ExecutionDataReader reader = new ExecutionDataReader(input); - final ExecutionDataStore execStore = new ExecutionDataStore(); - reader.setExecutionDataVisitor(execStore); - final SessionInfoStore infoStore = new SessionInfoStore(); - reader.setSessionInfoVisitor(infoStore); - reader.read(); - - assertEquals("Foo", execStore.get(0x12345678).getName()); - - final List<SessionInfo> infos = infoStore.getInfos(); - assertEquals(1, infos.size()); - assertEquals("stubid", infos.get(0).getId()); - - controller.shutdown(); - } - - @Test - public void testDumpWithReset() throws Exception { - controller.dump(true); - assertNoProbes(); - - controller.shutdown(); - } - - @Test - public void testReset() throws Exception { - controller.reset(); - assertNoProbes(); - - controller.shutdown(); - } - - @Test - public void testGetSessionId() throws Exception { - data.setSessionId("stubid"); - - assertEquals("stubid", controller.getSessionId()); - - controller.shutdown(); - } - - @Test - public void testSetSessionId() throws Exception { - controller.setSessionId("newid"); - assertEquals("newid", data.getSessionId()); - - controller.shutdown(); - } - - @Test - public void testGetVersion() throws Exception { - assertEquals(JaCoCo.VERSION, controller.getVersion()); - - controller.shutdown(); - } - - private void assertNoProbes() { - ExecutionDataStore store = new ExecutionDataStore(); - data.collect(store, new SessionInfoStore(), false); - assertTrue(store.getContents().isEmpty()); - } -} diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java index f726e0ca..68ac3c63 100644 --- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java +++ b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/Agent.java @@ -13,13 +13,16 @@ package org.jacoco.agent.rt.internal; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.lang.management.ManagementFactory; import java.net.InetAddress; import java.net.UnknownHostException; +import javax.management.ObjectName; +import javax.management.StandardMBean; + import org.jacoco.agent.rt.IAgent; import org.jacoco.agent.rt.internal.controller.IAgentController; import org.jacoco.agent.rt.internal.controller.LocalController; -import org.jacoco.agent.rt.internal.controller.MBeanController; import org.jacoco.agent.rt.internal.controller.TcpClientController; import org.jacoco.agent.rt.internal.controller.TcpServerController; import org.jacoco.core.JaCoCo; @@ -34,6 +37,8 @@ import org.jacoco.core.runtime.RuntimeData; */ public class Agent implements IAgent { + private static final String JMX_NAME = "org.jacoco:type=Runtime"; + private static Agent singleton; /** @@ -118,6 +123,11 @@ public class Agent implements IAgent { data.setSessionId(sessionId); controller = createAgentController(); controller.startup(options, data); + if (options.getJmx()) { + ManagementFactory.getPlatformMBeanServer().registerMBean( + new StandardMBean(this, IAgent.class), + new ObjectName(JMX_NAME)); + } } catch (final Exception e) { logger.logExeption(e); } @@ -132,6 +142,10 @@ public class Agent implements IAgent { controller.writeExecutionData(false); } controller.shutdown(); + if (options.getJmx()) { + ManagementFactory.getPlatformMBeanServer().unregisterMBean( + new ObjectName(JMX_NAME)); + } } catch (final Exception e) { logger.logExeption(e); } @@ -151,8 +165,6 @@ public class Agent implements IAgent { return new TcpServerController(logger); case tcpclient: return new TcpClientController(logger); - case mbean: - return new MBeanController(); default: throw new AssertionError(controllerType); } diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/controller/IRuntimeMBean.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/controller/IRuntimeMBean.java deleted file mode 100644 index 885cb8f4..00000000 --- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/controller/IRuntimeMBean.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Evgeny Mandrikov - initial API and implementation - * - *******************************************************************************/ -package org.jacoco.agent.rt.internal.controller; - -import java.io.IOException; - -/** - * MBean interface for remote commands to a coverage runtime. - */ -public interface IRuntimeMBean { - - /** - * Returns version of JaCoCo. - * - * @return version of JaCoCo - */ - String getVersion(); - - /** - * Returns current a session identifier. - * - * @return current session identifier - */ - String getSessionId(); - - /** - * Sets a session identifier. - * - * @param id - * new session identifier - */ - void setSessionId(String id); - - /** - * Returns current execution data. - * - * @param reset - * if <code>true</code> the current coverage information is also - * cleared - * @return dump of current execution data - * @throws IOException - */ - byte[] dump(boolean reset) throws IOException; - - /** - * Resets all coverage information. - */ - void reset(); - -} diff --git a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/controller/MBeanController.java b/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/controller/MBeanController.java deleted file mode 100644 index 2b3b9cb0..00000000 --- a/org.jacoco.agent.rt/src/org/jacoco/agent/rt/internal/controller/MBeanController.java +++ /dev/null @@ -1,77 +0,0 @@ -/******************************************************************************* - * Copyright (c) 2009, 2013 Mountainminds GmbH & Co. KG and Contributors - * All rights reserved. This program and the accompanying materials - * are made available under the terms of the Eclipse Public License v1.0 - * which accompanies this distribution, and is available at - * http://www.eclipse.org/legal/epl-v10.html - * - * Contributors: - * Evgeny Mandrikov - initial API and implementation - * - *******************************************************************************/ -package org.jacoco.agent.rt.internal.controller; - -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.lang.management.ManagementFactory; - -import javax.management.ObjectName; -import javax.management.StandardMBean; - -import org.jacoco.core.JaCoCo; -import org.jacoco.core.data.ExecutionDataWriter; -import org.jacoco.core.runtime.AgentOptions; -import org.jacoco.core.runtime.RuntimeData; - -/** - * Controller that registers MBean. This controller does not use agent options. - */ -public class MBeanController implements IAgentController, IRuntimeMBean { - - private static final String OBJECT_NAME = "org.jacoco:type=Runtime"; - - private RuntimeData data; - - public void startup(final AgentOptions options, final RuntimeData data) - throws Exception { - this.data = data; - ManagementFactory.getPlatformMBeanServer().registerMBean( - new StandardMBean(this, IRuntimeMBean.class), - new ObjectName(OBJECT_NAME)); - } - - public void shutdown() throws Exception { - ManagementFactory.getPlatformMBeanServer().unregisterMBean( - new ObjectName(OBJECT_NAME)); - } - - public void writeExecutionData(final boolean reset) { - // nothing to do - } - - // === IRuntimeMBean === - - public String getVersion() { - return JaCoCo.VERSION; - } - - public String getSessionId() { - return data.getSessionId(); - } - - public void setSessionId(final String id) { - data.setSessionId(id); - } - - public byte[] dump(final boolean reset) throws IOException { - final ByteArrayOutputStream output = new ByteArrayOutputStream(); - final ExecutionDataWriter writer = new ExecutionDataWriter(output); - data.collect(writer, writer, reset); - return output.toByteArray(); - } - - public void reset() { - data.reset(); - } - -} diff --git a/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java b/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java index 0dd9fa02..8471bc14 100644 --- a/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java +++ b/org.jacoco.ant/src/org/jacoco/ant/AbstractCoverageTask.java @@ -183,6 +183,16 @@ public class AbstractCoverageTask extends Task { } /** + * Sets whether the agent should exposes functionality via JMX. + * + * @param jmx + * <code>true</code> if JMX should be enabled + */ + public void setJmx(final boolean jmx) { + agentOptions.setJmx(jmx); + } + + /** * Creates JVM argument to launch with the specified JaCoCo agent jar and * the current options * diff --git a/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java b/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java index df074b09..be2dab1c 100644 --- a/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java +++ b/org.jacoco.core.test/src/org/jacoco/core/runtime/AgentOptionsTest.java @@ -49,6 +49,7 @@ public class AgentOptionsTest { assertNull(options.getAddress()); assertEquals(6300, options.getPort()); assertNull(options.getClassDumpDir()); + assertFalse(options.getJmx()); assertEquals("", options.toString()); } @@ -79,6 +80,7 @@ public class AgentOptionsTest { properties.put("address", "remotehost"); properties.put("port", "1234"); properties.put("classdumpdir", "target/dump"); + properties.put("jmx", "true"); AgentOptions options = new AgentOptions(properties); @@ -93,6 +95,7 @@ public class AgentOptionsTest { assertEquals("remotehost", options.getAddress()); assertEquals(1234, options.getPort()); assertEquals("target/dump", options.getClassDumpDir()); + assertTrue(options.getJmx()); } @Test @@ -320,6 +323,19 @@ public class AgentOptionsTest { } @Test + public void testGetJmx() { + AgentOptions options = new AgentOptions("jmx=true"); + assertTrue(options.getJmx()); + } + + @Test + public void testSetJmx() { + AgentOptions options = new AgentOptions(); + options.setJmx(true); + assertTrue(options.getJmx()); + } + + @Test public void testVMArgsWithNoOptions() { AgentOptions options = new AgentOptions(); String vmArgument = options.getVMArgument(defaultAgentJarFile); diff --git a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java index 22be041c..78f79319 100644 --- a/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java +++ b/org.jacoco.core/src/org/jacoco/core/runtime/AgentOptions.java @@ -115,13 +115,7 @@ public final class AgentOptions { * agent connects to a TCP port specified by the * {@link AgentOptions#ADDRESS} and {@link AgentOptions#PORT} attribute. */ - tcpclient, - - /** - * Value for the {@link AgentOptions#OUTPUT} parameter: At startup the - * agent creates MBean. - */ - mbean + tcpclient } @@ -156,9 +150,15 @@ public final class AgentOptions { */ public static final String CLASSDUMPDIR = "classdumpdir"; + /** + * Specifies whether the agent should expose functionality via JMX under the + * name "org.jacoco:type=Runtime". Default is <code>false</code>. + */ + public static final String JMX = "jmx"; + private static final Collection<String> VALID_OPTIONS = Arrays.asList( DESTFILE, APPEND, INCLUDES, EXCLUDES, EXCLCLASSLOADER, SESSIONID, - DUMPONEXIT, OUTPUT, ADDRESS, PORT, CLASSDUMPDIR); + DUMPONEXIT, OUTPUT, ADDRESS, PORT, CLASSDUMPDIR, JMX); private final Map<String, String> options; @@ -459,6 +459,25 @@ public final class AgentOptions { setOption(CLASSDUMPDIR, location); } + /** + * Returns whether the agent exposes functionality via JMX. + * + * @return <code>true</code>, when JMX is enabled + */ + public boolean getJmx() { + return getOption(JMX, false); + } + + /** + * Sets whether the agent should exposes functionality via JMX. + * + * @param jmx + * <code>true</code> if JMX should be enabled + */ + public void setJmx(final boolean jmx) { + setOption(JMX, jmx); + } + private void setOption(final String key, final int value) { setOption(key, Integer.toString(value)); } diff --git a/org.jacoco.doc/docroot/doc/agent.html b/org.jacoco.doc/docroot/doc/agent.html index f5cf8666..5391c2e3 100644 --- a/org.jacoco.doc/docroot/doc/agent.html +++ b/org.jacoco.doc/docroot/doc/agent.html @@ -26,9 +26,9 @@ </p> <p class="hint"> - If you use the <a href="ant.html">JaCoCo Ant tasks</a> or <a href="maven.html">JaCoCo Maven plug-in</a> - you don't have to care about the agent and its options directly. This is - transparently handled by the them. + If you use the <a href="ant.html">JaCoCo Ant tasks</a> or + <a href="maven.html">JaCoCo Maven plug-in</a> you don't have to care about the + agent and its options directly. This is transparently handled by the them. </p> <p> @@ -37,10 +37,15 @@ </p> <ul> - <li>File System: At JVM termination execution data is written to a local file.</li> - <li>TCP Socket Server: External tools can connect to the JVM and retrieve execution data over the socket connection. Optional execution data reset and execution data dump on VM exit is possible.</li> - <li>TCP Socket Client: At startup the JaCoCo agent connects to a given TCP endpoint. Execution data is written to the socket connection on request. Optional execution data reset and execution data dump on VM exit is possible.</li> - <li>JMX: External tools can connect to the JVM and retrieve execution data over the JMX.</li> + <li>File System: At JVM termination execution data is written to a local + file.</li> + <li>TCP Socket Server: External tools can connect to the JVM and retrieve + execution data over the socket connection. Optional execution data reset + and execution data dump on VM exit is possible.</li> + <li>TCP Socket Client: At startup the JaCoCo agent connects to a given TCP + endpoint. Execution data is written to the socket connection on request. + Optional execution data reset and execution data dump on VM exit is + possible.</li> </ul> <p> @@ -140,8 +145,6 @@ <li><code>tcpclient</code>: At startup the agent connects to the TCP port specified by the <code>address</code> and <code>port</code> attribute. Execution data is written to this TCP connection.</li> - <li><code>mbean</code>: The agent registers an JMX MBean under the - name <code>org.jacoco:type=Runtime</code>.</li> </ul> Please see the security considerations below. </td> @@ -176,6 +179,15 @@ </td> <td><i>no dumps</i></td> </tr> + <tr> + <td><code>jmx</code></td> + <td>If set to <code>true</code> the agent exposes + <a href="./api/org/jacoco/agent/rt/IAgent.html">functionality</a> via + JMX under the name <code>org.jacoco:type=Runtime</code>. Please see + the security considerations below. + </td> + <td><code>false</code></td> + </tr> </tbody> </table> @@ -183,11 +195,11 @@ <p> The ports and connections opened in <code>tcpserver</code> and - <code>tcpclient</code> mode do not provide any authentication mechanism. If - you run JaCoCo on production systems make sure that no untrusted sources have - access to the TCP server port, or JaCoCo TCP clients only connect to trusted - targets. Otherwise internal information of the application might be revealed - or DOS attacks are possible. + <code>tcpclient</code> mode and the JMX interface do not provide any + authentication mechanism. If you run JaCoCo on production systems make sure + that no untrusted sources have access to the TCP server port, or JaCoCo TCP + clients only connect to trusted targets. Otherwise internal information of the + application might be revealed or DOS attacks are possible. </p> </div> diff --git a/org.jacoco.doc/docroot/doc/ant.html b/org.jacoco.doc/docroot/doc/ant.html index fac58c53..c0e84e4f 100644 --- a/org.jacoco.doc/docroot/doc/ant.html +++ b/org.jacoco.doc/docroot/doc/ant.html @@ -231,8 +231,6 @@ <li><code>tcpclient</code>: At startup the agent connects to the TCP port specified by the <code>address</code> and <code>port</code> attribute. Execution data is written to this TCP connection.</li> - <li><code>mbean</code>: The agent registers an JMX MBean under the - name <code>org.jacoco:type=Runtime</code>.</li> </ul> </td> <td><code>file</code></td> @@ -266,6 +264,14 @@ </td> <td><i>no dumps</i></td> </tr> + <tr> + <td><code>jmx</code></td> + <td>If set to <code>true</code> the agent exposes + <a href="./api/org/jacoco/agent/rt/IAgent.html">functionality</a> via + JMX under the name <code>org.jacoco:type=Runtime</code>. + </td> + <td><code>false</code></td> + </tr> </tbody> </table> diff --git a/org.jacoco.doc/docroot/doc/changes.html b/org.jacoco.doc/docroot/doc/changes.html index c1338bfe..4104b1f1 100644 --- a/org.jacoco.doc/docroot/doc/changes.html +++ b/org.jacoco.doc/docroot/doc/changes.html @@ -35,6 +35,14 @@ <code>Eclipse-SourceReferences</code> manifest headers (GitHub #7, #59).</li> </ul> +<h3>API Changes</h3> +<ul> + <li>The <code>output</code> mode <code>mbean</code> of the agent has been + dropped in favor of the new boolean option <code>jmx</code>. This allows + to combine JMX access with any other output mode (GitHub #62).</li> +</ul> + + <h2>Release 0.6.1 (2012/12/23)</h2> <h3>New Features</h3> |