Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -72,3 +72,6 @@ core/tests/org.openjdk.jmc.flightrecorder.rules.jdk.test/baseline/Generated_JfrR

# Ignore configuration directories generated by spotbugs
**/configuration/spotbugs

# Ignore vendor specific agent instructions
CLAUDE.md
9 changes: 8 additions & 1 deletion application/org.openjdk.jmc.feature.core/feature.xml
Original file line number Diff line number Diff line change
Expand Up @@ -245,7 +245,7 @@
unpack="false"/>

<plugin
id="org.jolokia.client-jmx-adapter.standalone"
id="org.jolokia.client.jmx-adapter"
download-size="0"
install-size="0"
version="0.0.0"
Expand All @@ -257,6 +257,13 @@
install-size="0"
version="0.0.0"
unpack="false"/>

<plugin
id="org.jolokia.service.serializer"
download-size="0"
install-size="0"
version="0.0.0"
unpack="false"/>

<plugin
id="org.jolokia.server.core"
Expand Down
9 changes: 6 additions & 3 deletions application/org.openjdk.jmc.jolokia/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,15 @@ Automatic-Module-Name: org.openjdk.jmc.jolokia
Bundle-RequiredExecutionEnvironment: JavaSE-21
Require-Bundle: org.eclipse.core.runtime,
org.eclipse.ui,
org.jolokia.client-jmx-adapter.standalone;bundle-version="2.4.2";visibility:=reexport,
org.jolokia.client.jmx-adapter;bundle-version="2.5.1";visibility:=reexport,
org.openjdk.jmc.common,
org.openjdk.jmc.rjmx,
org.openjdk.jmc.ui,
org.jolokia.service.discovery,
org.jolokia.server.core
org.jolokia.service.discovery;bundle-version="2.5.1",
org.jolokia.service.serializer;bundle-version="2.5.1",
org.jolokia.server.core;bundle-version="2.5.1",
org.jolokia.core;bundle-version="2.5.1"
Import-Package: org.jolokia.service.discovery
Export-Package: org.openjdk.jmc.jolokia,
org.openjdk.jmc.jolokia.preferences
Bundle-Activator: org.openjdk.jmc.jolokia.JmcJolokiaPlugin
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/*
* Copyright (c) 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2026, Kantega AS. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* The contents of this file are subject to the terms of either the Universal Permissive License
* v 1.0 as shown at https://oss.oracle.com/licenses/upl
*
* or the following license:
*
* Redistribution and use in source and binary forms, with or without modification, are permitted
* provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this list of conditions
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice, this list of
* conditions and the following disclaimer in the documentation and/or other materials provided with
* the distribution.
*
* 3. Neither the name of the copyright holder nor the names of its contributors may be used to
* endorse or promote products derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY
* WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.openjdk.jmc.jolokia;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jolokia.core.api.LogHandler;
import org.jolokia.server.core.service.api.AgentDetails;
import org.jolokia.server.core.service.api.JolokiaContext;

/**
* A minimal Jolokia context, just in order to support discovery (other server side functionality is
* not relevant in our context)
*/
public class JmcJolokiaContext {
// Note: Discovery will register and unregister jolokia during lifetime, this is
// not needed within jmc
private static final Set<String> METHODS_TO_IGNORE = new HashSet<>(
Arrays.asList("registerMBean", "unregisterMBean")); //$NON-NLS-1$ //$NON-NLS-2$

private static final LogHandler logHandler = new JulLoggerAdapter(Logger.getLogger("org.openjdk.jmc.jolokia")); //$NON-NLS-1$

public static JolokiaContext proxyJolokiaContext() {
return (JolokiaContext) Proxy.newProxyInstance(JmcJolokiaContext.class.getClassLoader(),
new Class[] {JolokiaContext.class}, new InvocationHandler() {

@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
if ("getAgentDetails".equals(method.getName())) { //$NON-NLS-1$
return new AgentDetails("jmc"); //$NON-NLS-1$
} else if (METHODS_TO_IGNORE.contains(method.getName())) {
return null;
} else if (method.getDeclaringClass().getName().equals(LogHandler.class.getName())) {
// Redirect logs to java util logging
return method.invoke(logHandler, args);
}
throw new UnsupportedOperationException(
method.getName() + " is not supported for JMC Jolokia context"); //$NON-NLS-1$
}
});
}

}

