diff --git a/application/org.openjdk.jmc.browser.attach/src/main/java/org/openjdk/jmc/browser/attach/LocalJVMToolkit.java b/application/org.openjdk.jmc.browser.attach/src/main/java/org/openjdk/jmc/browser/attach/LocalJVMToolkit.java --- a/application/org.openjdk.jmc.browser.attach/src/main/java/org/openjdk/jmc/browser/attach/LocalJVMToolkit.java +++ b/application/org.openjdk.jmc.browser.attach/src/main/java/org/openjdk/jmc/browser/attach/LocalJVMToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -199,6 +199,8 @@ String address = null; String version = null; String jvmArgs = null; + String jvmVendor = null; + try { // This used to leak one \BaseNamedObjects\hsperfdata_* Section handle on Windows MonitoredVm mvm = host.getMonitoredVm(new VmIdentifier(name)); @@ -235,6 +237,12 @@ if (sm != null) { isDebug = isDebug(sm.stringValue()); } + + sm = (StringMonitor) mvm.findByName("java.property.java.vm.vendor"); //$NON-NLS-1$ + if (sm != null) { + jvmVendor = sm.stringValue(); + } + // NOTE: isAttachable seems to return true even if a real attach is not possible. // attachable = MonitoredVmUtil.isAttachable(mvm); @@ -260,7 +268,7 @@ } catch (Exception x) { // ignore } - connDesc = createDescriptor(name, jvmArgs, vmid, connectable, type, jvmArch, address, version, isDebug); + connDesc = createDescriptor(name, jvmArgs, jvmVendor, vmid, connectable, type, jvmArch, address, version, isDebug); return connDesc; } }); @@ -359,6 +367,7 @@ String javaArgs = null; String jvmArgs = null; String jvmVersion = null; + String jvmVendor = null; VirtualMachine vm = null; try { // Attach creates one process handle on Windows. @@ -379,6 +388,7 @@ jvmType = getJVMType(vmName); version = props.getProperty("java.version"); //$NON-NLS-1$ jvmVersion = props.getProperty("java.vm.version"); //$NON-NLS-1$ + jvmVendor = props.getProperty("java.vm.vendor"); isDebug = isDebug(jvmVersion); jvmArch = JVMArch.getJVMArch(props); } @@ -396,7 +406,7 @@ } } if (connectable.isAttachable()) { - connDesc = createDescriptor(javaArgs, jvmArgs, Integer.parseInt(vmd.id()), connectable, jvmType, jvmArch, + connDesc = createDescriptor(javaArgs, jvmArgs, jvmVendor, Integer.parseInt(vmd.id()), connectable, jvmType, jvmArch, address, version, isDebug); } BrowserAttachPlugin.getPluginLogger().info("Done resolving PID " + vmd); //$NON-NLS-1$ @@ -461,9 +471,10 @@ } private static DiscoveryEntry createDescriptor( - String javaCommand, String jvmArgs, int pid, Connectable connectable, JVMType type, JVMArch arch, - String address, String version, boolean isDebug) { - JVMDescriptor jvmInfo = new JVMDescriptor(version, type, arch, javaCommand, jvmArgs, pid, isDebug, connectable); + String javaCommand, String jvmArgs, String jvmVendor, int pid, Connectable connectable, JVMType type, + JVMArch arch, String address, String version, boolean isDebug) { + JVMDescriptor jvmInfo = new JVMDescriptor(version, type, arch, javaCommand, jvmArgs, jvmVendor, pid, isDebug, + connectable); LocalConnectionDescriptor lcd = new LocalConnectionDescriptor(pid, address, connectable == ATTACHABLE); String guid = "Local-[PID:" + pid + ", seq:" + (SEQ_NUMBER++) + "]"; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ IServerDescriptor sd = IServerDescriptor.create(guid, null, jvmInfo); diff --git a/application/org.openjdk.jmc.browser.jdp/src/main/java/org/openjdk/jmc/browser/jdp/JDPDescriptorProvider.java b/application/org.openjdk.jmc.browser.jdp/src/main/java/org/openjdk/jmc/browser/jdp/JDPDescriptorProvider.java --- a/application/org.openjdk.jmc.browser.jdp/src/main/java/org/openjdk/jmc/browser/jdp/JDPDescriptorProvider.java +++ b/application/org.openjdk.jmc.browser.jdp/src/main/java/org/openjdk/jmc/browser/jdp/JDPDescriptorProvider.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -89,9 +89,9 @@ String url = map.get(JMXDataKeys.KEY_JMX_SERVICE_URL); String commandLine = map.get(JMXDataKeys.KEY_JAVA_COMMAND); String pid = map.get(JMXDataKeys.KEY_PID); - // NOTE: We would like to have the JVM type and architecture included in the JDP payload. We should probably file an enhancement request on JDK for this. + // NOTE: We would like to have the JVM type, architecture and vendor included in the JDP payload. We should probably file an enhancement request on JDK for this. JVMDescriptor jvmInfo = new JVMDescriptor(null, JVMType.UNKNOWN, JVMArch.UNKNOWN, commandLine, null, - pid == null ? null : Integer.parseInt(pid), false, Connectable.MGMNT_AGENT_STARTED); + null, pid == null ? null : Integer.parseInt(pid), false, Connectable.MGMNT_AGENT_STARTED); String path = null; if (name == null) { } else if (name.endsWith(PATH_SEPARATOR)) { diff --git a/application/org.openjdk.jmc.rjmx.services.jfr/src/main/java/org/openjdk/jmc/rjmx/services/jfr/internal/FlightRecorderServiceV2.java b/application/org.openjdk.jmc.rjmx.services.jfr/src/main/java/org/openjdk/jmc/rjmx/services/jfr/internal/FlightRecorderServiceV2.java --- a/application/org.openjdk.jmc.rjmx.services.jfr/src/main/java/org/openjdk/jmc/rjmx/services/jfr/internal/FlightRecorderServiceV2.java +++ b/application/org.openjdk.jmc.rjmx.services.jfr/src/main/java/org/openjdk/jmc/rjmx/services/jfr/internal/FlightRecorderServiceV2.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -104,17 +104,14 @@ } private boolean isDynamicFlightRecorderSupported(IConnectionHandle handle) { - return ConnectionToolkit.isHotSpot(handle) - && ConnectionToolkit.isJavaVersionAboveOrEqual(handle, JavaVersionSupport.DYNAMIC_JFR_SUPPORTED); - } - - private boolean isFlightRecorderCommercial() { - return ConnectionToolkit.isHotSpot(connection) - && !ConnectionToolkit.isJavaVersionAboveOrEqual(connection, JavaVersionSupport.JFR_NOT_COMMERCIAL); + // All OpenJDK versions of JFR support dynamic enablement of JFR, so if there are no commercial features in play + // all is A-OK. + return !cfs.hasCommercialFeatures() || (ConnectionToolkit.isHotSpot(handle) + && ConnectionToolkit.isJavaVersionAboveOrEqual(handle, JavaVersionSupport.DYNAMIC_JFR_SUPPORTED)); } private boolean isFlightRecorderDisabled(IConnectionHandle handle) { - if (cfs != null && isFlightRecorderCommercial()) { + if (cfs != null && cfs.hasCommercialFeatures()) { return !cfs.isCommercialFeaturesEnabled() || JVMSupportToolkit.isFlightRecorderDisabled(handle, false); } else { return JVMSupportToolkit.isFlightRecorderDisabled(handle, false); @@ -127,6 +124,7 @@ public FlightRecorderServiceV2(IConnectionHandle handle) throws ConnectionException, ServiceNotAvailableException { cfs = handle.getServiceOrThrow(ICommercialFeaturesService.class); + if (!isDynamicFlightRecorderSupported(handle) && isFlightRecorderDisabled(handle)) { throw new ServiceNotAvailableException(""); //$NON-NLS-1$ } @@ -481,7 +479,7 @@ @Override public boolean isEnabled() { if (!wasEnabled) { - boolean isEnabled = isFlightRecorderCommercial() ? cfs.isCommercialFeaturesEnabled() + boolean isEnabled = cfs.hasCommercialFeatures() ? cfs.isCommercialFeaturesEnabled() : isAvailable(connection); if (isEnabled) { wasEnabled = true; diff --git a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/ConnectionToolkit.java b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/ConnectionToolkit.java --- a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/ConnectionToolkit.java +++ b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/ConnectionToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -56,6 +56,7 @@ import org.openjdk.jmc.common.version.JavaVMVersionToolkit; import org.openjdk.jmc.common.version.JavaVersion; import org.openjdk.jmc.rjmx.internal.RJMXConnection; +import org.openjdk.jmc.ui.common.jvm.JVMDescriptor; /** * Toolkit providing utility methods to retrieve MBean proxy objects, invoke JMX operations and @@ -346,7 +347,6 @@ * otherwise. */ public static boolean isJRockit(IConnectionHandle connectionHandle) { - String vmName = getVMName(connectionHandle); return JavaVMVersionToolkit.isJRockitJVMName(vmName); } @@ -366,6 +366,38 @@ } /** + * Returns {@code true} if the connection handle is associated with an Oracle built JVM, + * {@code false} otherwise. If the information is already present in the {@link JVMDescriptor}, + * this method will not cause any JMXRMI calls. If the information is lacking, an attempt will + * be made to look it up in the connected JVM. If the attempt fails, false will be returned. + * + * @return {@code true} if the connection handle describes an Oracle JVM, or {@code false} + * otherwise or if it could not be determined. + */ + public static boolean isOracle(IConnectionHandle handle) { + JVMDescriptor descriptor = handle.getServerDescriptor().getJvmInfo(); + // This should normally not happen for discovered JVMs, but users can create custom connections + String vendor = null; + if (descriptor != null) { + vendor = descriptor.getJvmVendor(); + } else { + // We try checking if connected + if (handle.isConnected()) { + MBeanServerConnection connection = handle.getServiceOrNull(MBeanServerConnection.class); + if (connection != null) { + try { + vendor = getRuntimeBean(connection).getVmVendor(); + } catch (IOException e) { + // Worst case we classify JVM vendor wrong + RJMXPlugin.getDefault().getLogger().log(Level.WARNING, "Could not check if Oracle JVM", e); + } + } + } + } + return vendor != null && vendor.contains("Oracle"); + } + + /** * This will return true if the java version is above or equal the supplied value. (For example * 1.7.0_40). * @@ -411,5 +443,4 @@ } return null; } - } diff --git a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/JVMSupportToolkit.java b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/JVMSupportToolkit.java --- a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/JVMSupportToolkit.java +++ b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/JVMSupportToolkit.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -137,7 +137,7 @@ } /** - * Returns information about whether to server denoted by the handle supports Flight Recorder + * Returns information about whether the server supports Flight Recorder. * * @param handle * the server to check diff --git a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/ICommercialFeaturesService.java b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/ICommercialFeaturesService.java --- a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/ICommercialFeaturesService.java +++ b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/ICommercialFeaturesService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -52,4 +52,9 @@ */ void enableCommercialFeatures() throws Exception; + /** + * @return true if there are commercial features available, or false if this JVM doesn't have + * commercial features. + */ + boolean hasCommercialFeatures(); } diff --git a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/CommercialFeaturesServiceFactory.java b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/CommercialFeaturesServiceFactory.java --- a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/CommercialFeaturesServiceFactory.java +++ b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/CommercialFeaturesServiceFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -34,6 +34,7 @@ import org.openjdk.jmc.common.version.JavaVersion; import org.openjdk.jmc.rjmx.ConnectionException; +import org.openjdk.jmc.rjmx.ConnectionToolkit; import org.openjdk.jmc.rjmx.IConnectionHandle; import org.openjdk.jmc.rjmx.ServiceNotAvailableException; import org.openjdk.jmc.rjmx.services.ICommercialFeaturesService; @@ -52,10 +53,16 @@ if (descriptor != null) { JavaVersion version = new JavaVersion(descriptor.getJavaVersion()); if (version.getMajorVersion() >= 11) { - return new Jdk11CommercialFeaturesService(); + return new NoCommercialFeaturesService(); } } - return new HotSpot23CommercialFeaturesService(handle); + + // Funnily enough, OpenJDK built JVMs for unknown reasons also have the unlock commercial features flag, + // so we'll just check if Oracle is the JVM vendor. Any other vendor will not have JFR protected by commercial flags. + if (ConnectionToolkit.isOracle(handle)) { + return new HotSpot23CommercialFeaturesService(handle); + } + return new NoCommercialFeaturesService(); } @Override diff --git a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/HotSpot23CommercialFeaturesService.java b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/HotSpot23CommercialFeaturesService.java --- a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/HotSpot23CommercialFeaturesService.java +++ b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/HotSpot23CommercialFeaturesService.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -43,7 +43,7 @@ import javax.management.ObjectName; public class HotSpot23CommercialFeaturesService implements ICommercialFeaturesService { - private final static String VM_FLAG = "UnlockCommercialFeatures"; //$NON-NLS-1$ + private final static String UNLOCK_COMMERCIAL_FEATURES_FLAG = "UnlockCommercialFeatures"; //$NON-NLS-1$ private final static String UNLOCK_COMMAND = "VM.unlock_commercial_features"; //$NON-NLS-1$ private final MBeanServerConnection server; private final IDiagnosticCommandService dcs; @@ -54,7 +54,7 @@ server = handle.getServiceOrThrow(MBeanServerConnection.class); dcs = handle.getServiceOrNull(IDiagnosticCommandService.class); try { - HotspotManagementToolkit.getVMOption(server, VM_FLAG); // Will fail if option is not available + HotspotManagementToolkit.getVMOption(server, UNLOCK_COMMERCIAL_FEATURES_FLAG); // Will fail if option is not available } catch (Exception e) { // Commercial Feature option is not available but Flight Recorder is. if (!isJfrMBeanAvailable()) { @@ -66,7 +66,8 @@ @Override public boolean isCommercialFeaturesEnabled() { try { - return ((String) HotspotManagementToolkit.getVMOption(server, VM_FLAG)).contains("true"); //$NON-NLS-1$ + return ((String) HotspotManagementToolkit.getVMOption(server, UNLOCK_COMMERCIAL_FEATURES_FLAG)) + .contains("true"); //$NON-NLS-1$ } catch (Exception e) { return false; } @@ -78,7 +79,7 @@ dcs.runCtrlBreakHandlerWithResult(UNLOCK_COMMAND); } if (!isCommercialFeaturesEnabled()) { - HotspotManagementToolkit.setVMOption(server, VM_FLAG, "true"); //$NON-NLS-1$ + HotspotManagementToolkit.setVMOption(server, UNLOCK_COMMERCIAL_FEATURES_FLAG, "true"); //$NON-NLS-1$ } } @@ -96,4 +97,9 @@ server.getMBeanInfo(candidateObjectName); return candidateObjectName; } + + @Override + public boolean hasCommercialFeatures() { + return true; + } } diff --git a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/Jdk11CommercialFeaturesService.java b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/Jdk11CommercialFeaturesService.java deleted file mode 100644 --- a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/Jdk11CommercialFeaturesService.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2018, Oracle and/or its affiliates. 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 http://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.rjmx.services.internal; - -import org.openjdk.jmc.rjmx.services.ICommercialFeaturesService; - -public class Jdk11CommercialFeaturesService implements ICommercialFeaturesService { - - @Override - public boolean isCommercialFeaturesEnabled() { - return true; - } - - @Override - public void enableCommercialFeatures() throws Exception { - // Noop - } -} diff --git a/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/NoCommercialFeaturesService.java b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/NoCommercialFeaturesService.java new file mode 100644 --- /dev/null +++ b/application/org.openjdk.jmc.rjmx/src/main/java/org/openjdk/jmc/rjmx/services/internal/NoCommercialFeaturesService.java @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. 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 http://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.rjmx.services.internal; + +import org.openjdk.jmc.rjmx.services.ICommercialFeaturesService; + +/** + * Used by JVMs with no commercial features, e.g. OpenJDK 8 and JDK 11+ JVMs. + */ +public class NoCommercialFeaturesService implements ICommercialFeaturesService { + + @Override + public boolean isCommercialFeaturesEnabled() { + return true; + } + + @Override + public void enableCommercialFeatures() throws Exception { + // Noop + } + + @Override + public boolean hasCommercialFeatures() { + return false; + } +} diff --git a/application/org.openjdk.jmc.ui.common/src/main/java/org/openjdk/jmc/ui/common/jvm/JVMDescriptor.java b/application/org.openjdk.jmc.ui.common/src/main/java/org/openjdk/jmc/ui/common/jvm/JVMDescriptor.java --- a/application/org.openjdk.jmc.ui.common/src/main/java/org/openjdk/jmc/ui/common/jvm/JVMDescriptor.java +++ b/application/org.openjdk.jmc.ui.common/src/main/java/org/openjdk/jmc/ui/common/jvm/JVMDescriptor.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -38,6 +38,7 @@ public class JVMDescriptor { private final String javaVersion; private final JVMType jvmType; + private final String jvmVendor; private final JVMArch jvmArch; private final String javaCommand; private final String jvmArguments; @@ -46,13 +47,14 @@ private final Connectable connectable; public JVMDescriptor(String javaVersion, JVMType jvmType, JVMArch jvmArch, String javaCommand, String jvmArguments, - Integer pid, boolean debug, Connectable attachable) { + String jvmVendor, Integer pid, boolean debug, Connectable attachable) { super(); this.javaVersion = javaVersion; this.jvmType = jvmType; this.jvmArch = jvmArch; this.javaCommand = javaCommand; this.jvmArguments = jvmArguments; + this.jvmVendor = jvmVendor; this.pid = pid; this.debug = debug; connectable = attachable; @@ -78,6 +80,10 @@ return jvmArguments; } + public String getJvmVendor() { + return jvmVendor; + } + public Integer getPid() { return pid; } diff --git a/application/tests/org.openjdk.jmc.rjmx.test/src/test/java/org/openjdk/jmc/rjmx/test/JVMSupportToolkitTest.java b/application/tests/org.openjdk.jmc.rjmx.test/src/test/java/org/openjdk/jmc/rjmx/test/JVMSupportToolkitTest.java --- a/application/tests/org.openjdk.jmc.rjmx.test/src/test/java/org/openjdk/jmc/rjmx/test/JVMSupportToolkitTest.java +++ b/application/tests/org.openjdk.jmc.rjmx.test/src/test/java/org/openjdk/jmc/rjmx/test/JVMSupportToolkitTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -33,6 +33,7 @@ package org.openjdk.jmc.rjmx.test; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import org.junit.Test; import org.openjdk.jmc.rjmx.ConnectionDescriptorBuilder; @@ -46,7 +47,8 @@ @SuppressWarnings("nls") public class JVMSupportToolkitTest { - + private static final String VENDOR_OPEN_JDK = "OpenJDK"; + private static final String VENDOR_ORACLE = "Oracle"; // FIXME: Add tests for the methods that take IConnectionHandle as a parameter. private static final String SUPPORTED_MESSAGE = null; @@ -63,7 +65,8 @@ public void testJfr17U40HotSpotSupported() { ServerHandle server = new ServerHandle( new ServerDescriptor(null, null, - new JVMDescriptor("1.7.0_40", JVMType.HOTSPOT, JVMArch.UNKNOWN, null, null, null, false, null)), + new JVMDescriptor("1.7.0_40", JVMType.HOTSPOT, JVMArch.UNKNOWN, VENDOR_ORACLE, null, null, null, + false, null)), new ConnectionDescriptorBuilder().hostName("localhost").port(0).build(), null); String errorMessage = JVMSupportToolkit.checkFlightRecorderSupport(server, false); assertEquals(SUPPORTED_MESSAGE, errorMessage); @@ -73,7 +76,8 @@ public void testJfr17U4HotSpotNotFullySupported() { ServerHandle server = new ServerHandle( new ServerDescriptor(null, null, - new JVMDescriptor("1.7.0_04", JVMType.HOTSPOT, JVMArch.UNKNOWN, null, null, null, false, null)), + new JVMDescriptor("1.7.0_04", JVMType.HOTSPOT, JVMArch.UNKNOWN, VENDOR_ORACLE, null, null, null, + false, null)), new ConnectionDescriptorBuilder().hostName("localhost").port(0).build(), null); String errorMessage = JVMSupportToolkit.checkFlightRecorderSupport(server, false); assertEquals(Messages.JVMSupport_FLIGHT_RECORDER_NOT_FULLY_SUPPORTED_OLD_HOTSPOT, errorMessage); @@ -83,7 +87,8 @@ public void testJfr17HotSpotNotSupported() { ServerHandle server = new ServerHandle( new ServerDescriptor(null, null, - new JVMDescriptor("1.7.0", JVMType.HOTSPOT, JVMArch.UNKNOWN, null, null, null, false, null)), + new JVMDescriptor("1.7.0", JVMType.HOTSPOT, JVMArch.UNKNOWN, VENDOR_ORACLE, null, null, null, + false, null)), new ConnectionDescriptorBuilder().hostName("localhost").port(0).build(), null); String errorMessage = JVMSupportToolkit.checkFlightRecorderSupport(server, false); assertEquals(Messages.JVMSupport_FLIGHT_RECORDER_NOT_SUPPORTED_OLD_HOTSPOT, errorMessage); @@ -93,7 +98,8 @@ public void testJfrJRockitNotSupported() { ServerHandle server = new ServerHandle( new ServerDescriptor(null, null, - new JVMDescriptor("1.6", JVMType.JROCKIT, JVMArch.UNKNOWN, null, null, null, false, null)), + new JVMDescriptor("1.6", JVMType.JROCKIT, JVMArch.UNKNOWN, VENDOR_ORACLE, null, null, null, + false, null)), new ConnectionDescriptorBuilder().hostName("localhost").port(0).build(), null); String errorMessage = JVMSupportToolkit.checkFlightRecorderSupport(server, false); assertEquals(Messages.JVMSupport_JROCKIT_NO_LONGER_SUPPORTED, errorMessage); @@ -103,7 +109,8 @@ public void testJfrOldHotSpotNotSupported() { ServerHandle server = new ServerHandle( new ServerDescriptor(null, null, - new JVMDescriptor("1.6", JVMType.HOTSPOT, JVMArch.UNKNOWN, null, null, null, false, null)), + new JVMDescriptor("1.6", JVMType.HOTSPOT, JVMArch.UNKNOWN, VENDOR_ORACLE, null, null, null, + false, null)), new ConnectionDescriptorBuilder().hostName("localhost").port(0).build(), null); String errorMessage = JVMSupportToolkit.checkFlightRecorderSupport(server, false); assertEquals(Messages.JVMSupport_FLIGHT_RECORDER_NOT_SUPPORTED_OLD_HOTSPOT, errorMessage); @@ -112,8 +119,8 @@ @Test public void testJfrNonHotSpotNotSupported() { ServerHandle server = new ServerHandle( - new ServerDescriptor(null, null, - new JVMDescriptor("1.7", JVMType.OTHER, JVMArch.UNKNOWN, null, null, null, false, null)), + new ServerDescriptor(null, null, new JVMDescriptor("1.7", JVMType.OTHER, JVMArch.UNKNOWN, VENDOR_ORACLE, + null, null, null, false, null)), new ConnectionDescriptorBuilder().hostName("localhost").port(0).build(), null); String errorMessage = JVMSupportToolkit.checkFlightRecorderSupport(server, false); assertEquals(Messages.JVMSupport_FLIGHT_RECORDER_NOT_SUPPORTED_NOT_HOTSPOT, errorMessage); @@ -123,10 +130,32 @@ public void testJfrUnknownNoWarning() { ServerHandle server = new ServerHandle( new ServerDescriptor(null, null, - new JVMDescriptor("1.7", JVMType.UNKNOWN, JVMArch.UNKNOWN, null, null, null, false, null)), + new JVMDescriptor("1.7", JVMType.UNKNOWN, JVMArch.UNKNOWN, VENDOR_ORACLE, null, null, null, + false, null)), new ConnectionDescriptorBuilder().hostName("localhost").port(0).build(), null); String errorMessage = JVMSupportToolkit.checkFlightRecorderSupport(server, false); assertEquals(SUPPORTED_MESSAGE, errorMessage); } + @Test + public void testJfr8HotSpotOpenJDKSupported() { + ServerHandle server = new ServerHandle( + new ServerDescriptor(null, null, + new JVMDescriptor("1.8.0", JVMType.HOTSPOT, JVMArch.UNKNOWN, VENDOR_OPEN_JDK, null, null, null, + false, null)), + new ConnectionDescriptorBuilder().hostName("localhost").port(0).build(), null); + String errorMessage = JVMSupportToolkit.checkFlightRecorderSupport(server, false); + assertEquals(SUPPORTED_MESSAGE, errorMessage); + } + + @Test + public void testJdk7HotSpotOpenJDKNotSupported() { + ServerHandle server = new ServerHandle( + new ServerDescriptor(null, null, + new JVMDescriptor("1.7.0", JVMType.HOTSPOT, JVMArch.UNKNOWN, VENDOR_OPEN_JDK, null, null, null, + false, null)), + new ConnectionDescriptorBuilder().hostName("localhost").port(0).build(), null); + String errorMessage = JVMSupportToolkit.checkFlightRecorderSupport(server, false); + assertNotNull(errorMessage); + } } diff --git a/application/tests/org.openjdk.jmc.rjmx.test/src/test/java/org/openjdk/jmc/rjmx/test/services/CommercialFeaturesServiceTest.java b/application/tests/org.openjdk.jmc.rjmx.test/src/test/java/org/openjdk/jmc/rjmx/test/services/CommercialFeaturesServiceTest.java --- a/application/tests/org.openjdk.jmc.rjmx.test/src/test/java/org/openjdk/jmc/rjmx/test/services/CommercialFeaturesServiceTest.java +++ b/application/tests/org.openjdk.jmc.rjmx.test/src/test/java/org/openjdk/jmc/rjmx/test/services/CommercialFeaturesServiceTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2018, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved. * * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * @@ -36,7 +36,6 @@ import static org.junit.Assert.assertTrue; import org.junit.Test; - import org.openjdk.jmc.rjmx.ConnectionException; import org.openjdk.jmc.rjmx.IConnectionHandle; import org.openjdk.jmc.rjmx.services.ICommercialFeaturesService; @@ -63,18 +62,17 @@ public void testSetCommercialFeaturesState() throws Exception { ICommercialFeaturesService service = getCommercialFeaturesService(); // Check state. Any state is okay, but we want to catch exceptions. - if (!service.isCommercialFeaturesEnabled()) { + if (service.hasCommercialFeatures() && !service.isCommercialFeaturesEnabled()) { service.enableCommercialFeatures(); } - assertTrue("Commercial features should now be enabled!", service.isCommercialFeaturesEnabled()); + if (service.hasCommercialFeatures()) { + assertTrue("Commercial features should now be enabled!", service.isCommercialFeaturesEnabled()); + } } private ICommercialFeaturesService getCommercialFeaturesService() throws ConnectionException { - IConnectionHandle handle = getConnectionHandle(); - - // LocalRJMXTestToolkit.createDefaultConnectionHandle(getConnectionManager()); + IConnectionHandle handle = getDefaultServer().connect("Connection handle for test"); assumeHotSpot7u4OrLater(handle); - ICommercialFeaturesService service = handle.getServiceOrNull(ICommercialFeaturesService.class); assertNotNull( diff --git a/configuration/spotbugs/spotbugs-exclude.xml b/configuration/spotbugs/spotbugs-exclude.xml --- a/configuration/spotbugs/spotbugs-exclude.xml +++ b/configuration/spotbugs/spotbugs-exclude.xml @@ -566,6 +566,13 @@ + + + + + +