/**
* Simple adapter based on
* https://github.com/jolokia/jolokia/blob/main/server/core/src/main/java/org/jolokia/server/core/service/impl/JulLogHandler.java
* (Which is not directly accessible due to OSGi constraints)
*/
class JulLoggerAdapter implements LogHandler {

private final Logger julLogger;

public JulLoggerAdapter(Logger julLogger) {
this.julLogger = julLogger;
}

@Override
public void debug(String message) {
julLogger.finer(message);
}

@Override
public void error(String message, Throwable err) {
julLogger.log(Level.SEVERE, message, err);
}

@Override
public void info(String message) {
julLogger.info(message);
}

@Override
public boolean isDebug() {
return julLogger.isLoggable(Level.FINER);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025, Kantega AS. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Kantega AS. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -35,31 +35,35 @@

import java.io.IOException;
import java.lang.management.ManagementFactory;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;
import java.util.Optional;

import javax.management.AttributeNotFoundException;
import javax.management.Descriptor;
import javax.management.ImmutableDescriptor;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.modelmbean.DescriptorSupport;
import javax.management.openmbean.TabularData;

import org.jolokia.client.JolokiaClient;
import org.jolokia.client.jmxadapter.RemoteJmxAdapter;
import org.jolokia.core.service.serializer.SerializeOptions;
import org.jolokia.service.serializer.JolokiaSerializer;
import org.jolokia.server.core.service.serializer.SerializeOptions;
import org.openjdk.jmc.rjmx.common.ConnectionDecorator;

/**
* Make JMC specific adjustments to Jolokia JMX connection. May consider to use the decorator
* pattern if differences are big, but for now subclass
*/
public class JmcJolokiaJmxConnection extends RemoteJmxAdapter {
public class JmcJolokiaJmxConnection extends ConnectionDecorator {

private static final String UNKNOWN = "Unknown"; //$NON-NLS-1$
private static final String DIAGNOSTIC_OPTIONS = "com.sun.management:type=DiagnosticCommand"; //$NON-NLS-1$
Expand All @@ -74,13 +78,15 @@ public class JmcJolokiaJmxConnection extends RemoteJmxAdapter {
private static final String ARGUMENT_TYPE = PREFIX + "arg.type"; //$NON-NLS-1$
private static final String ARGUMENT_OPTION = PREFIX + "arg.isOption"; //$NON-NLS-1$
private static final String ARGUMENT_MULITPLE = PREFIX + "arg.isMultiple"; //$NON-NLS-1$
private Map<ObjectName, MBeanInfo> mbeanInfoCache = new HashMap<>();

public JmcJolokiaJmxConnection(JolokiaClient client) throws IOException {
super(client);
public JmcJolokiaJmxConnection(MBeanServerConnection delegate) {
super(delegate);
}

@Override
public MBeanInfo getMBeanInfo(ObjectName name) throws InstanceNotFoundException, IOException {
public MBeanInfo getMBeanInfo(ObjectName name)
throws InstanceNotFoundException, ReflectionException, IOException, IntrospectionException {
MBeanInfo mBeanInfo = super.getMBeanInfo(name);
// the diagnostic options tab and memory relies on descriptor info in MBeanInfo,
// modify descriptors the first time
Expand Down Expand Up @@ -115,7 +121,7 @@ private Optional<MBeanInfo> checkForLocalOperationInfo(ObjectName name) {

@Override
public Object invoke(ObjectName name, String operationName, Object[] params, String[] signature)
throws InstanceNotFoundException, MBeanException, IOException {
throws InstanceNotFoundException, MBeanException, IOException, ReflectionException {

if (params != null) {
for (int i = 0; i < params.length; i++) {
Expand Down Expand Up @@ -211,14 +217,14 @@ private Descriptor buildArgument(MBeanParameterInfo parameter) {

@Override
public boolean isInstanceOf(ObjectName objectName, String type) throws InstanceNotFoundException, IOException {
if ("java.lang.management.OperatingSystemMXBean".equals(type) //$NON-NLS-1$
&& "com.sun.management.internal.OperatingSystemImpl" //$NON-NLS-1$
.equals(this.getMBeanInfo(objectName).getClassName())) {
return true;
}
try {
if ("java.lang.management.OperatingSystemMXBean".equals(type) //$NON-NLS-1$
&& "com.sun.management.internal.OperatingSystemImpl" //$NON-NLS-1$
.equals(this.getMBeanInfo(objectName).getClassName())) {
return true;
}
return super.isInstanceOf(objectName, type);
} catch (NoClassDefFoundError | UnsatisfiedLinkError e) {
} catch (NoClassDefFoundError | UnsatisfiedLinkError | ReflectionException | IntrospectionException e) {
//Handle this until it is fixed in jolokia https://github.com/jolokia/jolokia/issues/666
return false;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2025, Kantega AS. All rights reserved.
* Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2024, 2026, Kantega AS. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -33,14 +33,13 @@
*/
package org.openjdk.jmc.jolokia;

import java.io.IOException;
import java.util.Map;

import javax.management.MBeanServerConnection;
import javax.management.remote.JMXServiceURL;
import javax.security.auth.Subject;

import org.jolokia.client.JolokiaClientBuilder;
import org.jolokia.client.jmxadapter.JolokiaJmxConnector;
import org.jolokia.client.jmxadapter.RemoteJmxAdapter;

public class JmcJolokiaJmxConnector extends JolokiaJmxConnector {

Expand All @@ -49,8 +48,13 @@ public JmcJolokiaJmxConnector(JMXServiceURL serviceURL, Map<String, ?> environme
}

@Override
protected RemoteJmxAdapter instantiateAdapter(JolokiaClientBuilder clientBuilder, Map<String, Object> mergedEnv)
throws IOException {
return new JmcJolokiaJmxConnection(clientBuilder.build());
public MBeanServerConnection getMBeanServerConnection() {
return new JmcJolokiaJmxConnection(super.getMBeanServerConnection());
}

@Override
public MBeanServerConnection getMBeanServerConnection(Subject delegationSubject) {
return new JmcJolokiaJmxConnection(super.getMBeanServerConnection(delegationSubject));
}

}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, Kantega AS. All rights reserved.
* Copyright (c) 2025, 2026, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2025, 2026, Kantega AS. All rights reserved.
*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
Expand Down Expand Up @@ -33,17 +33,7 @@
*/
package org.openjdk.jmc.jolokia;

import java.util.Arrays;
import java.util.TreeSet;

import org.jolokia.server.core.config.ConfigKey;
import org.jolokia.server.core.config.StaticConfiguration;
import org.jolokia.server.core.detector.ServerDetector;
import org.jolokia.server.core.restrictor.AllowAllRestrictor;
import org.jolokia.server.core.service.JolokiaServiceManagerFactory;
import org.jolokia.server.core.service.api.JolokiaContext;
import org.jolokia.server.core.service.api.JolokiaServiceManager;
import org.jolokia.server.core.service.impl.JulLogHandler;
import org.openjdk.jmc.jolokia.preferences.PreferenceConstants;
import org.openjdk.jmc.ui.MCAbstractUIPlugin;

Expand Down Expand Up @@ -72,11 +62,7 @@ public boolean shouldRunDiscovery() {
*/
@Override
public JolokiaContext getJolokiaContext() {
StaticConfiguration configuration = new StaticConfiguration(ConfigKey.AGENT_ID, "jmc");//$NON-NLS-1$
JolokiaServiceManager serviceManager = JolokiaServiceManagerFactory.createJolokiaServiceManager(configuration,
new JulLogHandler(PLUGIN_ID), new AllowAllRestrictor(),
logHandler -> new TreeSet<ServerDetector>(Arrays.asList(ServerDetector.FALLBACK)));
return serviceManager.start();
return JmcJolokiaContext.proxyJolokiaContext();
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,6 @@ Require-Bundle: org.junit,
org.hamcrest,
org.osgi.service.servlet;bundle-version="2.0.0"
Automatic-Module-Name: org.openjdk.jmc.jolokia.test
Import-Package: org.jolokia.server.core.config;version="2.5.1",
org.jolokia.server.core.service.api;version="2.5.1",
org.jolokia.service.discovery;version="2.5.1"
6 changes: 3 additions & 3 deletions application/tests/org.openjdk.jmc.jolokia.test/pom.xml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2024, 2025, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2024, 2025, Kantega AS. All rights reserved.
Copyright (c) 2024, 2026, Oracle and/or its affiliates. All rights reserved.
Copyright (c) 2024, 2026, Kantega AS. All rights reserved.

DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.

Expand Down Expand Up @@ -46,7 +46,7 @@

<properties>
<jmc.config.path>${project.basedir}/../../../configuration</jmc.config.path>
<jolokia.agent.version>2.4.2</jolokia.agent.version>
<jolokia.agent.version>2.5.1</jolokia.agent.version>
</properties>

<dependencies>
Expand Down
Loading
Loading