author | sjiang |
Fri, 17 Apr 2015 09:40:02 +0200 | |
changeset 30355 | e37c7eba132f |
parent 30354 | ca83b4cae363 |
child 30356 | a56e57aad51f |
--- a/jdk/make/lib/Lib-java.management.gmk Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/make/lib/Lib-java.management.gmk Fri Apr 17 09:40:02 2015 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -30,28 +30,14 @@ ################################################################################ -BUILD_LIBMANAGEMENT_SRC += $(JDK_TOPDIR)/src/java.management/share/native/libmanagement \ +LIBMANAGEMENT_SRC += $(JDK_TOPDIR)/src/java.management/share/native/libmanagement \ $(JDK_TOPDIR)/src/java.management/$(OPENJDK_TARGET_OS_TYPE)/native/libmanagement -BUILD_LIBMANAGEMENT_CFLAGS := -I$(JDK_TOPDIR)/src/java.management/share/native/include \ - $(addprefix -I,$(BUILD_LIBMANAGEMENT_SRC)) \ +LIBMANAGEMENT_CFLAGS := -I$(JDK_TOPDIR)/src/java.management/share/native/include \ + $(addprefix -I,$(LIBMANAGEMENT_SRC)) \ -I$(SUPPORT_OUTPUTDIR)/headers/java.management \ $(LIBJAVA_HEADER_FLAGS) \ # -BUILD_LIBMANAGEMENT_EXCLUDES := - -ifneq ($(OPENJDK_TARGET_OS), solaris) - BUILD_LIBMANAGEMENT_EXCLUDES += SolarisOperatingSystem.c -endif - -ifneq ($(OPENJDK_TARGET_OS), linux) - BUILD_LIBMANAGEMENT_EXCLUDES += LinuxOperatingSystem.c -endif - -ifneq ($(OPENJDK_TARGET_OS), macosx) - BUILD_LIBMANAGEMENT_EXCLUDES += MacosxOperatingSystem.c -endif - LIBMANAGEMENT_OPTIMIZATION := HIGH ifneq ($(findstring $(OPENJDK_TARGET_OS), solaris linux), ) ifeq ($(ENABLE_DEBUG_SYMBOLS), true) @@ -59,18 +45,14 @@ endif endif -# Make it possible to override this variable -LIBMANAGEMENT_MAPFILE ?= $(JDK_TOPDIR)/make/mapfiles/libmanagement/mapfile-vers - $(eval $(call SetupNativeCompilation,BUILD_LIBMANAGEMENT, \ LIBRARY := management, \ OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ - SRC := $(BUILD_LIBMANAGEMENT_SRC), \ - EXCLUDE_FILES := $(BUILD_LIBMANAGEMENT_EXCLUDES), \ + SRC := $(LIBMANAGEMENT_SRC), \ LANG := C, \ OPTIMIZATION := $(LIBMANAGEMENT_OPTIMIZATION), \ - CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) $(BUILD_LIBMANAGEMENT_CFLAGS), \ - MAPFILE := $(LIBMANAGEMENT_MAPFILE), \ + CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) $(LIBMANAGEMENT_CFLAGS), \ + MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libmanagement/mapfile-vers, \ LDFLAGS := $(LDFLAGS_JDKLIB) \ $(call SET_SHARED_LIBRARY_ORIGIN), \ LDFLAGS_solaris := -lkstat, \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/lib/Lib-jdk.management.gmk Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,75 @@ +# +# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +include LibCommon.gmk + +# Hook to include the corresponding custom file, if present. +$(eval $(call IncludeCustomExtension, jdk, lib/Lib-jdk.management.gmk)) + +################################################################################ + +LIBMANAGEMENT_EXT_SRC += $(JDK_TOPDIR)/src/jdk.management/share/native/libmanagement_ext \ + $(JDK_TOPDIR)/src/jdk.management/$(OPENJDK_TARGET_OS_TYPE)/native/libmanagement_ext \ + $(JDK_TOPDIR)/src/jdk.management/$(OPENJDK_TARGET_OS)/native/libmanagement_ext +LIBMANAGEMENT_EXT_CFLAGS := -I$(JDK_TOPDIR)/src/java.management/share/native/include \ + $(addprefix -I,$(LIBMANAGEMENT_EXT_SRC)) \ + -I$(SUPPORT_OUTPUTDIR)/headers/jdk.management \ + $(LIBJAVA_HEADER_FLAGS) \ + # + +LIBMANAGEMENT_EXT_OPTIMIZATION := HIGH +ifneq ($(findstring $(OPENJDK_TARGET_OS), solaris linux), ) + ifeq ($(ENABLE_DEBUG_SYMBOLS), true) + LIBMANAGEMENT_EXT_OPTIMIZATION := LOW + endif +endif + +$(eval $(call SetupNativeCompilation,BUILD_LIBMANAGEMENT_EXT, \ + LIBRARY := management_ext, \ + OUTPUT_DIR := $(INSTALL_LIBRARIES_HERE), \ + SRC := $(LIBMANAGEMENT_EXT_SRC), \ + LANG := C, \ + OPTIMIZATION := $(LIBMANAGEMENT_EXT_OPTIMIZATION), \ + CFLAGS := $(CFLAGS_JDKLIB) $(CFLAGS_WARNINGS_ARE_ERRORS) $(LIBMANAGEMENT_EXT_CFLAGS), \ + MAPFILE := $(JDK_TOPDIR)/make/mapfiles/libmanagement_ext/mapfile-vers, \ + LDFLAGS := $(LDFLAGS_JDKLIB) \ + $(call SET_SHARED_LIBRARY_ORIGIN), \ + LDFLAGS_solaris := -lkstat, \ + LDFLAGS_SUFFIX := $(LDFLAGS_JDKLIB_SUFFIX), \ + LDFLAGS_SUFFIX_windows := jvm.lib psapi.lib $(WIN_JAVA_LIB) advapi32.lib, \ + LDFLAGS_SUFFIX_aix := -lperfstat,\ + VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \ + RC_FLAGS := $(RC_FLAGS) \ + -D "JDK_FNAME=management_ext.dll" \ + -D "JDK_INTERNAL_NAME=management_ext" \ + -D "JDK_FTYPE=0x2L", \ + OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libmanagement_ext, \ + DEBUG_SYMBOLS := true)) + +$(BUILD_LIBMANAGEMENT_EXT): $(call FindLib, java.base, java) + +TARGETS += $(BUILD_LIBMANAGEMENT_EXT) + +################################################################################
--- a/jdk/make/mapfiles/libmanagement/mapfile-vers Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/make/mapfiles/libmanagement/mapfile-vers Fri Apr 17 09:40:02 2015 +0200 @@ -1,5 +1,5 @@ # -# Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. +# Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. # # This code is free software; you can redistribute it and/or modify it @@ -27,37 +27,10 @@ SUNWprivate_1.1 { global: - Java_sun_management_OperatingSystemImpl_getCommittedVirtualMemorySize0; - Java_sun_management_OperatingSystemImpl_getFreePhysicalMemorySize0; - Java_sun_management_OperatingSystemImpl_getFreeSwapSpaceSize0; - Java_sun_management_OperatingSystemImpl_getMaxFileDescriptorCount0; - Java_sun_management_OperatingSystemImpl_getOpenFileDescriptorCount0; - Java_sun_management_OperatingSystemImpl_getProcessCpuLoad0; - Java_sun_management_OperatingSystemImpl_getProcessCpuTime0; - Java_sun_management_OperatingSystemImpl_getSystemCpuLoad0; - Java_sun_management_OperatingSystemImpl_getTotalPhysicalMemorySize0; - Java_sun_management_OperatingSystemImpl_getTotalSwapSpaceSize0; - Java_sun_management_OperatingSystemImpl_initialize0; Java_sun_management_ClassLoadingImpl_setVerboseClass; - Java_sun_management_DiagnosticCommandImpl_executeDiagnosticCommand; - Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommands; - Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommandInfo; - Java_sun_management_DiagnosticCommandImpl_setNotificationEnabled; - Java_sun_management_FileSystemImpl_isAccessUserOnly0; - Java_sun_management_Flag_getAllFlagNames; - Java_sun_management_Flag_getFlags; - Java_sun_management_Flag_getInternalFlagCount; - Java_sun_management_Flag_initialize; - Java_sun_management_Flag_setLongValue; - Java_sun_management_Flag_setBooleanValue; - Java_sun_management_Flag_setStringValue; - Java_sun_management_GarbageCollectorImpl_getCollectionCount; + Java_sun_management_FileSystemImpl_isAccessUserOnly0; + Java_sun_management_GarbageCollectorImpl_getCollectionCount; Java_sun_management_GarbageCollectorImpl_getCollectionTime; - Java_sun_management_GarbageCollectorImpl_setNotificationEnabled; - Java_sun_management_GcInfoBuilder_fillGcAttributeInfo; - Java_sun_management_GcInfoBuilder_getLastGcInfo0; - Java_sun_management_GcInfoBuilder_getNumGcExtAttributes; - Java_sun_management_HotSpotDiagnostic_dumpHeap0; Java_sun_management_HotspotThread_getInternalThreadCount; Java_sun_management_HotspotThread_getInternalThreadTimes0; Java_sun_management_MemoryImpl_getMemoryManagers0;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/make/mapfiles/libmanagement_ext/mapfile-vers Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,60 @@ +# +# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# + +# Define library interface. + +SUNWprivate_1.1 { + global: + Java_com_sun_management_internal_OperatingSystemImpl_getCommittedVirtualMemorySize0; + Java_com_sun_management_internal_OperatingSystemImpl_getFreePhysicalMemorySize0; + Java_com_sun_management_internal_OperatingSystemImpl_getFreeSwapSpaceSize0; + Java_com_sun_management_internal_OperatingSystemImpl_getMaxFileDescriptorCount0; + Java_com_sun_management_internal_OperatingSystemImpl_getOpenFileDescriptorCount0; + Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0; + Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuTime0; + Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0; + Java_com_sun_management_internal_OperatingSystemImpl_getTotalPhysicalMemorySize0; + Java_com_sun_management_internal_OperatingSystemImpl_getTotalSwapSpaceSize0; + Java_com_sun_management_internal_OperatingSystemImpl_initialize0; + Java_com_sun_management_internal_DiagnosticCommandImpl_executeDiagnosticCommand; + Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommands; + Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommandInfo; + Java_com_sun_management_internal_DiagnosticCommandImpl_setNotificationEnabled; + Java_com_sun_management_internal_Flag_getAllFlagNames; + Java_com_sun_management_internal_Flag_getFlags; + Java_com_sun_management_internal_Flag_getInternalFlagCount; + Java_com_sun_management_internal_Flag_initialize; + Java_com_sun_management_internal_Flag_setLongValue; + Java_com_sun_management_internal_Flag_setBooleanValue; + Java_com_sun_management_internal_Flag_setStringValue; + Java_com_sun_management_internal_GarbageCollectorExtImpl_setNotificationEnabled; + Java_com_sun_management_internal_GcInfoBuilder_fillGcAttributeInfo; + Java_com_sun_management_internal_GcInfoBuilder_getLastGcInfo0; + Java_com_sun_management_internal_GcInfoBuilder_getNumGcExtAttributes; + Java_com_sun_management_internal_HotSpotDiagnostic_dumpHeap0; + JNI_OnLoad; + local: + *; +};
--- a/jdk/make/src/classes/build/tools/module/boot.modules Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/make/src/classes/build/tools/module/boot.modules Fri Apr 17 09:40:02 2015 +0200 @@ -22,6 +22,7 @@ jdk.hprof.agent jdk.httpserver jdk.jfr +jdk.management jdk.management.cmm jdk.naming.rmi jdk.sctp
--- a/jdk/src/java.management/share/classes/META-INF/services/sun.management.spi.PlatformMBeanProvider Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -# -# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. -# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. -# -# This code is free software; you can redistribute it and/or modify it -# under the terms of the GNU General Public License version 2 only, as -# published by the Free Software Foundation. Oracle designates this -# particular file as subject to the "Classpath" exception as provided -# by Oracle in the LICENSE file that accompanied this code. -# -# This code is distributed in the hope that it will be useful, but WITHOUT -# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or -# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -# version 2 for more details (a copy is included in the LICENSE file that -# accompanied this code). -# -# You should have received a copy of the GNU General Public License version -# 2 along with this work; if not, write to the Free Software Foundation, -# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. -# -# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA -# or visit www.oracle.com if you need additional information or have any -# questions. -# -com.sun.management.internal.PlatformMBeanProviderImpl
--- a/jdk/src/java.management/share/classes/com/sun/management/DiagnosticCommandMBean.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,220 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.management; - -import java.lang.management.PlatformManagedObject; -import javax.management.DynamicMBean; - -/** - * Management interface for the diagnostic commands for the HotSpot Virtual Machine. - * - * <p>The {@code DiagnosticCommandMBean} is registered to the - * {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer - * platform MBeanServer} as are other platform MBeans. - * - * <p>The {@link javax.management.ObjectName ObjectName} for uniquely identifying - * the diagnostic MBean within an MBeanServer is: - * <blockquote> - * {@code com.sun.management:type=DiagnosticCommand} - * </blockquote> - * - * <p>This MBean is a {@link javax.management.DynamicMBean DynamicMBean} - * and also a {@link javax.management.NotificationEmitter}. - * The {@code DiagnosticCommandMBean} is generated at runtime and is subject to - * modifications during the lifetime of the Java virtual machine. - * - * A <em>diagnostic command</em> is represented as an operation of - * the {@code DiagnosticCommandMBean} interface. Each diagnostic command has: - * <ul> - * <li>the diagnostic command name which is the name being referenced in - * the HotSpot Virtual Machine</li> - * <li>the MBean operation name which is the - * {@linkplain javax.management.MBeanOperationInfo#getName() name} - * generated for the diagnostic command operation invocation. - * The MBean operation name is implementation dependent</li> - * </ul> - * - * The recommended way to transform a diagnostic command name into a MBean - * operation name is as follows: - * <ul> - * <li>All characters from the first one to the first dot are set to be - * lower-case characters</li> - * <li>Every dot or underline character is removed and the following - * character is set to be an upper-case character</li> - * <li>All other characters are copied without modification</li> - * </ul> - * - * <p>The diagnostic command name is always provided with the meta-data on the - * operation in a field named {@code dcmd.name} (see below). - * - * <p>A diagnostic command may or may not support options or arguments. - * All the operations return {@code String} and either take - * no parameter for operations that do not support any option or argument, - * or take a {@code String[]} parameter for operations that support at least - * one option or argument. - * Each option or argument must be stored in a single String. - * Options or arguments split across several String instances are not supported. - * - * <p>The distinction between options and arguments: options are identified by - * the option name while arguments are identified by their position in the - * command line. Options and arguments are processed in the order of the array - * passed to the invocation method. - * - * <p>Like any operation of a dynamic MBean, each of these operations is - * described by {@link javax.management.MBeanOperationInfo MBeanOperationInfo} - * instance. Here's the values returned by this object: - * <ul> - * <li>{@link javax.management.MBeanOperationInfo#getName() getName()} - * returns the operation name generated from the diagnostic command name</li> - * <li>{@link javax.management.MBeanOperationInfo#getDescription() getDescription()} - * returns the diagnostic command description - * (the same as the one return in the 'help' command)</li> - * <li>{@link javax.management.MBeanOperationInfo#getImpact() getImpact()} - * returns <code>ACTION_INFO</code></li> - * <li>{@link javax.management.MBeanOperationInfo#getReturnType() getReturnType()} - * returns {@code java.lang.String}</li> - * <li>{@link javax.management.MBeanOperationInfo#getDescriptor() getDescriptor()} - * returns a Descriptor instance (see below)</li> - * </ul> - * - * <p>The {@link javax.management.Descriptor Descriptor} - * is a collection of fields containing additional - * meta-data for a JMX element. A field is a name and an associated value. - * The additional meta-data provided for an operation associated with a - * diagnostic command are described in the table below: - * <p> - * - * <table border="1" cellpadding="5"> - * <tr> - * <th>Name</th><th>Type</th><th>Description</th> - * </tr> - * <tr> - * <td>dcmd.name</td><td>String</td> - * <td>The original diagnostic command name (not the operation name)</td> - * </tr> - * <tr> - * <td>dcmd.description</td><td>String</td> - * <td>The diagnostic command description</td> - * </tr> - * <tr> - * <td>dcmd.help</td><td>String</td> - * <td>The full help message for this diagnostic command (same output as - * the one produced by the 'help' command)</td> - * </tr> - * <tr> - * <td>dcmd.vmImpact</td><td>String</td> - * <td>The impact of the diagnostic command, - * this value is the same as the one printed in the 'impact' - * section of the help message of the diagnostic command, and it - * is different from the getImpact() of the MBeanOperationInfo</td> - * </tr> - * <tr> - * <td>dcmd.enabled</td><td>boolean</td> - * <td>True if the diagnostic command is enabled, false otherwise</td> - * </tr> - * <tr> - * <td>dcmd.permissionClass</td><td>String</td> - * <td>Some diagnostic command might require a specific permission to be - * executed, in addition to the MBeanPermission to invoke their - * associated MBean operation. This field returns the fully qualified - * name of the permission class or null if no permission is required - * </td> - * </tr> - * <tr> - * <td>dcmd.permissionName</td><td>String</td> - * <td>The fist argument of the permission required to execute this - * diagnostic command or null if no permission is required</td> - * </tr> - * <tr> - * <td>dcmd.permissionAction</td><td>String</td> - * <td>The second argument of the permission required to execute this - * diagnostic command or null if the permission constructor has only - * one argument (like the ManagementPermission) or if no permission - * is required</td> - * </tr> - * <tr> - * <td>dcmd.arguments</td><td>Descriptor</td> - * <td>A Descriptor instance containing the descriptions of options and - * arguments supported by the diagnostic command (see below)</td> - * </tr> - * </table> - * <p> - * - * <p>The description of parameters (options or arguments) of a diagnostic - * command is provided within a Descriptor instance. In this Descriptor, - * each field name is a parameter name, and each field value is itself - * a Descriptor instance. The fields provided in this second Descriptor - * instance are described in the table below: - * - * <table border="1" cellpadding="5"> - * <tr> - * <th>Name</th><th>Type</th><th>Description</th> - * </tr> - * <tr> - * <td>dcmd.arg.name</td><td>String</td> - * <td>The name of the parameter</td> - * </tr> - * <tr> - * <td>dcmd.arg.type</td><td>String</td> - * <td>The type of the parameter. The returned String is the name of a type - * recognized by the diagnostic command parser. These types are not - * Java types and are implementation dependent. - * </td> - * </tr> - * <tr> - * <td>dcmd.arg.description</td><td>String</td> - * <td>The parameter description</td> - * </tr> - * <tr> - * <td>dcmd.arg.isMandatory</td><td>boolean</td> - * <td>True if the parameter is mandatory, false otherwise</td> - * </tr> - * <tr> - * <td>dcmd.arg.isOption</td><td>boolean</td> - * <td>True if the parameter is an option, false if it is an argument</td> - * </tr> - * <tr> - * <td>dcmd.arg.isMultiple</td><td>boolean</td> - * <td>True if the parameter can be specified several times, false - * otherwise</td> - * </tr> - * </table> - * - * <p>When the set of diagnostic commands currently supported by the Java - * Virtual Machine is modified, the {@code DiagnosticCommandMBean} emits - * a {@link javax.management.Notification} with a - * {@linkplain javax.management.Notification#getType() type} of - * <a href="{@docRoot}/../../../../api/javax/management/MBeanInfo.html#info-changed"> - * {@code "jmx.mbean.info.changed"}</a> and a - * {@linkplain javax.management.Notification#getUserData() userData} that - * is the new {@code MBeanInfo}. - * - * @since 1.8 - */ -public interface DiagnosticCommandMBean extends DynamicMBean -{ - -}
--- a/jdk/src/java.management/share/classes/com/sun/management/GarbageCollectionNotificationInfo.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.management; - -import javax.management.Notification; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataView; -import javax.management.openmbean.CompositeType; -import java.util.Collection; -import java.util.Collections; -import sun.management.GarbageCollectionNotifInfoCompositeData; - -/** - * The information about a garbage collection - * - * <p> - * A garbage collection notification is emitted by {@link GarbageCollectorMXBean} - * when the Java virtual machine completes a garbage collection action - * The notification emitted will contain the garbage collection notification - * information about the status of the memory: - * <u1> - * <li>The name of the garbage collector used to perform the collection.</li> - * <li>The action performed by the garbage collector.</li> - * <li>The cause of the garbage collection action.</li> - * <li>A {@link GcInfo} object containing some statistics about the GC cycle - (start time, end time) and the memory usage before and after - the GC cycle.</li> - * </u1> - * - * <p> - * A {@link CompositeData CompositeData} representing - * the {@code GarbageCollectionNotificationInfo} object - * is stored in the - * {@linkplain javax.management.Notification#setUserData userdata} - * of a {@linkplain javax.management.Notification notification}. - * The {@link #from from} method is provided to convert from - * a {@code CompositeData} to a {@code GarbageCollectionNotificationInfo} - * object. For example: - * - * <blockquote><pre> - * Notification notif; - * - * // receive the notification emitted by a GarbageCollectorMXBean and set to notif - * ... - * - * String notifType = notif.getType(); - * if (notifType.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) { - * // retrieve the garbage collection notification information - * CompositeData cd = (CompositeData) notif.getUserData(); - * GarbageCollectionNotificationInfo info = GarbageCollectionNotificationInfo.from(cd); - * .... - * } - * </pre></blockquote> - * - * <p> - * The type of the notification emitted by a {@code GarbageCollectorMXBean} is: - * <ul> - * <li>A {@linkplain #GARBAGE_COLLECTION_NOTIFICATION garbage collection notification}. - * <br>Used by every notification emitted by the garbage collector, the details about - * the notification are provided in the {@linkplain #getGcAction action} String - * <p></li> - * </ul> - **/ - -@jdk.Exported -public class GarbageCollectionNotificationInfo implements CompositeDataView { - - private final String gcName; - private final String gcAction; - private final String gcCause; - private final GcInfo gcInfo; - private final CompositeData cdata; - - /** - * Notification type denoting that - * the Java virtual machine has completed a garbage collection cycle. - * This notification is emitted by a {@link GarbageCollectorMXBean}. - * The value of this notification type is - * {@code com.sun.management.gc.notification}. - */ - public static final String GARBAGE_COLLECTION_NOTIFICATION = - "com.sun.management.gc.notification"; - - /** - * Constructs a {@code GarbageCollectionNotificationInfo} object. - * - * @param gcName The name of the garbage collector used to perform the collection - * @param gcAction The name of the action performed by the garbage collector - * @param gcCause The cause of the garbage collection action - * @param gcInfo a GcInfo object providing statistics about the GC cycle - */ - public GarbageCollectionNotificationInfo(String gcName, - String gcAction, - String gcCause, - GcInfo gcInfo) { - if (gcName == null) { - throw new NullPointerException("Null gcName"); - } - if (gcAction == null) { - throw new NullPointerException("Null gcAction"); - } - if (gcCause == null) { - throw new NullPointerException("Null gcCause"); - } - this.gcName = gcName; - this.gcAction = gcAction; - this.gcCause = gcCause; - this.gcInfo = gcInfo; - this.cdata = new GarbageCollectionNotifInfoCompositeData(this); - } - - GarbageCollectionNotificationInfo(CompositeData cd) { - GarbageCollectionNotifInfoCompositeData.validateCompositeData(cd); - - this.gcName = GarbageCollectionNotifInfoCompositeData.getGcName(cd); - this.gcAction = GarbageCollectionNotifInfoCompositeData.getGcAction(cd); - this.gcCause = GarbageCollectionNotifInfoCompositeData.getGcCause(cd); - this.gcInfo = GarbageCollectionNotifInfoCompositeData.getGcInfo(cd); - this.cdata = cd; - } - - /** - * Returns the name of the garbage collector used to perform the collection - * - * @return the name of the garbage collector used to perform the collection - */ - public String getGcName() { - return gcName; - } - - /** - * Returns the action performed by the garbage collector - * - * @return the action performed by the garbage collector - */ - public String getGcAction() { - return gcAction; - } - - /** - * Returns the cause of the garbage collection - * - * @return the cause of the garbage collection - */ - public String getGcCause() { - return gcCause; - } - - /** - * Returns the GC information related to the last garbage collection - * - * @return the GC information related to the - * last garbage collection - */ - public GcInfo getGcInfo() { - return gcInfo; - } - - /** - * Returns a {@code GarbageCollectionNotificationInfo} object represented by the - * given {@code CompositeData}. - * The given {@code CompositeData} must contain - * the following attributes: - * <blockquote> - * <table border> - * <tr> - * <th align=left>Attribute Name</th> - * <th align=left>Type</th> - * </tr> - * <tr> - * <td>gcName</td> - * <td>{@code java.lang.String}</td> - * </tr> - * <tr> - * <td>gcAction</td> - * <td>{@code java.lang.String}</td> - * </tr> - * <tr> - * <td>gcCause</td> - * <td>{@code java.lang.String}</td> - * </tr> - * <tr> - * <td>gcInfo</td> - * <td>{@code javax.management.openmbean.CompositeData}</td> - * </tr> - * </table> - * </blockquote> - * - * @param cd {@code CompositeData} representing a - * {@code GarbageCollectionNotificationInfo} - * - * @throws IllegalArgumentException if {@code cd} does not - * represent a {@code GarbaageCollectionNotificationInfo} object. - * - * @return a {@code GarbageCollectionNotificationInfo} object represented - * by {@code cd} if {@code cd} is not {@code null}; - * {@code null} otherwise. - */ - public static GarbageCollectionNotificationInfo from(CompositeData cd) { - if (cd == null) { - return null; - } - - if (cd instanceof GarbageCollectionNotifInfoCompositeData) { - return ((GarbageCollectionNotifInfoCompositeData) cd).getGarbageCollectionNotifInfo(); - } else { - return new GarbageCollectionNotificationInfo(cd); - } - } - - public CompositeData toCompositeData(CompositeType ct) { - return cdata; - } - -}
--- a/jdk/src/java.management/share/classes/com/sun/management/GarbageCollectorMXBean.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.management; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeType; - -/** - * Platform-specific management interface for a garbage collector - * which performs collections in cycles. - * - * <p> This platform extension is only available to the garbage - * collection implementation that supports this extension. - * - * @author Mandy Chung - * @since 1.5 - */ -@jdk.Exported -public interface GarbageCollectorMXBean - extends java.lang.management.GarbageCollectorMXBean { - - /** - * Returns the GC information about the most recent GC. - * This method returns a {@link GcInfo}. - * If no GC information is available, <tt>null</tt> is returned. - * The collector-specific attributes, if any, can be obtained - * via the {@link CompositeData CompositeData} interface. - * <p> - * <b>MBeanServer access:</b> - * The mapped type of <tt>GcInfo</tt> is <tt>CompositeData</tt> - * with attributes specified in {@link GcInfo#from GcInfo}. - * - * @return a <tt>GcInfo</tt> object representing - * the most GC information; or <tt>null</tt> if no GC - * information available. - */ - public GcInfo getLastGcInfo(); -}
--- a/jdk/src/java.management/share/classes/com/sun/management/GcInfo.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,289 +0,0 @@ -/* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.management; - -import java.lang.management.MemoryUsage; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataView; -import javax.management.openmbean.CompositeType; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; -import java.util.List; -import sun.management.GcInfoCompositeData; -import sun.management.GcInfoBuilder; - -/** - * Garbage collection information. It contains the following - * information for one garbage collection as well as GC-specific - * attributes: - * <blockquote> - * <ul> - * <li>Start time</li> - * <li>End time</li> - * <li>Duration</li> - * <li>Memory usage before the collection starts</li> - * <li>Memory usage after the collection ends</li> - * </ul> - * </blockquote> - * - * <p> - * <tt>GcInfo</tt> is a {@link CompositeData CompositeData} - * The GC-specific attributes can be obtained via the CompositeData - * interface. This is a historical relic, and other classes should - * not copy this pattern. Use {@link CompositeDataView} instead. - * - * <h4>MXBean Mapping</h4> - * <tt>GcInfo</tt> is mapped to a {@link CompositeData CompositeData} - * with attributes as specified in the {@link #from from} method. - * - * @author Mandy Chung - * @since 1.5 - */ -@jdk.Exported -public class GcInfo implements CompositeData, CompositeDataView { - private final long index; - private final long startTime; - private final long endTime; - private final Map<String, MemoryUsage> usageBeforeGc; - private final Map<String, MemoryUsage> usageAfterGc; - private final Object[] extAttributes; - private final CompositeData cdata; - private final GcInfoBuilder builder; - - private GcInfo(GcInfoBuilder builder, - long index, long startTime, long endTime, - MemoryUsage[] muBeforeGc, - MemoryUsage[] muAfterGc, - Object[] extAttributes) { - this.builder = builder; - this.index = index; - this.startTime = startTime; - this.endTime = endTime; - String[] poolNames = builder.getPoolNames(); - this.usageBeforeGc = new HashMap<String, MemoryUsage>(poolNames.length); - this.usageAfterGc = new HashMap<String, MemoryUsage>(poolNames.length); - for (int i = 0; i < poolNames.length; i++) { - this.usageBeforeGc.put(poolNames[i], muBeforeGc[i]); - this.usageAfterGc.put(poolNames[i], muAfterGc[i]); - } - this.extAttributes = extAttributes; - this.cdata = new GcInfoCompositeData(this, builder, extAttributes); - } - - private GcInfo(CompositeData cd) { - GcInfoCompositeData.validateCompositeData(cd); - - this.index = GcInfoCompositeData.getId(cd); - this.startTime = GcInfoCompositeData.getStartTime(cd); - this.endTime = GcInfoCompositeData.getEndTime(cd); - this.usageBeforeGc = GcInfoCompositeData.getMemoryUsageBeforeGc(cd); - this.usageAfterGc = GcInfoCompositeData.getMemoryUsageAfterGc(cd); - this.extAttributes = null; - this.builder = null; - this.cdata = cd; - } - - /** - * Returns the identifier of this garbage collection which is - * the number of collections that this collector has done. - * - * @return the identifier of this garbage collection which is - * the number of collections that this collector has done. - */ - public long getId() { - return index; - } - - /** - * Returns the start time of this GC in milliseconds - * since the Java virtual machine was started. - * - * @return the start time of this GC. - */ - public long getStartTime() { - return startTime; - } - - /** - * Returns the end time of this GC in milliseconds - * since the Java virtual machine was started. - * - * @return the end time of this GC. - */ - public long getEndTime() { - return endTime; - } - - /** - * Returns the elapsed time of this GC in milliseconds. - * - * @return the elapsed time of this GC in milliseconds. - */ - public long getDuration() { - return endTime - startTime; - } - - /** - * Returns the memory usage of all memory pools - * at the beginning of this GC. - * This method returns - * a <tt>Map</tt> of the name of a memory pool - * to the memory usage of the corresponding - * memory pool before GC starts. - * - * @return a <tt>Map</tt> of memory pool names to the memory - * usage of a memory pool before GC starts. - */ - public Map<String, MemoryUsage> getMemoryUsageBeforeGc() { - return Collections.unmodifiableMap(usageBeforeGc); - } - - /** - * Returns the memory usage of all memory pools - * at the end of this GC. - * This method returns - * a <tt>Map</tt> of the name of a memory pool - * to the memory usage of the corresponding - * memory pool when GC finishes. - * - * @return a <tt>Map</tt> of memory pool names to the memory - * usage of a memory pool when GC finishes. - */ - public Map<String, MemoryUsage> getMemoryUsageAfterGc() { - return Collections.unmodifiableMap(usageAfterGc); - } - - /** - * Returns a <tt>GcInfo</tt> object represented by the - * given <tt>CompositeData</tt>. The given - * <tt>CompositeData</tt> must contain - * all the following attributes: - * - * <p> - * <blockquote> - * <table border> - * <tr> - * <th align=left>Attribute Name</th> - * <th align=left>Type</th> - * </tr> - * <tr> - * <td>index</td> - * <td><tt>java.lang.Long</tt></td> - * </tr> - * <tr> - * <td>startTime</td> - * <td><tt>java.lang.Long</tt></td> - * </tr> - * <tr> - * <td>endTime</td> - * <td><tt>java.lang.Long</tt></td> - * </tr> - * <tr> - * <td>memoryUsageBeforeGc</td> - * <td><tt>javax.management.openmbean.TabularData</tt></td> - * </tr> - * <tr> - * <td>memoryUsageAfterGc</td> - * <td><tt>javax.management.openmbean.TabularData</tt></td> - * </tr> - * </table> - * </blockquote> - * - * @throws IllegalArgumentException if <tt>cd</tt> does not - * represent a <tt>GcInfo</tt> object with the attributes - * described above. - * - * @return a <tt>GcInfo</tt> object represented by <tt>cd</tt> - * if <tt>cd</tt> is not <tt>null</tt>; <tt>null</tt> otherwise. - */ - public static GcInfo from(CompositeData cd) { - if (cd == null) { - return null; - } - - if (cd instanceof GcInfoCompositeData) { - return ((GcInfoCompositeData) cd).getGcInfo(); - } else { - return new GcInfo(cd); - } - - } - - // Implementation of the CompositeData interface - public boolean containsKey(String key) { - return cdata.containsKey(key); - } - - public boolean containsValue(Object value) { - return cdata.containsValue(value); - } - - public boolean equals(Object obj) { - return cdata.equals(obj); - } - - public Object get(String key) { - return cdata.get(key); - } - - public Object[] getAll(String[] keys) { - return cdata.getAll(keys); - } - - public CompositeType getCompositeType() { - return cdata.getCompositeType(); - } - - public int hashCode() { - return cdata.hashCode(); - } - - public String toString() { - return cdata.toString(); - } - - public Collection<?> values() { - return cdata.values(); - } - - /** - * <p>Return the {@code CompositeData} representation of this - * {@code GcInfo}, including any GC-specific attributes. The - * returned value will have at least all the attributes described - * in the {@link #from(CompositeData) from} method, plus optionally - * other attributes. - * - * @param ct the {@code CompositeType} that the caller expects. - * This parameter is ignored and can be null. - * - * @return the {@code CompositeData} representation. - */ - public CompositeData toCompositeData(CompositeType ct) { - return cdata; - } -}
--- a/jdk/src/java.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,119 +0,0 @@ -/* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.management; - -import java.lang.management.PlatformManagedObject; - -/** - * Diagnostic management interface for the HotSpot Virtual Machine. - * - * <p>The diagnostic MBean is registered to the platform MBeanServer - * as are other platform MBeans. - * - * <p>The <tt>ObjectName</tt> for uniquely identifying the diagnostic - * MXBean within an MBeanServer is: - * <blockquote> - * <tt>com.sun.management:type=HotSpotDiagnostic</tt> - * </blockquote> -.* - * It can be obtained by calling the - * {@link PlatformManagedObject#getObjectName} method. - * - * All methods throw a {@code NullPointerException} if any input argument is - * {@code null} unless it's stated otherwise. - * - * @see java.lang.management.ManagementFactory#getPlatformMXBeans(Class) - */ -@jdk.Exported -public interface HotSpotDiagnosticMXBean extends PlatformManagedObject { - /** - * Dumps the heap to the <tt>outputFile</tt> file in the same - * format as the hprof heap dump. - * <p> - * If this method is called remotely from another process, - * the heap dump output is written to a file named <tt>outputFile</tt> - * on the machine where the target VM is running. If outputFile is - * a relative path, it is relative to the working directory where - * the target VM was started. - * - * @param outputFile the system-dependent filename - * @param live if <tt>true</tt> dump only <i>live</i> objects - * i.e. objects that are reachable from others - * @throws IOException if the <tt>outputFile</tt> - * cannot be created, opened, or written to. - * @throws UnsupportedOperationException if this operation is not supported. - * @throws NullPointerException if <tt>outputFile</tt> is <tt>null</tt>. - * @throws SecurityException - * If a security manager exists and its {@link - * java.lang.SecurityManager#checkWrite(java.lang.String)} - * method denies write access to the named file - * or the caller does not have ManagmentPermission("control"). - */ - public void dumpHeap(String outputFile, boolean live) throws java.io.IOException; - - /** - * Returns a list of <tt>VMOption</tt> objects for all diagnostic options. - * A diagnostic option is a {@link VMOption#isWriteable writeable} - * VM option that can be set dynamically mainly for troubleshooting - * and diagnosis. - * - * @return a list of <tt>VMOption</tt> objects for all diagnostic options. - */ - public java.util.List<VMOption> getDiagnosticOptions(); - - /** - * Returns a <tt>VMOption</tt> object for a VM option of the given - * name. - * - * @return a <tt>VMOption</tt> object for a VM option of the given name. - * @throws NullPointerException if name is <tt>null</tt>. - * @throws IllegalArgumentException if a VM option of the given name - * does not exist. - */ - public VMOption getVMOption(String name); - - /** - * Sets a VM option of the given name to the specified value. - * The new value will be reflected in a new <tt>VMOption</tt> - * object returned by the {@link #getVMOption} method or - * the {@link #getDiagnosticOptions} method. This method does - * not change the value of this <tt>VMOption</tt> object. - * - * @param name Name of a VM option - * @param value New value of the VM option to be set - * - * @throws IllegalArgumentException if the VM option of the given name - * does not exist. - * @throws IllegalArgumentException if the new value is invalid. - * @throws IllegalArgumentException if the VM option is not writable. - * @throws NullPointerException if name or value is <tt>null</tt>. - * - * @throws java.lang.SecurityException - * if a security manager exists and the caller does not have - * ManagementPermission("control"). - */ - public void setVMOption(String name, String value); -}
--- a/jdk/src/java.management/share/classes/com/sun/management/OperatingSystemMXBean.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.management; - -/** - * Platform-specific management interface for the operating system - * on which the Java virtual machine is running. - * - * <p> - * The <tt>OperatingSystemMXBean</tt> object returned by - * {@link java.lang.management.ManagementFactory#getOperatingSystemMXBean()} - * is an instance of the implementation class of this interface - * or {@link UnixOperatingSystemMXBean} interface depending on - * its underlying operating system. - * - * @author Mandy Chung - * @since 1.5 - */ -@jdk.Exported -public interface OperatingSystemMXBean extends - java.lang.management.OperatingSystemMXBean { - - /** - * Returns the amount of virtual memory that is guaranteed to - * be available to the running process in bytes, - * or <tt>-1</tt> if this operation is not supported. - * - * @return the amount of virtual memory that is guaranteed to - * be available to the running process in bytes, - * or <tt>-1</tt> if this operation is not supported. - */ - public long getCommittedVirtualMemorySize(); - - /** - * Returns the total amount of swap space in bytes. - * - * @return the total amount of swap space in bytes. - */ - public long getTotalSwapSpaceSize(); - - /** - * Returns the amount of free swap space in bytes. - * - * @return the amount of free swap space in bytes. - */ - public long getFreeSwapSpaceSize(); - - /** - * Returns the CPU time used by the process on which the Java - * virtual machine is running in nanoseconds. The returned value - * is of nanoseconds precision but not necessarily nanoseconds - * accuracy. This method returns <tt>-1</tt> if the - * the platform does not support this operation. - * - * @return the CPU time used by the process in nanoseconds, - * or <tt>-1</tt> if this operation is not supported. - */ - public long getProcessCpuTime(); - - /** - * Returns the amount of free physical memory in bytes. - * - * @return the amount of free physical memory in bytes. - */ - public long getFreePhysicalMemorySize(); - - /** - * Returns the total amount of physical memory in bytes. - * - * @return the total amount of physical memory in bytes. - */ - public long getTotalPhysicalMemorySize(); - - /** - * Returns the "recent cpu usage" for the whole system. This value is a - * double in the [0.0,1.0] interval. A value of 0.0 means that all CPUs - * were idle during the recent period of time observed, while a value - * of 1.0 means that all CPUs were actively running 100% of the time - * during the recent period being observed. All values betweens 0.0 and - * 1.0 are possible depending of the activities going on in the system. - * If the system recent cpu usage is not available, the method returns a - * negative value. - * - * @return the "recent cpu usage" for the whole system; a negative - * value if not available. - * @since 1.7 - */ - public double getSystemCpuLoad(); - - /** - * Returns the "recent cpu usage" for the Java Virtual Machine process. - * This value is a double in the [0.0,1.0] interval. A value of 0.0 means - * that none of the CPUs were running threads from the JVM process during - * the recent period of time observed, while a value of 1.0 means that all - * CPUs were actively running threads from the JVM 100% of the time - * during the recent period being observed. Threads from the JVM include - * the application threads as well as the JVM internal threads. All values - * betweens 0.0 and 1.0 are possible depending of the activities going on - * in the JVM process and the whole system. If the Java Virtual Machine - * recent CPU usage is not available, the method returns a negative value. - * - * @return the "recent cpu usage" for the Java Virtual Machine process; - * a negative value if not available. - * @since 1.7 - */ - public double getProcessCpuLoad(); - -}
--- a/jdk/src/java.management/share/classes/com/sun/management/ThreadMXBean.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,222 +0,0 @@ -/* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.management; - -import java.util.Map; - -/** - * Platform-specific management interface for the thread system - * of the Java virtual machine. - * <p> - * This platform extension is only available to a thread - * implementation that supports this extension. - * - * @author Paul Hohensee - * @since 6u25 - */ - -@jdk.Exported -public interface ThreadMXBean extends java.lang.management.ThreadMXBean { - /** - * Returns the total CPU time for each thread whose ID is - * in the input array {@code ids} in nanoseconds. - * The returned values are of nanoseconds precision but - * not necessarily nanoseconds accuracy. - * <p> - * This method is equivalent to calling the - * {@link ThreadMXBean#getThreadCpuTime(long)} - * method for each thread ID in the input array {@code ids} and setting the - * returned value in the corresponding element of the returned array. - * - * @param ids an array of thread IDs. - * @return an array of long values, each of which is the amount of CPU - * time the thread whose ID is in the corresponding element of the input - * array of IDs has used, - * if the thread of a specified ID exists, the thread is alive, - * and CPU time measurement is enabled; - * {@code -1} otherwise. - * - * @throws NullPointerException if {@code ids} is {@code null} - * @throws IllegalArgumentException if any element in the input array - * {@code ids} is {@code <=} {@code 0}. - * @throws java.lang.UnsupportedOperationException if the Java - * virtual machine implementation does not support CPU time - * measurement. - * - * @see ThreadMXBean#getThreadCpuTime(long) - * @see #getThreadUserTime - * @see ThreadMXBean#isThreadCpuTimeSupported - * @see ThreadMXBean#isThreadCpuTimeEnabled - * @see ThreadMXBean#setThreadCpuTimeEnabled - */ - public long[] getThreadCpuTime(long[] ids); - - /** - * Returns the CPU time that each thread whose ID is in the input array - * {@code ids} has executed in user mode in nanoseconds. - * The returned values are of nanoseconds precision but - * not necessarily nanoseconds accuracy. - * <p> - * This method is equivalent to calling the - * {@link ThreadMXBean#getThreadUserTime(long)} - * method for each thread ID in the input array {@code ids} and setting the - * returned value in the corresponding element of the returned array. - * - * @param ids an array of thread IDs. - * @return an array of long values, each of which is the amount of user - * mode CPU time the thread whose ID is in the corresponding element of - * the input array of IDs has used, - * if the thread of a specified ID exists, the thread is alive, - * and CPU time measurement is enabled; - * {@code -1} otherwise. - * - * @throws NullPointerException if {@code ids} is {@code null} - * @throws IllegalArgumentException if any element in the input array - * {@code ids} is {@code <=} {@code 0}. - * @throws java.lang.UnsupportedOperationException if the Java - * virtual machine implementation does not support CPU time - * measurement. - * - * @see ThreadMXBean#getThreadUserTime(long) - * @see #getThreadCpuTime - * @see ThreadMXBean#isThreadCpuTimeSupported - * @see ThreadMXBean#isThreadCpuTimeEnabled - * @see ThreadMXBean#setThreadCpuTimeEnabled - */ - public long[] getThreadUserTime(long[] ids); - - /** - * Returns an approximation of the total amount of memory, in bytes, - * allocated in heap memory for the thread of the specified ID. - * The returned value is an approximation because some Java virtual machine - * implementations may use object allocation mechanisms that result in a - * delay between the time an object is allocated and the time its size is - * recorded. - * <p> - * If the thread of the specified ID is not alive or does not exist, - * this method returns {@code -1}. If thread memory allocation measurement - * is disabled, this method returns {@code -1}. - * A thread is alive if it has been started and has not yet died. - * <p> - * If thread memory allocation measurement is enabled after the thread has - * started, the Java virtual machine implementation may choose any time up - * to and including the time that the capability is enabled as the point - * where thread memory allocation measurement starts. - * - * @param id the thread ID of a thread - * @return an approximation of the total memory allocated, in bytes, in - * heap memory for a thread of the specified ID - * if the thread of the specified ID exists, the thread is alive, - * and thread memory allocation measurement is enabled; - * {@code -1} otherwise. - * - * @throws IllegalArgumentException if {@code id} {@code <=} {@code 0}. - * @throws java.lang.UnsupportedOperationException if the Java virtual - * machine implementation does not support thread memory allocation - * measurement. - * - * @see #isThreadAllocatedMemorySupported - * @see #isThreadAllocatedMemoryEnabled - * @see #setThreadAllocatedMemoryEnabled - */ - public long getThreadAllocatedBytes(long id); - - /** - * Returns an approximation of the total amount of memory, in bytes, - * allocated in heap memory for each thread whose ID is in the input - * array {@code ids}. - * The returned values are approximations because some Java virtual machine - * implementations may use object allocation mechanisms that result in a - * delay between the time an object is allocated and the time its size is - * recorded. - * <p> - * This method is equivalent to calling the - * {@link #getThreadAllocatedBytes(long)} - * method for each thread ID in the input array {@code ids} and setting the - * returned value in the corresponding element of the returned array. - * - * @param ids an array of thread IDs. - * @return an array of long values, each of which is an approximation of - * the total memory allocated, in bytes, in heap memory for the thread - * whose ID is in the corresponding element of the input array of IDs. - * - * @throws NullPointerException if {@code ids} is {@code null} - * @throws IllegalArgumentException if any element in the input array - * {@code ids} is {@code <=} {@code 0}. - * @throws java.lang.UnsupportedOperationException if the Java virtual - * machine implementation does not support thread memory allocation - * measurement. - * - * @see #getThreadAllocatedBytes(long) - * @see #isThreadAllocatedMemorySupported - * @see #isThreadAllocatedMemoryEnabled - * @see #setThreadAllocatedMemoryEnabled - */ - public long[] getThreadAllocatedBytes(long[] ids); - - /** - * Tests if the Java virtual machine implementation supports thread memory - * allocation measurement. - * - * @return - * {@code true} - * if the Java virtual machine implementation supports thread memory - * allocation measurement; - * {@code false} otherwise. - */ - public boolean isThreadAllocatedMemorySupported(); - - /** - * Tests if thread memory allocation measurement is enabled. - * - * @return {@code true} if thread memory allocation measurement is enabled; - * {@code false} otherwise. - * - * @throws java.lang.UnsupportedOperationException if the Java virtual - * machine does not support thread memory allocation measurement. - * - * @see #isThreadAllocatedMemorySupported - */ - public boolean isThreadAllocatedMemoryEnabled(); - - /** - * Enables or disables thread memory allocation measurement. The default - * is platform dependent. - * - * @param enable {@code true} to enable; - * {@code false} to disable. - * - * @throws java.lang.UnsupportedOperationException if the Java virtual - * machine does not support thread memory allocation measurement. - * - * @throws java.lang.SecurityException if a security manager - * exists and the caller does not have - * ManagementPermission("control"). - * - * @see #isThreadAllocatedMemorySupported - */ - public void setThreadAllocatedMemoryEnabled(boolean enable); -}
--- a/jdk/src/java.management/share/classes/com/sun/management/UnixOperatingSystemMXBean.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.management; - -/** - * Platform-specific management interface for the Unix - * operating system on which the Java virtual machine is running. - * - * @author Mandy Chung - * @since 1.5 - */ -@jdk.Exported -public interface UnixOperatingSystemMXBean extends - com.sun.management.OperatingSystemMXBean { - - /** - * Returns the number of open file descriptors. - * - * @return the number of open file descriptors. - */ - public long getOpenFileDescriptorCount(); - - /** - * Returns the maximum number of file descriptors. - * - * @return the maximum number of file descriptors. - */ - public long getMaxFileDescriptorCount(); -}
--- a/jdk/src/java.management/share/classes/com/sun/management/VMOption.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,245 +0,0 @@ -/* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package com.sun.management; - -import sun.management.VMOptionCompositeData; -import javax.management.openmbean.CompositeData; - -/** - * Information about a VM option including its value and - * where the value came from which is referred as its - * {@link VMOption.Origin <i>origin</i>}. - * <p> - * Each VM option has a default value. A VM option can - * be set at VM creation time typically as a command line - * argument to the launcher or an argument passed to the - * VM created using the JNI invocation interface. - * In addition, a VM option may be set via an environment - * variable or a configuration file. A VM option can also - * be set dynamically via a management interface after - * the VM was started. - * - * A <tt>VMOption</tt> contains the value of a VM option - * and the origin of that value at the time this <tt>VMOption</tt> - * object was constructed. The value of the VM option - * may be changed after the <tt>VMOption</tt> object was constructed, - * - * @see <a href="{@docRoot}/../../../../technotes/guides/vm/index.html"> - * Java Virtual Machine</a> - * @author Mandy Chung - * @since 1.6 - */ -@jdk.Exported -public class VMOption { - private String name; - private String value; - private boolean writeable; - private Origin origin; - - /** - * Origin of the value of a VM option. It tells where the - * value of a VM option came from. - * - * @since 1.6 - */ - @jdk.Exported - public enum Origin { - /** - * The VM option has not been set and its value - * is the default value. - */ - DEFAULT, - /** - * The VM option was set at VM creation time typically - * as a command line argument to the launcher or - * an argument passed to the VM created using the - * JNI invocation interface. - */ - VM_CREATION, - /** - * The VM option was set via an environment variable. - */ - ENVIRON_VAR, - /** - * The VM option was set via a configuration file. - */ - CONFIG_FILE, - /** - * The VM option was set via the management interface after the VM - * was started. - */ - MANAGEMENT, - /** - * The VM option was set via the VM ergonomic support. - */ - ERGONOMIC, - /** - * The VM option was set using the attach framework. - * @since 1.9 - */ - ATTACH_ON_DEMAND, - /** - * The VM option was set via some other mechanism. - */ - OTHER - } - - /** - * Constructs a <tt>VMOption</tt>. - * - * @param name Name of a VM option. - * @param value Value of a VM option. - * @param writeable <tt>true</tt> if a VM option can be set dynamically, - * or <tt>false</tt> otherwise. - * @param origin where the value of a VM option came from. - * - * @throws NullPointerException if the name or value is <tt>null</tt> - */ - public VMOption(String name, String value, boolean writeable, Origin origin) { - this.name = name; - this.value = value; - this.writeable = writeable; - this.origin = origin; - } - - /** - * Constructs a <tt>VMOption</tt> object from a - * {@link CompositeData CompositeData}. - */ - private VMOption(CompositeData cd) { - // validate the input composite data - VMOptionCompositeData.validateCompositeData(cd); - - this.name = VMOptionCompositeData.getName(cd); - this.value = VMOptionCompositeData.getValue(cd); - this.writeable = VMOptionCompositeData.isWriteable(cd); - this.origin = VMOptionCompositeData.getOrigin(cd); - } - - /** - * Returns the name of this VM option. - * - * @return the name of this VM option. - */ - public String getName() { - return name; - } - - /** - * Returns the value of this VM option at the time when - * this <tt>VMOption</tt> was created. The value could have been changed. - * - * @return the value of the VM option at the time when - * this <tt>VMOption</tt> was created. - */ - public String getValue() { - return value; - } - - /** - * Returns the origin of the value of this VM option. That is, - * where the value of this VM option came from. - * - * @return where the value of this VM option came from. - */ - public Origin getOrigin() { - return origin; - } - - /** - * Tests if this VM option is writeable. If this VM option is writeable, - * it can be set by the {@link HotSpotDiagnosticMXBean#setVMOption - * HotSpotDiagnosticMXBean.setVMOption} method. - * - * @return <tt>true</tt> if this VM option is writeable; <tt>false</tt> - * otherwise. - */ - public boolean isWriteable() { - return writeable; - } - - public String toString() { - return "VM option: " + getName() + - " value: " + value + " " + - " origin: " + origin + " " + - (writeable ? "(read-write)" : "(read-only)"); - } - - /** - * Returns a <tt>VMOption</tt> object represented by the - * given <tt>CompositeData</tt>. The given <tt>CompositeData</tt> - * must contain the following attributes: - * <p> - * <blockquote> - * <table border> - * <tr> - * <th align=left>Attribute Name</th> - * <th align=left>Type</th> - * </tr> - * <tr> - * <td>name</td> - * <td><tt>java.lang.String</tt></td> - * </tr> - * <tr> - * <td>value</td> - * <td><tt>java.lang.String</tt></td> - * </tr> - * <tr> - * <td>origin</td> - * <td><tt>java.lang.String</tt></td> - * </tr> - * <tr> - * <td>writeable</td> - * <td><tt>java.lang.Boolean</tt></td> - * </tr> - * </table> - * </blockquote> - * - * @param cd <tt>CompositeData</tt> representing a <tt>VMOption</tt> - * - * @throws IllegalArgumentException if <tt>cd</tt> does not - * represent a <tt>VMOption</tt> with the attributes described - * above. - * - * @return a <tt>VMOption</tt> object represented by <tt>cd</tt> - * if <tt>cd</tt> is not <tt>null</tt>; - * <tt>null</tt> otherwise. - */ - public static VMOption from(CompositeData cd) { - if (cd == null) { - return null; - } - - if (cd instanceof VMOptionCompositeData) { - return ((VMOptionCompositeData) cd).getVMOption(); - } else { - return new VMOption(cd); - } - - } - - -}
--- a/jdk/src/java.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package com.sun.management.internal; - -import java.lang.management.ManagementFactory; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import javax.management.DynamicMBean; -import javax.management.ObjectName; -import sun.management.ManagementFactoryHelper; -import sun.management.spi.PlatformMBeanProvider; - -public final class PlatformMBeanProviderImpl extends PlatformMBeanProvider { - private final List<PlatformComponent<?>> mxbeanList; - - public PlatformMBeanProviderImpl() { - mxbeanList = Collections.unmodifiableList(init()); - } - - @Override - public List<PlatformComponent<?>> getPlatformComponentList() { - return mxbeanList; - } - - private List<PlatformComponent<?>> init() { - ArrayList<PlatformComponent<?>> initMBeanList = new ArrayList<>(); - /** - * Garbage Collector in the Java virtual machine. - */ - initMBeanList.add(new PlatformComponent<java.lang.management.MemoryManagerMXBean>() { - private final Set<String> garbageCollectorMXBeanInterfaceNames - = Collections.unmodifiableSet( - Stream.of("java.lang.management.MemoryManagerMXBean", - "java.lang.management.GarbageCollectorMXBean", - "com.sun.management.GarbageCollectorMXBean") - .collect(Collectors.toSet())); - - @Override - public Set<Class<? extends java.lang.management.MemoryManagerMXBean>> mbeanInterfaces() { - return Stream.of(java.lang.management.MemoryManagerMXBean.class, - java.lang.management.GarbageCollectorMXBean.class, - com.sun.management.GarbageCollectorMXBean.class) - .collect(Collectors.toSet()); - } - - @Override - public Set<String> mbeanInterfaceNames() { - return garbageCollectorMXBeanInterfaceNames; - } - - @Override - public String getObjectNamePattern() { - return ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",name=*"; - } - - @Override - public boolean isSingleton() { - return false; // zero or more instances - } - - @Override - public Map<String, java.lang.management.MemoryManagerMXBean> nameToMBeanMap() { - List<java.lang.management.GarbageCollectorMXBean> list - = ManagementFactoryHelper.getGarbageCollectorMXBeans();; - Map<String, java.lang.management.MemoryManagerMXBean> map; - if (list.isEmpty()) { - map = Collections.<String, java.lang.management.MemoryManagerMXBean>emptyMap(); - } else { - map = new HashMap<>(list.size()); - for (java.lang.management.MemoryManagerMXBean gcm : list) { - map.put(gcm.getObjectName().getCanonicalName(), - gcm); - } - } - return map; - } - }); - - /** - * OperatingSystemMXBean - */ - initMBeanList.add(new PlatformComponent<java.lang.management.OperatingSystemMXBean>() { - private final Set<String> operatingSystemMXBeanInterfaceNames - = Collections.unmodifiableSet( - Stream.of("java.lang.management.OperatingSystemMXBean", - "com.sun.management.OperatingSystemMXBean", - "com.sun.management.UnixOperatingSystemMXBean") - .collect(Collectors.toSet())); - - @Override - public Set<Class<? extends java.lang.management.OperatingSystemMXBean>> mbeanInterfaces() { - return Stream.of(java.lang.management.OperatingSystemMXBean.class, - com.sun.management.OperatingSystemMXBean.class, - com.sun.management.UnixOperatingSystemMXBean.class) - .collect(Collectors.toSet()); - } - - @Override - public Set<String> mbeanInterfaceNames() { - return operatingSystemMXBeanInterfaceNames; - } - - @Override - public String getObjectNamePattern() { - return ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME; - } - - @Override - public Map<String, java.lang.management.OperatingSystemMXBean> nameToMBeanMap() { - return Collections.<String, java.lang.management.OperatingSystemMXBean>singletonMap( - ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, - ManagementFactoryHelper.getOperatingSystemMXBean()); - } - }); - - /** - * Diagnostic support for the HotSpot Virtual Machine. - */ - initMBeanList.add(new PlatformComponent<com.sun.management.HotSpotDiagnosticMXBean>() { - private final Set<String> hotSpotDiagnosticMXBeanInterfaceNames = - Collections.unmodifiableSet(Collections.<String>singleton("com.sun.management.HotSpotDiagnosticMXBean")); - - @Override - public Set<Class<? extends com.sun.management.HotSpotDiagnosticMXBean>> mbeanInterfaces() { - return Collections.singleton(com.sun.management.HotSpotDiagnosticMXBean.class); - } - - @Override - public Set<String> mbeanInterfaceNames() { - return hotSpotDiagnosticMXBeanInterfaceNames; - } - - @Override - public String getObjectNamePattern() { - return "com.sun.management:type=HotSpotDiagnostic"; - } - - @Override - public Map<String, com.sun.management.HotSpotDiagnosticMXBean> nameToMBeanMap() { - return Collections.<String, com.sun.management.HotSpotDiagnosticMXBean>singletonMap( - "com.sun.management:type=HotSpotDiagnostic", - ManagementFactoryHelper.getDiagnosticMXBean()); - } - }); - - /** - * DynamicMBean - */ - HashMap<ObjectName, DynamicMBean> dynmbeans - = ManagementFactoryHelper.getPlatformDynamicMBeans(); - final Set<String> dynamicMBeanInterfaceNames = - Collections.unmodifiableSet(Collections.<String>singleton("javax.management.DynamicMBean")); - for (Map.Entry<ObjectName, DynamicMBean> e : dynmbeans.entrySet()) { - initMBeanList.add(new PlatformComponent<DynamicMBean>() { - @Override - public Set<String> mbeanInterfaceNames() { - return dynamicMBeanInterfaceNames; - } - - @Override - public Set<Class<? extends DynamicMBean>> mbeanInterfaces() { - return Collections.emptySet(); // DynamicMBean cannot be used to find an MBean by ManagementFactory - } - - @Override - public String getObjectNamePattern() { - return e.getKey().getCanonicalName(); - } - - @Override - public Map<String, DynamicMBean> nameToMBeanMap() { - return Collections.<String, DynamicMBean>singletonMap( - e.getKey().getCanonicalName(), - e.getValue()); - } - }); - } - initMBeanList.trimToSize(); - return initMBeanList; - } -}
--- a/jdk/src/java.management/share/classes/com/sun/management/package-info.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -/** - * This package contains Oracle Corporation's platform extension to - * the implementation of the - * <a href="{@docRoot}/../../../../api/java/lang/management/package-summary.html"> - * java.lang.management</a> API and also defines the management - * interface for some other components for the platform. - * - * <p> - * All platform MBeans are registered in the <em>platform MBeanServer</em> - * which can be obtained via the - * <a href="{@docRoot}/../../../../api/java/lang/management/ManagementFactory.html#getPlatformMBeanServer()"> - * java.lang.management.ManagementFactory.getPlatformMBeanServer</a> - * - * @author Mandy Chung - * @since 1.5 - */ - -@jdk.Exported -package com.sun.management;
--- a/jdk/src/java.management/share/classes/java/lang/management/DefaultPlatformMBeanProvider.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/classes/java/lang/management/DefaultPlatformMBeanProvider.java Fri Apr 17 09:40:02 2015 +0200 @@ -33,7 +33,6 @@ import java.util.function.Function; import java.util.stream.Collectors; import java.util.stream.Stream; -import javax.management.DynamicMBean; import javax.management.ObjectName; import sun.management.ManagementFactoryHelper; import sun.management.spi.PlatformMBeanProvider; @@ -162,8 +161,7 @@ @Override public Set<Class<? extends MemoryManagerMXBean>> mbeanInterfaces() { return Stream.of(MemoryManagerMXBean.class, - GarbageCollectorMXBean.class, - com.sun.management.GarbageCollectorMXBean.class).collect(Collectors.toSet()); + GarbageCollectorMXBean.class).collect(Collectors.toSet()); } @Override @@ -464,39 +462,6 @@ }); - /** - * DynamicMBean - */ - HashMap<ObjectName, DynamicMBean> dynmbeans - = ManagementFactoryHelper.getPlatformDynamicMBeans(); - final Set<String> dynamicMBeanInterfaceNames = - Collections.unmodifiableSet(Collections.singleton("javax.management.DynamicMBean")); - for (Map.Entry<ObjectName, DynamicMBean> e : dynmbeans.entrySet()) { - initMBeanList.add(new PlatformComponent<DynamicMBean>() { - @Override - public Set<Class<? extends DynamicMBean>> mbeanInterfaces() { - return Collections.emptySet(); - } - - @Override - public Set<String> mbeanInterfaceNames() { - return dynamicMBeanInterfaceNames; - } - - @Override - public String getObjectNamePattern() { - return e.getKey().getCanonicalName(); - } - - @Override - public Map<String, DynamicMBean> nameToMBeanMap() { - return Collections.<String, DynamicMBean>singletonMap( - e.getKey().getCanonicalName(), - e.getValue()); - } - }); - } - initMBeanList.trimToSize(); return initMBeanList; }
--- a/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java Fri Apr 17 09:40:02 2015 +0200 @@ -582,7 +582,7 @@ final Class<?> cls = mxbeanInterface; ClassLoader loader = AccessController.doPrivileged( - (PrivilegedAction<ClassLoader>) () -> cls.getClassLoader()); + (PrivilegedAction<ClassLoader>) () -> cls.getClassLoader()); if (!sun.misc.VM.isSystemDomainLoader(loader)) { throw new IllegalArgumentException(mxbeanName + " is not a platform MXBean"); @@ -883,7 +883,7 @@ all.add(new DefaultPlatformMBeanProvider()); return all; }, null, new FilePermission("<<ALL FILES>>", "read"), - new RuntimePermission("sun.management.spi.PlatformMBeanProvider")); + new RuntimePermission("sun.management.spi.PlatformMBeanProvider.subclass")); // load all platform components into a map componentMap = providers.stream() @@ -970,4 +970,11 @@ return singleton; } } + + static { + AccessController.doPrivileged((PrivilegedAction<Void>) () -> { + System.loadLibrary("management"); + return null; + }); + } }
--- a/jdk/src/java.management/share/classes/sun/management/DiagnosticCommandArgumentInfo.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,159 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -/** - * Diagnostic Command Argument information. It contains the description - * of one parameter of the diagnostic command. A parameter can either be an - * option or an argument. Options are identified by the option name while - * arguments are identified by their position in the command line. The generic - * syntax of a diagnostic command is: - * <blockquote> - * <command name> [<option>=<value>] [<argument_value>] - * </blockquote> - * Example: - * <blockquote> - * command_name option1=value1 option2=value argumentA argumentB argumentC - * </blockquote> - * In this command line, the diagnostic command receives five parameters, two - * options named {@code option1} and {@code option2}, and three arguments. - * argumentA's position is 0, argumentB's position is 1 and argumentC's - * position is 2. - * - * @since 1.8 - */ - -class DiagnosticCommandArgumentInfo { - private final String name; - private final String description; - private final String type; - private final String defaultValue; - private final boolean mandatory; - private final boolean option; - private final boolean multiple; - private final int position; - - /** - * Returns the argument name. - * - * @return the argument name - */ - String getName() { - return name; - } - - /** - * Returns the argument description. - * - * @return the argument description - */ - String getDescription() { - return description; - } - - /** - * Returns the argument type. - * - * @return the argument type - */ - String getType() { - return type; - } - - /** - * Returns the default value as a String if a default value - * is defined, null otherwise. - * - * @return the default value as a String if a default value - * is defined, null otherwise. - */ - String getDefault() { - return defaultValue; - } - - /** - * Returns {@code true} if the argument is mandatory, - * {@code false} otherwise. - * - * @return {@code true} if the argument is mandatory, - * {@code false} otherwise - */ - boolean isMandatory() { - return mandatory; - } - - /** - * Returns {@code true} if the argument is an option, - * {@code false} otherwise. Options have to be specified using the - * <key>=<value> syntax on the command line, while other - * arguments are specified with a single <value> field and are - * identified by their position on command line. - * - * @return {@code true} if the argument is an option, - * {@code false} otherwise - */ - boolean isOption() { - return option; - } - - /** - * Returns {@code true} if the argument can be specified multiple times, - * {@code false} otherwise. - * - * @return {@code true} if the argument can be specified multiple times, - * {@code false} otherwise - */ - boolean isMultiple() { - return multiple; - } - - /** - * Returns the expected position of this argument if it is not an option, - * -1 otherwise. Argument position if defined from left to right, - * starting at zero and ignoring the diagnostic command name and - * options. - * - * @return the expected position of this argument if it is not an option, - * -1 otherwise. - */ - int getPosition() { - return position; - } - - DiagnosticCommandArgumentInfo(String name, String description, - String type, String defaultValue, - boolean mandatory, boolean option, - boolean multiple, int position) { - this.name = name; - this.description = description; - this.type = type; - this.defaultValue = defaultValue; - this.mandatory = mandatory; - this.option = option; - this.multiple = multiple; - this.position = position; - } -}
--- a/jdk/src/java.management/share/classes/sun/management/DiagnosticCommandImpl.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,380 +0,0 @@ -/* - * Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -import com.sun.management.DiagnosticCommandMBean; -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.security.Permission; -import java.util.*; -import javax.management.*; - -/** - * Implementation class for the diagnostic commands subsystem. - * - * @since 1.8 - */ -class DiagnosticCommandImpl extends NotificationEmitterSupport - implements DiagnosticCommandMBean { - - private final VMManagement jvm; - private volatile Map<String, Wrapper> wrappers = null; - private static final String strClassName = "".getClass().getName(); - private static final String strArrayClassName = String[].class.getName(); - private final boolean isSupported; - - @Override - public Object getAttribute(String attribute) throws AttributeNotFoundException, - MBeanException, ReflectionException { - throw new AttributeNotFoundException(attribute); - } - - @Override - public void setAttribute(Attribute attribute) throws AttributeNotFoundException, - InvalidAttributeValueException, MBeanException, ReflectionException { - throw new AttributeNotFoundException(attribute.getName()); - } - - @Override - public AttributeList getAttributes(String[] attributes) { - return new AttributeList(); - } - - @Override - public AttributeList setAttributes(AttributeList attributes) { - return new AttributeList(); - } - - private class Wrapper { - - String name; - String cmd; - DiagnosticCommandInfo info; - Permission permission; - - Wrapper(String name, String cmd, DiagnosticCommandInfo info) - throws InstantiationException { - this.name = name; - this.cmd = cmd; - this.info = info; - this.permission = null; - Exception cause = null; - if (info.getPermissionClass() != null) { - try { - Class<?> c = Class.forName(info.getPermissionClass()); - if (info.getPermissionAction() == null) { - try { - Constructor<?> constructor = c.getConstructor(String.class); - permission = (Permission) constructor.newInstance(info.getPermissionName()); - - } catch (InstantiationException | IllegalAccessException - | IllegalArgumentException | InvocationTargetException - | NoSuchMethodException | SecurityException ex) { - cause = ex; - } - } - if (permission == null) { - try { - Constructor<?> constructor = c.getConstructor(String.class, String.class); - permission = (Permission) constructor.newInstance( - info.getPermissionName(), - info.getPermissionAction()); - } catch (InstantiationException | IllegalAccessException - | IllegalArgumentException | InvocationTargetException - | NoSuchMethodException | SecurityException ex) { - cause = ex; - } - } - } catch (ClassNotFoundException ex) { } - if (permission == null) { - InstantiationException iex = - new InstantiationException("Unable to instantiate required permission"); - iex.initCause(cause); - } - } - } - - public String execute(String[] args) { - if (permission != null) { - SecurityManager sm = System.getSecurityManager(); - if (sm != null) { - sm.checkPermission(permission); - } - } - if(args == null) { - return executeDiagnosticCommand(cmd); - } else { - StringBuilder sb = new StringBuilder(); - sb.append(cmd); - for(int i=0; i<args.length; i++) { - if(args[i] == null) { - throw new IllegalArgumentException("Invalid null argument"); - } - sb.append(" "); - sb.append(args[i]); - } - return executeDiagnosticCommand(sb.toString()); - } - } - } - - DiagnosticCommandImpl(VMManagement jvm) { - this.jvm = jvm; - isSupported = jvm.isRemoteDiagnosticCommandsSupported(); - } - - private static class OperationInfoComparator implements Comparator<MBeanOperationInfo> { - @Override - public int compare(MBeanOperationInfo o1, MBeanOperationInfo o2) { - return o1.getName().compareTo(o2.getName()); - } - } - - @Override - public MBeanInfo getMBeanInfo() { - SortedSet<MBeanOperationInfo> operations = new TreeSet<>(new OperationInfoComparator()); - Map<String, Wrapper> wrappersmap; - if (!isSupported) { - wrappersmap = Collections.emptyMap(); - } else { - try { - String[] command = getDiagnosticCommands(); - DiagnosticCommandInfo[] info = getDiagnosticCommandInfo(command); - MBeanParameterInfo stringArgInfo[] = new MBeanParameterInfo[]{ - new MBeanParameterInfo("arguments", strArrayClassName, - "Array of Diagnostic Commands Arguments and Options") - }; - wrappersmap = new HashMap<>(); - for (int i = 0; i < command.length; i++) { - String name = transform(command[i]); - try { - Wrapper w = new Wrapper(name, command[i], info[i]); - wrappersmap.put(name, w); - operations.add(new MBeanOperationInfo( - w.name, - w.info.getDescription(), - (w.info.getArgumentsInfo() == null - || w.info.getArgumentsInfo().isEmpty()) - ? null : stringArgInfo, - strClassName, - MBeanOperationInfo.ACTION_INFO, - commandDescriptor(w))); - } catch (InstantiationException ex) { - // If for some reasons the creation of a diagnostic command - // wrappers fails, the diagnostic command is just ignored - // and won't appear in the DynamicMBean - } - } - } catch (IllegalArgumentException | UnsupportedOperationException e) { - wrappersmap = Collections.emptyMap(); - } - } - wrappers = Collections.unmodifiableMap(wrappersmap); - HashMap<String, Object> map = new HashMap<>(); - map.put("immutableInfo", "false"); - map.put("interfaceClassName","com.sun.management.DiagnosticCommandMBean"); - map.put("mxbean", "false"); - Descriptor desc = new ImmutableDescriptor(map); - return new MBeanInfo( - this.getClass().getName(), - "Diagnostic Commands", - null, // attributes - null, // constructors - operations.toArray(new MBeanOperationInfo[operations.size()]), // operations - getNotificationInfo(), // notifications - desc); - } - - @Override - public Object invoke(String actionName, Object[] params, String[] signature) - throws MBeanException, ReflectionException { - if (!isSupported) { - throw new UnsupportedOperationException(); - } - if (wrappers == null) { - getMBeanInfo(); - } - Wrapper w = wrappers.get(actionName); - if (w != null) { - if (w.info.getArgumentsInfo().isEmpty() - && (params == null || params.length == 0) - && (signature == null || signature.length == 0)) { - return w.execute(null); - } else if((params != null && params.length == 1) - && (signature != null && signature.length == 1 - && signature[0] != null - && signature[0].compareTo(strArrayClassName) == 0)) { - return w.execute((String[]) params[0]); - } - } - throw new ReflectionException(new NoSuchMethodException(actionName)); - } - - private static String transform(String name) { - StringBuilder sb = new StringBuilder(); - boolean toLower = true; - boolean toUpper = false; - for (int i = 0; i < name.length(); i++) { - char c = name.charAt(i); - if (c == '.' || c == '_') { - toLower = false; - toUpper = true; - } else { - if (toUpper) { - toUpper = false; - sb.append(Character.toUpperCase(c)); - } else if(toLower) { - sb.append(Character.toLowerCase(c)); - } else { - sb.append(c); - } - } - } - return sb.toString(); - } - - private Descriptor commandDescriptor(Wrapper w) throws IllegalArgumentException { - HashMap<String, Object> map = new HashMap<>(); - map.put("dcmd.name", w.info.getName()); - map.put("dcmd.description", w.info.getDescription()); - map.put("dcmd.vmImpact", w.info.getImpact()); - map.put("dcmd.permissionClass", w.info.getPermissionClass()); - map.put("dcmd.permissionName", w.info.getPermissionName()); - map.put("dcmd.permissionAction", w.info.getPermissionAction()); - map.put("dcmd.enabled", w.info.isEnabled()); - StringBuilder sb = new StringBuilder(); - sb.append("help "); - sb.append(w.info.getName()); - map.put("dcmd.help", executeDiagnosticCommand(sb.toString())); - if (w.info.getArgumentsInfo() != null && !w.info.getArgumentsInfo().isEmpty()) { - HashMap<String, Object> allargmap = new HashMap<>(); - for (DiagnosticCommandArgumentInfo arginfo : w.info.getArgumentsInfo()) { - HashMap<String, Object> argmap = new HashMap<>(); - argmap.put("dcmd.arg.name", arginfo.getName()); - argmap.put("dcmd.arg.type", arginfo.getType()); - argmap.put("dcmd.arg.description", arginfo.getDescription()); - argmap.put("dcmd.arg.isMandatory", arginfo.isMandatory()); - argmap.put("dcmd.arg.isMultiple", arginfo.isMultiple()); - boolean isOption = arginfo.isOption(); - argmap.put("dcmd.arg.isOption", isOption); - if(!isOption) { - argmap.put("dcmd.arg.position", arginfo.getPosition()); - } else { - argmap.put("dcmd.arg.position", -1); - } - allargmap.put(arginfo.getName(), new ImmutableDescriptor(argmap)); - } - map.put("dcmd.arguments", new ImmutableDescriptor(allargmap)); - } - return new ImmutableDescriptor(map); - } - - private final static String notifName = - "javax.management.Notification"; - - private final static String[] diagFramNotifTypes = { - "jmx.mbean.info.changed" - }; - - private MBeanNotificationInfo[] notifInfo = null; - - @Override - public MBeanNotificationInfo[] getNotificationInfo() { - synchronized (this) { - if (notifInfo == null) { - notifInfo = new MBeanNotificationInfo[1]; - notifInfo[0] = - new MBeanNotificationInfo(diagFramNotifTypes, - notifName, - "Diagnostic Framework Notification"); - } - } - return notifInfo; - } - - private static long seqNumber = 0; - private static long getNextSeqNumber() { - return ++seqNumber; - } - - private void createDiagnosticFrameworkNotification() { - - if (!hasListeners()) { - return; - } - ObjectName on = null; - try { - on = ObjectName.getInstance(ManagementFactoryHelper.HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME); - } catch (MalformedObjectNameException e) { } - Notification notif = new Notification("jmx.mbean.info.changed", - on, - getNextSeqNumber()); - notif.setUserData(getMBeanInfo()); - sendNotification(notif); - } - - @Override - public synchronized void addNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) { - boolean before = hasListeners(); - super.addNotificationListener(listener, filter, handback); - boolean after = hasListeners(); - if (!before && after) { - setNotificationEnabled(true); - } - } - - @Override - public synchronized void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - boolean before = hasListeners(); - super.removeNotificationListener(listener); - boolean after = hasListeners(); - if (before && !after) { - setNotificationEnabled(false); - } - } - - @Override - public synchronized void removeNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) - throws ListenerNotFoundException { - boolean before = hasListeners(); - super.removeNotificationListener(listener, filter, handback); - boolean after = hasListeners(); - if (before && !after) { - setNotificationEnabled(false); - } - } - - private native void setNotificationEnabled(boolean enabled); - private native String[] getDiagnosticCommands(); - private native DiagnosticCommandInfo[] getDiagnosticCommandInfo(String[] commands); - private native String executeDiagnosticCommand(String command); - -}
--- a/jdk/src/java.management/share/classes/sun/management/DiagnosticCommandInfo.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -import java.util.List; - -/** - * Diagnostic command information. It contains the description of a - * diagnostic command. - * - * @since 1.8 - */ - -class DiagnosticCommandInfo { - private final String name; - private final String description; - private final String impact; - private final String permissionClass; - private final String permissionName; - private final String permissionAction; - private final boolean enabled; - private final List<DiagnosticCommandArgumentInfo> arguments; - - /** - * Returns the diagnostic command name. - * - * @return the diagnostic command name - */ - String getName() { - return name; - } - - /** - * Returns the diagnostic command description. - * - * @return the diagnostic command description - */ - String getDescription() { - return description; - } - - /** - * Returns the potential impact of the diagnostic command execution - * on the Java virtual machine behavior. - * - * @return the potential impact of the diagnostic command execution - * on the Java virtual machine behavior - */ - String getImpact() { - return impact; - } - - /** - * Returns the name of the permission class required to be allowed - * to invoke the diagnostic command, or null if no permission - * is required. - * - * @return the name of the permission class name required to be allowed - * to invoke the diagnostic command, or null if no permission - * is required - */ - String getPermissionClass() { - return permissionClass; - } - - /** - * Returns the permission name required to be allowed to invoke the - * diagnostic command, or null if no permission is required. - * - * @return the permission name required to be allowed to invoke the - * diagnostic command, or null if no permission is required - */ - String getPermissionName() { - return permissionName; - } - - /** - * Returns the permission action required to be allowed to invoke the - * diagnostic command, or null if no permission is required or - * if the permission has no action specified. - * - * @return the permission action required to be allowed to invoke the - * diagnostic command, or null if no permission is required or - * if the permission has no action specified - */ - String getPermissionAction() { - return permissionAction; - } - - /** - * Returns {@code true} if the diagnostic command is enabled, - * {@code false} otherwise. The enabled/disabled - * status of a diagnostic command can evolve during - * the lifetime of the Java virtual machine. - * - * @return {@code true} if the diagnostic command is enabled, - * {@code false} otherwise - */ - boolean isEnabled() { - return enabled; - } - - /** - * Returns the list of the diagnostic command arguments description. - * If the diagnostic command has no arguments, it returns an empty list. - * - * @return a list of the diagnostic command arguments description - */ - List<DiagnosticCommandArgumentInfo> getArgumentsInfo() { - return arguments; - } - - DiagnosticCommandInfo(String name, String description, - String impact, String permissionClass, - String permissionName, String permissionAction, - boolean enabled, - List<DiagnosticCommandArgumentInfo> arguments) - { - this.name = name; - this.description = description; - this.impact = impact; - this.permissionClass = permissionClass; - this.permissionName = permissionName; - this.permissionAction = permissionAction; - this.enabled = enabled; - this.arguments = arguments; - } -}
--- a/jdk/src/java.management/share/classes/sun/management/Flag.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,129 +0,0 @@ -/* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -import java.util.*; -import com.sun.management.VMOption; -import com.sun.management.VMOption.Origin; -import java.security.AccessController; - -/** - * Flag class is a helper class for constructing a VMOption. - * It has the static methods for getting the Flag objects, each - * corresponds to one VMOption. - * - */ -class Flag { - private String name; - private Object value; - private Origin origin; - private boolean writeable; - private boolean external; - - Flag(String name, Object value, boolean writeable, - boolean external, Origin origin) { - this.name = name; - this.value = value == null ? "" : value ; - this.origin = origin; - this.writeable = writeable; - this.external = external; - } - - Object getValue() { - return value; - } - - boolean isWriteable() { - return writeable; - } - - boolean isExternal() { - return external; - } - - VMOption getVMOption() { - return new VMOption(name, value.toString(), writeable, origin); - } - - static Flag getFlag(String name) { - String[] names = new String[1]; - names[0] = name; - - List<Flag> flags = getFlags(names, 1); - if (flags.isEmpty()) { - return null; - } else { - // flags should have only one element - return flags.get(0); - } - } - - static List<Flag> getAllFlags() { - int numFlags = getInternalFlagCount(); - - // Get all internal flags with names = null - return getFlags(null, numFlags); - } - - private static List<Flag> getFlags(String[] names, int numFlags) { - Flag[] flags = new Flag[numFlags]; - int count = getFlags(names, flags, numFlags); - - List<Flag> result = new ArrayList<>(); - for (Flag f : flags) { - if (f != null) { - result.add(f); - } - } - return result; - } - - private static native String[] getAllFlagNames(); - // getFlags sets each element in the given flags array - // with a Flag object only if the name is valid and the - // type is supported. The flags array may contain null elements. - private static native int getFlags(String[] names, Flag[] flags, int count); - private static native int getInternalFlagCount(); - - // These set* methods are synchronized on the class object - // to avoid multiple threads updating the same flag at the same time. - static synchronized native void setLongValue(String name, long value); - static synchronized native void setDoubleValue(String name, double value); - static synchronized native void setBooleanValue(String name, boolean value); - static synchronized native void setStringValue(String name, String value); - - static { - AccessController.doPrivileged( - new java.security.PrivilegedAction<Void>() { - public Void run() { - System.loadLibrary("management"); - return null; - } - }); - initialize(); - } - private static native void initialize(); -}
--- a/jdk/src/java.management/share/classes/sun/management/GarbageCollectionNotifInfoCompositeData.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,215 +0,0 @@ -/* - * Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -import com.sun.management.GarbageCollectionNotificationInfo; -import com.sun.management.GcInfo; -import java.lang.reflect.Method; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.lang.reflect.Field; -import java.util.HashMap; - -/** - * A CompositeData for GarbageCollectionNotificationInfo for the local management support. - * This class avoids the performance penalty paid to the - * construction of a CompositeData use in the local case. - */ -public class GarbageCollectionNotifInfoCompositeData extends LazyCompositeData { - private final GarbageCollectionNotificationInfo gcNotifInfo; - - public GarbageCollectionNotifInfoCompositeData(GarbageCollectionNotificationInfo info) { - this.gcNotifInfo = info; - } - - public GarbageCollectionNotificationInfo getGarbageCollectionNotifInfo() { - return gcNotifInfo; - } - - public static CompositeData toCompositeData(GarbageCollectionNotificationInfo info) { - GarbageCollectionNotifInfoCompositeData gcnicd = - new GarbageCollectionNotifInfoCompositeData(info); - return gcnicd.getCompositeData(); - } - - private CompositeType getCompositeTypeByBuilder() { - final GcInfoBuilder builder = AccessController.doPrivileged (new PrivilegedAction<GcInfoBuilder>() { - public GcInfoBuilder run() { - try { - Class<?> cl = Class.forName("com.sun.management.GcInfo"); - Field f = cl.getDeclaredField("builder"); - f.setAccessible(true); - return (GcInfoBuilder)f.get(gcNotifInfo.getGcInfo()); - } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { - return null; - } - } - }); - CompositeType gict = null; - synchronized(compositeTypeByBuilder) { - gict = compositeTypeByBuilder.get(builder); - if(gict == null) { - OpenType<?>[] gcNotifInfoItemTypes = new OpenType<?>[] { - SimpleType.STRING, - SimpleType.STRING, - SimpleType.STRING, - builder.getGcInfoCompositeType(), - }; - try { - final String typeName = - "sun.management.GarbageCollectionNotifInfoCompositeType"; - gict = new CompositeType(typeName, - "CompositeType for GC notification info", - gcNotifInfoItemNames, - gcNotifInfoItemNames, - gcNotifInfoItemTypes); - compositeTypeByBuilder.put(builder,gict); - } catch (OpenDataException e) { - // shouldn't reach here - throw Util.newException(e); - } - } - } - return gict; - } - - protected CompositeData getCompositeData() { - // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH - // gcNotifInfoItemNames! - final Object[] gcNotifInfoItemValues; - gcNotifInfoItemValues = new Object[] { - gcNotifInfo.getGcName(), - gcNotifInfo.getGcAction(), - gcNotifInfo.getGcCause(), - GcInfoCompositeData.toCompositeData(gcNotifInfo.getGcInfo()) - }; - - CompositeType gict = getCompositeTypeByBuilder(); - - try { - return new CompositeDataSupport(gict, - gcNotifInfoItemNames, - gcNotifInfoItemValues); - } catch (OpenDataException e) { - // Should never reach here - throw new AssertionError(e); - } - } - - // private static MappedMXBeanType gcInfoMapType; - private static final String GC_NAME = "gcName"; - private static final String GC_ACTION = "gcAction"; - private static final String GC_CAUSE = "gcCause"; - private static final String GC_INFO = "gcInfo"; - private static final String[] gcNotifInfoItemNames = { - GC_NAME, - GC_ACTION, - GC_CAUSE, - GC_INFO - }; - private static HashMap<GcInfoBuilder,CompositeType> compositeTypeByBuilder = - new HashMap<>(); - - public static String getGcName(CompositeData cd) { - String gcname = getString(cd, GC_NAME); - if (gcname == null) { - throw new IllegalArgumentException("Invalid composite data: " + - "Attribute " + GC_NAME + " has null value"); - } - return gcname; - } - - public static String getGcAction(CompositeData cd) { - String gcaction = getString(cd, GC_ACTION); - if (gcaction == null) { - throw new IllegalArgumentException("Invalid composite data: " + - "Attribute " + GC_ACTION + " has null value"); - } - return gcaction; - } - - public static String getGcCause(CompositeData cd) { - String gccause = getString(cd, GC_CAUSE); - if (gccause == null) { - throw new IllegalArgumentException("Invalid composite data: " + - "Attribute " + GC_CAUSE + " has null value"); - } - return gccause; - } - - public static GcInfo getGcInfo(CompositeData cd) { - CompositeData gcInfoData = (CompositeData) cd.get(GC_INFO); - return GcInfo.from(gcInfoData); - } - - /** Validate if the input CompositeData has the expected - * CompositeType (i.e. contain all attributes with expected - * names and types). - */ - public static void validateCompositeData(CompositeData cd) { - if (cd == null) { - throw new NullPointerException("Null CompositeData"); - } - - if (!isTypeMatched( getBaseGcNotifInfoCompositeType(), cd.getCompositeType())) { - throw new IllegalArgumentException( - "Unexpected composite type for GarbageCollectionNotificationInfo"); - } - } - - // This is only used for validation. - private static CompositeType baseGcNotifInfoCompositeType = null; - private static synchronized CompositeType getBaseGcNotifInfoCompositeType() { - if (baseGcNotifInfoCompositeType == null) { - try { - OpenType<?>[] baseGcNotifInfoItemTypes = new OpenType<?>[] { - SimpleType.STRING, - SimpleType.STRING, - SimpleType.STRING, - GcInfoCompositeData.getBaseGcInfoCompositeType() - }; - baseGcNotifInfoCompositeType = - new CompositeType("sun.management.BaseGarbageCollectionNotifInfoCompositeType", - "CompositeType for Base GarbageCollectionNotificationInfo", - gcNotifInfoItemNames, - gcNotifInfoItemNames, - baseGcNotifInfoItemTypes); - } catch (OpenDataException e) { - // shouldn't reach here - throw Util.newException(e); - } - } - return baseGcNotifInfoCompositeType; - } - - private static final long serialVersionUID = -1805123446483771292L; -}
--- a/jdk/src/java.management/share/classes/sun/management/GarbageCollectorImpl.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/classes/sun/management/GarbageCollectorImpl.java Fri Apr 17 09:40:02 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,168 +25,31 @@ package sun.management; -import com.sun.management.GarbageCollectorMXBean; -import com.sun.management.GarbageCollectionNotificationInfo; +import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; -import java.lang.management.MemoryPoolMXBean; -import java.lang.management.MemoryUsage; - -import com.sun.management.GcInfo; -import javax.management.openmbean.CompositeData; -import javax.management.MBeanInfo; -import javax.management.MBeanAttributeInfo; import javax.management.ObjectName; -import javax.management.MBeanNotificationInfo; -import javax.management.Notification; -import javax.management.NotificationFilter; -import javax.management.NotificationListener; -import javax.management.ListenerNotFoundException; - -import java.util.List; -import java.util.ListIterator; -import java.util.Map; /** * Implementation class for the garbage collector. - * Standard and committed hotspot-specific metrics if any. * * ManagementFactory.getGarbageCollectorMXBeans() returns a list * of instances of this class. */ -class GarbageCollectorImpl extends MemoryManagerImpl +public class GarbageCollectorImpl extends MemoryManagerImpl implements GarbageCollectorMXBean { - GarbageCollectorImpl(String name) { + protected GarbageCollectorImpl(String name) { super(name); } + @Override public native long getCollectionCount(); + + @Override public native long getCollectionTime(); - - // The memory pools are static and won't be changed. - // TODO: If the hotspot implementation begins to have pools - // dynamically created and removed, this needs to be modified. - private String[] poolNames = null; - synchronized String[] getAllPoolNames() { - if (poolNames == null) { - List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans(); - poolNames = new String[pools.size()]; - int i = 0; - for (MemoryPoolMXBean m : pools) { - poolNames[i++] = m.getName(); - } - } - return poolNames; - } - - // Sun JDK extension - private GcInfoBuilder gcInfoBuilder; - - private synchronized GcInfoBuilder getGcInfoBuilder() { - if(gcInfoBuilder == null) { - gcInfoBuilder = new GcInfoBuilder(this, getAllPoolNames()); - } - return gcInfoBuilder; - } - - public GcInfo getLastGcInfo() { - GcInfo info = getGcInfoBuilder().getLastGcInfo(); - return info; - } - - private final static String notifName = - "javax.management.Notification"; - - private final static String[] gcNotifTypes = { - GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION - }; - - private MBeanNotificationInfo[] notifInfo = null; - public MBeanNotificationInfo[] getNotificationInfo() { - synchronized (this) { - if (notifInfo == null) { - notifInfo = new MBeanNotificationInfo[1]; - notifInfo[0] = new MBeanNotificationInfo(gcNotifTypes, - notifName, - "GC Notification"); - } - } - return notifInfo; - } - - private static long seqNumber = 0; - private static long getNextSeqNumber() { - return ++seqNumber; - } - - void createGCNotification(long timestamp, - String gcName, - String gcAction, - String gcCause, - GcInfo gcInfo) { - - if (!hasListeners()) { - return; - } - - Notification notif = new Notification(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION, - getObjectName(), - getNextSeqNumber(), - timestamp, - gcName); - GarbageCollectionNotificationInfo info = - new GarbageCollectionNotificationInfo(gcName, - gcAction, - gcCause, - gcInfo); - - CompositeData cd = - GarbageCollectionNotifInfoCompositeData.toCompositeData(info); - notif.setUserData(cd); - sendNotification(notif); - } - - public synchronized void addNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) - { - boolean before = hasListeners(); - super.addNotificationListener(listener, filter, handback); - boolean after = hasListeners(); - if (!before && after) { - setNotificationEnabled(this, true); - } - } - - public synchronized void removeNotificationListener(NotificationListener listener) - throws ListenerNotFoundException { - boolean before = hasListeners(); - super.removeNotificationListener(listener); - boolean after = hasListeners(); - if (before && !after) { - setNotificationEnabled(this,false); - } - } - - public synchronized void removeNotificationListener(NotificationListener listener, - NotificationFilter filter, - Object handback) - throws ListenerNotFoundException - { - boolean before = hasListeners(); - super.removeNotificationListener(listener,filter,handback); - boolean after = hasListeners(); - if (before && !after) { - setNotificationEnabled(this,false); - } - } - + @Override public ObjectName getObjectName() { return Util.newObjectName(ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE, getName()); } - - native void setNotificationEnabled(GarbageCollectorMXBean gc, - boolean enabled); - }
--- a/jdk/src/java.management/share/classes/sun/management/GcInfoBuilder.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,205 +0,0 @@ -/* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ -package sun.management; - -import java.lang.management.GarbageCollectorMXBean; -import java.lang.management.MemoryUsage; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.TabularType; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.TabularDataSupport; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; -import com.sun.management.GcInfo; - -/** - * Helper class to build composite data. - */ -public class GcInfoBuilder { - private final GarbageCollectorMXBean gc; - private final String[] poolNames; - private String[] allItemNames; - - // GC-specific composite type: - // Each GarbageCollectorMXBean may have different GC-specific attributes - // the CompositeType for the GcInfo could be different. - private CompositeType gcInfoCompositeType; - - // GC-specific items - private final int gcExtItemCount; - private final String[] gcExtItemNames; - private final String[] gcExtItemDescs; - private final char[] gcExtItemTypes; - - GcInfoBuilder(GarbageCollectorMXBean gc, String[] poolNames) { - this.gc = gc; - this.poolNames = poolNames; - this.gcExtItemCount = getNumGcExtAttributes(gc); - this.gcExtItemNames = new String[gcExtItemCount]; - this.gcExtItemDescs = new String[gcExtItemCount]; - this.gcExtItemTypes = new char[gcExtItemCount]; - - // Fill the information about extension attributes - fillGcAttributeInfo(gc, gcExtItemCount, gcExtItemNames, - gcExtItemTypes, gcExtItemDescs); - - // lazily build the CompositeType for the GcInfo - // including the GC-specific extension attributes - this.gcInfoCompositeType = null; - } - - GcInfo getLastGcInfo() { - MemoryUsage[] usageBeforeGC = new MemoryUsage[poolNames.length]; - MemoryUsage[] usageAfterGC = new MemoryUsage[poolNames.length]; - Object[] values = new Object[gcExtItemCount]; - - return getLastGcInfo0(gc, gcExtItemCount, values, gcExtItemTypes, - usageBeforeGC, usageAfterGC); - } - - public String[] getPoolNames() { - return poolNames; - } - - int getGcExtItemCount() { - return gcExtItemCount; - } - - // Returns the CompositeType for the GcInfo including - // the extension attributes - synchronized CompositeType getGcInfoCompositeType() { - if (gcInfoCompositeType != null) - return gcInfoCompositeType; - - // First, fill with the attributes in the GcInfo - String[] gcInfoItemNames = GcInfoCompositeData.getBaseGcInfoItemNames(); - OpenType<?>[] gcInfoItemTypes = GcInfoCompositeData.getBaseGcInfoItemTypes(); - int numGcInfoItems = gcInfoItemNames.length; - - int itemCount = numGcInfoItems + gcExtItemCount; - allItemNames = new String[itemCount]; - String[] allItemDescs = new String[itemCount]; - OpenType<?>[] allItemTypes = new OpenType<?>[itemCount]; - - System.arraycopy(gcInfoItemNames, 0, allItemNames, 0, numGcInfoItems); - System.arraycopy(gcInfoItemNames, 0, allItemDescs, 0, numGcInfoItems); - System.arraycopy(gcInfoItemTypes, 0, allItemTypes, 0, numGcInfoItems); - - // Then fill with the extension GC-specific attributes, if any. - if (gcExtItemCount > 0) { - fillGcAttributeInfo(gc, gcExtItemCount, gcExtItemNames, - gcExtItemTypes, gcExtItemDescs); - System.arraycopy(gcExtItemNames, 0, allItemNames, - numGcInfoItems, gcExtItemCount); - System.arraycopy(gcExtItemDescs, 0, allItemDescs, - numGcInfoItems, gcExtItemCount); - for (int i = numGcInfoItems, j = 0; j < gcExtItemCount; i++, j++) { - switch (gcExtItemTypes[j]) { - case 'Z': - allItemTypes[i] = SimpleType.BOOLEAN; - break; - case 'B': - allItemTypes[i] = SimpleType.BYTE; - break; - case 'C': - allItemTypes[i] = SimpleType.CHARACTER; - break; - case 'S': - allItemTypes[i] = SimpleType.SHORT; - break; - case 'I': - allItemTypes[i] = SimpleType.INTEGER; - break; - case 'J': - allItemTypes[i] = SimpleType.LONG; - break; - case 'F': - allItemTypes[i] = SimpleType.FLOAT; - break; - case 'D': - allItemTypes[i] = SimpleType.DOUBLE; - break; - default: - throw new AssertionError( - "Unsupported type [" + gcExtItemTypes[i] + "]"); - } - } - } - - CompositeType gict = null; - try { - final String typeName = - "sun.management." + gc.getName() + ".GcInfoCompositeType"; - - gict = new CompositeType(typeName, - "CompositeType for GC info for " + - gc.getName(), - allItemNames, - allItemDescs, - allItemTypes); - } catch (OpenDataException e) { - // shouldn't reach here - throw Util.newException(e); - } - gcInfoCompositeType = gict; - - return gcInfoCompositeType; - } - - synchronized String[] getItemNames() { - if (allItemNames == null) { - // initialize when forming the composite type - getGcInfoCompositeType(); - } - return allItemNames; - } - - // Retrieve information about extension attributes - private native int getNumGcExtAttributes(GarbageCollectorMXBean gc); - private native void fillGcAttributeInfo(GarbageCollectorMXBean gc, - int numAttributes, - String[] attributeNames, - char[] types, - String[] descriptions); - - /** - * Returns the last GcInfo - * - * @param gc GarbageCollectorMXBean that the gc info is associated with. - * @param numExtAtts number of extension attributes - * @param extAttValues Values of extension attributes to be filled. - * @param before Memory usage before GC to be filled. - * @param after Memory usage after GC to be filled. - */ - private native GcInfo getLastGcInfo0(GarbageCollectorMXBean gc, - int numExtAtts, - Object[] extAttValues, - char[] extAttTypes, - MemoryUsage[] before, - MemoryUsage[] after); -}
--- a/jdk/src/java.management/share/classes/sun/management/GcInfoCompositeData.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,276 +0,0 @@ -/* - * Copyright (c) 2004, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -import java.lang.management.MemoryUsage; -import java.lang.reflect.Method; -import java.lang.reflect.Field; -import java.util.Iterator; -import java.util.Map; -import java.util.HashMap; -import java.util.List; -import java.util.Collections; -import java.io.InvalidObjectException; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.TabularData; -import javax.management.openmbean.SimpleType; -import javax.management.openmbean.OpenType; -import javax.management.openmbean.OpenDataException; -import com.sun.management.GcInfo; -import com.sun.management.GarbageCollectionNotificationInfo; -import java.security.AccessController; -import java.security.PrivilegedAction; - -/** - * A CompositeData for GcInfo for the local management support. - * This class avoids the performance penalty paid to the - * construction of a CompositeData use in the local case. - */ -public class GcInfoCompositeData extends LazyCompositeData { - private final GcInfo info; - private final GcInfoBuilder builder; - private final Object[] gcExtItemValues; - - public GcInfoCompositeData(GcInfo info, - GcInfoBuilder builder, - Object[] gcExtItemValues) { - this.info = info; - this.builder = builder; - this.gcExtItemValues = gcExtItemValues; - } - - public GcInfo getGcInfo() { - return info; - } - - public static CompositeData toCompositeData(final GcInfo info) { - final GcInfoBuilder builder = AccessController.doPrivileged (new PrivilegedAction<GcInfoBuilder>() { - public GcInfoBuilder run() { - try { - Class<?> cl = Class.forName("com.sun.management.GcInfo"); - Field f = cl.getDeclaredField("builder"); - f.setAccessible(true); - return (GcInfoBuilder)f.get(info); - } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { - return null; - } - } - }); - final Object[] extAttr = AccessController.doPrivileged (new PrivilegedAction<Object[]>() { - public Object[] run() { - try { - Class<?> cl = Class.forName("com.sun.management.GcInfo"); - Field f = cl.getDeclaredField("extAttributes"); - f.setAccessible(true); - return (Object[])f.get(info); - } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { - return null; - } - } - }); - GcInfoCompositeData gcicd = - new GcInfoCompositeData(info,builder,extAttr); - return gcicd.getCompositeData(); - } - - protected CompositeData getCompositeData() { - // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH - // baseGcInfoItemNames! - final Object[] baseGcInfoItemValues; - - try { - baseGcInfoItemValues = new Object[] { - info.getId(), - info.getStartTime(), - info.getEndTime(), - info.getDuration(), - memoryUsageMapType.toOpenTypeData(info.getMemoryUsageBeforeGc()), - memoryUsageMapType.toOpenTypeData(info.getMemoryUsageAfterGc()), - }; - } catch (OpenDataException e) { - // Should never reach here - throw new AssertionError(e); - } - - // Get the item values for the extension attributes - final int gcExtItemCount = builder.getGcExtItemCount(); - if (gcExtItemCount == 0 && - gcExtItemValues != null && gcExtItemValues.length != 0) { - throw new AssertionError("Unexpected Gc Extension Item Values"); - } - - if (gcExtItemCount > 0 && (gcExtItemValues == null || - gcExtItemCount != gcExtItemValues.length)) { - throw new AssertionError("Unmatched Gc Extension Item Values"); - } - - Object[] values = new Object[baseGcInfoItemValues.length + - gcExtItemCount]; - System.arraycopy(baseGcInfoItemValues, 0, values, 0, - baseGcInfoItemValues.length); - - if (gcExtItemCount > 0) { - System.arraycopy(gcExtItemValues, 0, values, - baseGcInfoItemValues.length, gcExtItemCount); - } - - try { - return new CompositeDataSupport(builder.getGcInfoCompositeType(), - builder.getItemNames(), - values); - } catch (OpenDataException e) { - // Should never reach here - throw new AssertionError(e); - } - } - - private static final String ID = "id"; - private static final String START_TIME = "startTime"; - private static final String END_TIME = "endTime"; - private static final String DURATION = "duration"; - private static final String MEMORY_USAGE_BEFORE_GC = "memoryUsageBeforeGc"; - private static final String MEMORY_USAGE_AFTER_GC = "memoryUsageAfterGc"; - - private static final String[] baseGcInfoItemNames = { - ID, - START_TIME, - END_TIME, - DURATION, - MEMORY_USAGE_BEFORE_GC, - MEMORY_USAGE_AFTER_GC, - }; - - - private static MappedMXBeanType memoryUsageMapType; - static { - try { - Method m = GcInfo.class.getMethod("getMemoryUsageBeforeGc"); - memoryUsageMapType = - MappedMXBeanType.getMappedType(m.getGenericReturnType()); - } catch (NoSuchMethodException | OpenDataException e) { - // Should never reach here - throw new AssertionError(e); - } - } - - static String[] getBaseGcInfoItemNames() { - return baseGcInfoItemNames; - } - - private static OpenType<?>[] baseGcInfoItemTypes = null; - static synchronized OpenType<?>[] getBaseGcInfoItemTypes() { - if (baseGcInfoItemTypes == null) { - OpenType<?> memoryUsageOpenType = memoryUsageMapType.getOpenType(); - baseGcInfoItemTypes = new OpenType<?>[] { - SimpleType.LONG, - SimpleType.LONG, - SimpleType.LONG, - SimpleType.LONG, - - memoryUsageOpenType, - memoryUsageOpenType, - }; - } - return baseGcInfoItemTypes; - } - - public static long getId(CompositeData cd) { - return getLong(cd, ID); - } - public static long getStartTime(CompositeData cd) { - return getLong(cd, START_TIME); - } - public static long getEndTime(CompositeData cd) { - return getLong(cd, END_TIME); - } - - public static Map<String, MemoryUsage> - getMemoryUsageBeforeGc(CompositeData cd) { - try { - TabularData td = (TabularData) cd.get(MEMORY_USAGE_BEFORE_GC); - return cast(memoryUsageMapType.toJavaTypeData(td)); - } catch (InvalidObjectException | OpenDataException e) { - // Should never reach here - throw new AssertionError(e); - } - } - - @SuppressWarnings("unchecked") - public static Map<String, MemoryUsage> cast(Object x) { - return (Map<String, MemoryUsage>) x; - } - public static Map<String, MemoryUsage> - getMemoryUsageAfterGc(CompositeData cd) { - try { - TabularData td = (TabularData) cd.get(MEMORY_USAGE_AFTER_GC); - //return (Map<String,MemoryUsage>) - return cast(memoryUsageMapType.toJavaTypeData(td)); - } catch (InvalidObjectException | OpenDataException e) { - // Should never reach here - throw new AssertionError(e); - } - } - - /** - * Returns true if the input CompositeData has the expected - * CompositeType (i.e. contain all attributes with expected - * names and types). Otherwise, return false. - */ - public static void validateCompositeData(CompositeData cd) { - if (cd == null) { - throw new NullPointerException("Null CompositeData"); - } - - if (!isTypeMatched(getBaseGcInfoCompositeType(), - cd.getCompositeType())) { - throw new IllegalArgumentException( - "Unexpected composite type for GcInfo"); - } - } - - // This is only used for validation. - private static CompositeType baseGcInfoCompositeType = null; - static synchronized CompositeType getBaseGcInfoCompositeType() { - if (baseGcInfoCompositeType == null) { - try { - baseGcInfoCompositeType = - new CompositeType("sun.management.BaseGcInfoCompositeType", - "CompositeType for Base GcInfo", - getBaseGcInfoItemNames(), - getBaseGcInfoItemNames(), - getBaseGcInfoItemTypes()); - } catch (OpenDataException e) { - // shouldn't reach here - throw Util.newException(e); - } - } - return baseGcInfoCompositeType; - } - - private static final long serialVersionUID = -5716428894085882742L; -}
--- a/jdk/src/java.management/share/classes/sun/management/HotSpotDiagnostic.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,143 +0,0 @@ -/* - * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -import java.io.IOException; -import java.util.ArrayList; -import java.util.List; -import javax.management.ObjectName; - -import com.sun.management.HotSpotDiagnosticMXBean; -import com.sun.management.VMOption; - -/** - * Implementation of the diagnostic MBean for Hotspot VM. - */ -public class HotSpotDiagnostic implements HotSpotDiagnosticMXBean { - public HotSpotDiagnostic() { - } - - @Override - public void dumpHeap(String outputFile, boolean live) throws IOException { - SecurityManager security = System.getSecurityManager(); - if (security != null) { - security.checkWrite(outputFile); - Util.checkControlAccess(); - } - - dumpHeap0(outputFile, live); - } - - private native void dumpHeap0(String outputFile, boolean live) throws IOException; - - @Override - public List<VMOption> getDiagnosticOptions() { - List<Flag> allFlags = Flag.getAllFlags(); - List<VMOption> result = new ArrayList<>(); - for (Flag flag : allFlags) { - if (flag.isWriteable() && flag.isExternal()) { - result.add(flag.getVMOption()); - } - } - return result; - } - - @Override - public VMOption getVMOption(String name) { - if (name == null) { - throw new NullPointerException("name cannot be null"); - } - - Flag f = Flag.getFlag(name); - if (f == null) { - throw new IllegalArgumentException("VM option \"" + - name + "\" does not exist"); - } - return f.getVMOption(); - } - - @Override - public void setVMOption(String name, String value) { - if (name == null) { - throw new NullPointerException("name cannot be null"); - } - if (value == null) { - throw new NullPointerException("value cannot be null"); - } - - Util.checkControlAccess(); - Flag flag = Flag.getFlag(name); - if (flag == null) { - throw new IllegalArgumentException("VM option \"" + - name + "\" does not exist"); - } - if (!flag.isWriteable()){ - throw new IllegalArgumentException("VM Option \"" + - name + "\" is not writeable"); - } - - // Check the type of the value - Object v = flag.getValue(); - if (v instanceof Long) { - try { - long l = Long.parseLong(value); - Flag.setLongValue(name, l); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Invalid value:" + - " VM Option \"" + name + "\"" + - " expects numeric value", e); - } - } else if (v instanceof Double) { - try { - double d = Double.parseDouble(value); - Flag.setDoubleValue(name, d); - } catch (NumberFormatException e) { - throw new IllegalArgumentException("Invalid value:" + - " VM Option \"" + name + "\"" + - " expects numeric value", e); - } - } else if (v instanceof Boolean) { - if (!value.equalsIgnoreCase("true") && - !value.equalsIgnoreCase("false")) { - throw new IllegalArgumentException("Invalid value:" + - " VM Option \"" + name + "\"" + - " expects \"true\" or \"false\"."); - } - Flag.setBooleanValue(name, Boolean.parseBoolean(value)); - } else if (v instanceof String) { - Flag.setStringValue(name, value); - } else { - throw new IllegalArgumentException("VM Option \"" + - name + "\" is of an unsupported type: " + - v.getClass().getName()); - } - } - - @Override - public ObjectName getObjectName() { - return Util.newObjectName("com.sun.management:type=HotSpotDiagnostic"); - } -}
--- a/jdk/src/java.management/share/classes/sun/management/LazyCompositeData.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/classes/sun/management/LazyCompositeData.java Fri Apr 17 09:40:02 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -115,28 +115,28 @@ protected abstract CompositeData getCompositeData(); // Helper methods - static String getString(CompositeData cd, String itemName) { + public static String getString(CompositeData cd, String itemName) { if (cd == null) throw new IllegalArgumentException("Null CompositeData"); return (String) cd.get(itemName); } - static boolean getBoolean(CompositeData cd, String itemName) { + public static boolean getBoolean(CompositeData cd, String itemName) { if (cd == null) throw new IllegalArgumentException("Null CompositeData"); return ((Boolean) cd.get(itemName)).booleanValue(); } - static long getLong(CompositeData cd, String itemName) { + public static long getLong(CompositeData cd, String itemName) { if (cd == null) throw new IllegalArgumentException("Null CompositeData"); return ((Long) cd.get(itemName)).longValue(); } - static int getInt(CompositeData cd, String itemName) { + public static int getInt(CompositeData cd, String itemName) { if (cd == null) throw new IllegalArgumentException("Null CompositeData");
--- a/jdk/src/java.management/share/classes/sun/management/ManagementFactory.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -import java.lang.management.MemoryManagerMXBean; -import java.lang.management.MemoryPoolMXBean; -import java.lang.management.GarbageCollectorMXBean; - -/** - * ManagementFactory class provides the methods that the HotSpot VM - * will invoke. So the class and method names cannot be renamed. - */ -class ManagementFactory { - private ManagementFactory() {}; - - // Invoked by the VM - private static MemoryPoolMXBean createMemoryPool - (String name, boolean isHeap, long uThreshold, long gcThreshold) { - return new MemoryPoolImpl(name, isHeap, uThreshold, gcThreshold); - } - - private static MemoryManagerMXBean createMemoryManager(String name) { - return new MemoryManagerImpl(name); - } - - private static GarbageCollectorMXBean - createGarbageCollector(String name, String type) { - - // ignore type parameter which is for future extension - return new GarbageCollectorImpl(name); - } -}
--- a/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java Fri Apr 17 09:40:02 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -26,8 +26,6 @@ package sun.management; import java.lang.management.*; - -import javax.management.DynamicMBean; import javax.management.InstanceAlreadyExistsException; import javax.management.InstanceNotFoundException; import javax.management.MBeanServer; @@ -38,30 +36,35 @@ import java.security.AccessController; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; - import sun.util.logging.LoggingSupport; - import java.util.ArrayList; -import java.util.HashMap; import java.util.List; -import com.sun.management.DiagnosticCommandMBean; -import com.sun.management.HotSpotDiagnosticMXBean; /** * ManagementFactoryHelper provides static factory methods to create * instances of the management interface. */ public class ManagementFactoryHelper { + static { + // make sure that the management lib is loaded within + // java.lang.management.ManagementFactory + sun.misc.Unsafe.getUnsafe().ensureClassInitialized(ManagementFactory.class); + } + + private static final VMManagement jvm = new VMManagementImpl(); + private ManagementFactoryHelper() {}; - private static VMManagement jvm; + public static VMManagement getVMManagement() { + return jvm; + } private static ClassLoadingImpl classMBean = null; private static MemoryImpl memoryMBean = null; private static ThreadImpl threadMBean = null; private static RuntimeImpl runtimeMBean = null; private static CompilationImpl compileMBean = null; - private static OperatingSystemImpl osMBean = null; + private static BaseOperatingSystemImpl osMBean = null; public static synchronized ClassLoadingMXBean getClassLoadingMXBean() { if (classMBean == null) { @@ -100,7 +103,7 @@ public static synchronized OperatingSystemMXBean getOperatingSystemMXBean() { if (osMBean == null) { - osMBean = new OperatingSystemImpl(jvm); + osMBean = new BaseOperatingSystemImpl(jvm); } return osMBean; } @@ -123,7 +126,7 @@ return result; } - public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() { + public static List<GarbageCollectorMXBean> getGarbageCollectorMXBeans() { MemoryManagerMXBean[] mgrs = MemoryImpl.getMemoryManagers(); List<GarbageCollectorMXBean> result = new ArrayList<>(mgrs.length); for (MemoryManagerMXBean m : mgrs) { @@ -257,20 +260,11 @@ }; } - private static HotSpotDiagnostic hsDiagMBean = null; private static HotspotRuntime hsRuntimeMBean = null; private static HotspotClassLoading hsClassMBean = null; private static HotspotThread hsThreadMBean = null; private static HotspotCompilation hsCompileMBean = null; private static HotspotMemory hsMemoryMBean = null; - private static DiagnosticCommandImpl hsDiagCommandMBean = null; - - public static synchronized HotSpotDiagnosticMXBean getDiagnosticMXBean() { - if (hsDiagMBean == null) { - hsDiagMBean = new HotSpotDiagnostic(); - } - return hsDiagMBean; - } /** * This method is for testing only. @@ -312,14 +306,6 @@ return hsMemoryMBean; } - public static synchronized DiagnosticCommandMBean getDiagnosticCommandMBean() { - // Remote Diagnostic Commands may not be supported - if (hsDiagCommandMBean == null && jvm.isRemoteDiagnosticCommandsSupported()) { - hsDiagCommandMBean = new DiagnosticCommandImpl(jvm); - } - return hsDiagCommandMBean; - } - /** * This method is for testing only. */ @@ -374,18 +360,6 @@ private final static String HOTSPOT_THREAD_MBEAN_NAME = "sun.management:type=HotspotThreading"; - final static String HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME = - "com.sun.management:type=DiagnosticCommand"; - - public static HashMap<ObjectName, DynamicMBean> getPlatformDynamicMBeans() { - HashMap<ObjectName, DynamicMBean> map = new HashMap<>(); - DiagnosticCommandMBean diagMBean = getDiagnosticCommandMBean(); - if (diagMBean != null) { - map.put(Util.newObjectName(HOTSPOT_DIAGNOSTIC_COMMAND_MBEAN_NAME), diagMBean); - } - return map; - } - static void registerInternalMBeans(MBeanServer mbs) { // register all internal MBeans if not registered // No exception is thrown if a MBean with that object name @@ -441,17 +415,6 @@ } } - static { - AccessController.doPrivileged( - new java.security.PrivilegedAction<Void>() { - public Void run() { - System.loadLibrary("management"); - return null; - } - }); - jvm = new VMManagementImpl(); - } - public static boolean isThreadSuspended(int state) { return ((state & JMM_THREAD_STATE_FLAG_SUSPENDED) != 0); } @@ -471,4 +434,20 @@ private static final int JMM_THREAD_STATE_FLAG_SUSPENDED = 0x00100000; private static final int JMM_THREAD_STATE_FLAG_NATIVE = 0x00400000; + // Invoked by the VM + private static MemoryPoolMXBean createMemoryPool + (String name, boolean isHeap, long uThreshold, long gcThreshold) { + return new MemoryPoolImpl(name, isHeap, uThreshold, gcThreshold); + } + + private static MemoryManagerMXBean createMemoryManager(String name) { + return new MemoryManagerImpl(name); + } + + private static GarbageCollectorMXBean + createGarbageCollector(String name, String type) { + + // ignore type parameter which is for future extension + return new GarbageCollectorImpl(name); + } }
--- a/jdk/src/java.management/share/classes/sun/management/MappedMXBeanType.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/classes/sun/management/MappedMXBeanType.java Fri Apr 17 09:40:02 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -38,10 +38,8 @@ import java.security.PrivilegedAction; import java.security.PrivilegedActionException; import java.security.PrivilegedExceptionAction; -import javax.management.*; import javax.management.openmbean.*; import static javax.management.openmbean.SimpleType.*; -import com.sun.management.VMOption; /** * A mapped mxbean type maps a Java type to an open type. @@ -113,7 +111,7 @@ return mt; } - static synchronized MappedMXBeanType getMappedType(Type t) + public static synchronized MappedMXBeanType getMappedType(Type t) throws OpenDataException { MappedMXBeanType mt = convertedTypes.get(t); if (mt == null) { @@ -152,7 +150,7 @@ } // Return the mapped open type - OpenType<?> getOpenType() { + public OpenType<?> getOpenType() { return openType; } @@ -177,10 +175,10 @@ // return name of the class or the generic type abstract String getName(); - abstract Object toOpenTypeData(Object javaTypeData) + public abstract Object toOpenTypeData(Object javaTypeData) throws OpenDataException; - abstract Object toJavaTypeData(Object openTypeData) + public abstract Object toJavaTypeData(Object openTypeData) throws OpenDataException, InvalidObjectException; // Basic Types - Classes that do not require data conversion @@ -208,11 +206,11 @@ return basicType.getName(); } - Object toOpenTypeData(Object data) throws OpenDataException { + public Object toOpenTypeData(Object data) throws OpenDataException { return data; } - Object toJavaTypeData(Object data) + public Object toJavaTypeData(Object data) throws OpenDataException, InvalidObjectException { return data; @@ -243,11 +241,11 @@ return enumClass.getName(); } - Object toOpenTypeData(Object data) throws OpenDataException { + public Object toOpenTypeData(Object data) throws OpenDataException { return ((Enum) data).name(); } - Object toJavaTypeData(Object data) + public Object toJavaTypeData(Object data) throws OpenDataException, InvalidObjectException { try { @@ -315,7 +313,7 @@ return arrayClass.getName(); } - Object toOpenTypeData(Object data) throws OpenDataException { + public Object toOpenTypeData(Object data) throws OpenDataException { // If the base element type is a basic type // return the data as no conversion is needed. // Primitive types are not converted to wrappers. @@ -340,7 +338,7 @@ } - Object toJavaTypeData(Object data) + public Object toJavaTypeData(Object data) throws OpenDataException, InvalidObjectException { // If the base element type is a basic type @@ -457,7 +455,7 @@ return typeName; } - Object toOpenTypeData(Object data) throws OpenDataException { + public Object toOpenTypeData(Object data) throws OpenDataException { final List<Object> list = (List<Object>) data; final Object[] openArray = (Object[]) @@ -470,7 +468,7 @@ return openArray; } - Object toJavaTypeData(Object data) + public Object toJavaTypeData(Object data) throws OpenDataException, InvalidObjectException { final Object[] openArray = (Object[]) data; @@ -538,7 +536,7 @@ return typeName; } - Object toOpenTypeData(Object data) throws OpenDataException { + public Object toOpenTypeData(Object data) throws OpenDataException { final Map<Object,Object> map = (Map<Object,Object>) data; final TabularType tabularType = (TabularType) openType; final TabularData table = new TabularDataSupport(tabularType); @@ -556,7 +554,7 @@ return table; } - Object toJavaTypeData(Object data) + public Object toJavaTypeData(Object data) throws OpenDataException, InvalidObjectException { final TabularData td = (TabularData) data; @@ -605,8 +603,9 @@ // static class CompositeDataMXBeanType extends MappedMXBeanType { final Class<?> javaClass; - final boolean isCompositeData; + boolean isCompositeData = false; Method fromMethod = null; + Method toMethod = null; CompositeDataMXBeanType(Class<?> c) throws OpenDataException { this.javaClass = c; @@ -624,6 +623,26 @@ // that has no from method to be embeded in another class. } + // check if a static "toCompositeData" method exists + try { + toMethod = AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() { + public Method run() throws NoSuchMethodException { + Method m = javaClass.getDeclaredMethod("toCompositeData", javaClass); + if (m != null + && CompositeData.class.isAssignableFrom(m.getReturnType()) + && Modifier.isStatic(m.getModifiers())) { + m.setAccessible(true); + return m; + } else { + return null; + } + } + }); + } catch (PrivilegedActionException e) { + // ignore NoSuchMethodException since we allow classes + // that has no from method to be embeded in another class. + } + if (COMPOSITE_DATA_CLASS.isAssignableFrom(c)) { // c implements CompositeData - set openType to null // defer generating the CompositeType @@ -636,16 +655,16 @@ // Make a CompositeData containing all the getters final Method[] methods = AccessController.doPrivileged(new PrivilegedAction<Method[]>() { - public Method[] run() { - return javaClass.getMethods(); - } - }); + public Method[] run() { + return javaClass.getMethods(); + } + }); final List<String> names = new ArrayList<>(); final List<OpenType<?>> types = new ArrayList<>(); /* Select public methods that look like "T getX()" or "boolean - isX()", where T is not void and X is not the empty - string. Exclude "Class getClass()" inherited from Object. */ + isX()", where T is not void and X is not the empty + string. Exclude "Class getClass()" inherited from Object. */ for (int i = 0; i < methods.length; i++) { final Method method = methods[i]; final String name = method.getName(); @@ -676,10 +695,10 @@ final String[] nameArray = names.toArray(new String[0]); openType = new CompositeType(c.getName(), - c.getName(), - nameArray, // field names - nameArray, // field descriptions - types.toArray(new OpenType<?>[0])); + c.getName(), + nameArray, // field names + nameArray, // field descriptions + types.toArray(new OpenType<?>[0])); } } @@ -691,7 +710,23 @@ return javaClass.getName(); } - Object toOpenTypeData(Object data) throws OpenDataException { + public Object toOpenTypeData(Object data) throws OpenDataException { + if (toMethod != null) { + try { + return toMethod.invoke(null, data); + } catch (IllegalAccessException e) { + // should never reach here + throw new AssertionError(e); + } catch (InvocationTargetException e) { + final OpenDataException ode + = new OpenDataException("Failed to invoke " + + toMethod.getName() + " to convert " + javaClass.getName() + + " to CompositeData"); + ode.initCause(e); + throw ode; + } + } + if (data instanceof MemoryUsage) { return MemoryUsageCompositeData.toCompositeData((MemoryUsage) data); } @@ -712,10 +747,6 @@ toCompositeData((MemoryNotificationInfo) data); } - if (data instanceof VMOption) { - return VMOptionCompositeData.toCompositeData((VMOption) data); - } - if (isCompositeData) { // Classes that implement CompositeData // @@ -732,7 +763,7 @@ " is not supported for platform MXBeans"); } - Object toJavaTypeData(Object data) + public Object toJavaTypeData(Object data) throws OpenDataException, InvalidObjectException { if (fromMethod == null) {
--- a/jdk/src/java.management/share/classes/sun/management/NotificationEmitterSupport.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/classes/sun/management/NotificationEmitterSupport.java Fri Apr 17 09:40:02 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2012, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,13 +34,12 @@ import java.util.List; import java.util.ArrayList; -import java.util.ListIterator; import java.util.Collections; /** * Abstract helper class for notification emitter support. */ -abstract class NotificationEmitterSupport implements NotificationEmitter { +public abstract class NotificationEmitterSupport implements NotificationEmitter { protected NotificationEmitterSupport() { } @@ -135,7 +134,7 @@ } } - void sendNotification(Notification notification) { + public void sendNotification(Notification notification) { if (notification == null) { return; @@ -162,7 +161,7 @@ } } - boolean hasListeners() { + public boolean hasListeners() { synchronized (listenerLock) { return !listenerList.isEmpty(); }
--- a/jdk/src/java.management/share/classes/sun/management/ThreadImpl.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/classes/sun/management/ThreadImpl.java Fri Apr 17 09:40:02 2015 +0200 @@ -26,20 +26,18 @@ package sun.management; import java.lang.management.ManagementFactory; - import java.lang.management.ThreadInfo; - +import java.lang.management.ThreadMXBean; import javax.management.ObjectName; /** - * Implementation class for the thread subsystem. - * Standard and committed hotspot-specific metrics if any. - * - * ManagementFactory.getThreadMXBean() returns an instance - * of this class. + * Implementation for java.lang.management.ThreadMXBean as well as providing the + * supporting method for com.sun.management.ThreadMXBean. + * The supporting method for com.sun.management.ThreadMXBean can be moved to + * jdk.management in the future. */ -class ThreadImpl implements com.sun.management.ThreadMXBean { +public class ThreadImpl implements ThreadMXBean { private final VMManagement jvm; // default for thread contention monitoring is disabled. @@ -50,32 +48,38 @@ /** * Constructor of ThreadImpl class. */ - ThreadImpl(VMManagement vm) { + protected ThreadImpl(VMManagement vm) { this.jvm = vm; this.cpuTimeEnabled = jvm.isThreadCpuTimeEnabled(); this.allocatedMemoryEnabled = jvm.isThreadAllocatedMemoryEnabled(); } + @Override public int getThreadCount() { return jvm.getLiveThreadCount(); } + @Override public int getPeakThreadCount() { return jvm.getPeakThreadCount(); } + @Override public long getTotalStartedThreadCount() { return jvm.getTotalThreadCount(); } + @Override public int getDaemonThreadCount() { return jvm.getDaemonThreadCount(); } + @Override public boolean isThreadContentionMonitoringSupported() { return jvm.isThreadContentionMonitoringSupported(); } + @Override public synchronized boolean isThreadContentionMonitoringEnabled() { if (!isThreadContentionMonitoringSupported()) { throw new UnsupportedOperationException( @@ -84,18 +88,21 @@ return contentionMonitoringEnabled; } + @Override public boolean isThreadCpuTimeSupported() { return jvm.isOtherThreadCpuTimeSupported(); } + @Override public boolean isCurrentThreadCpuTimeSupported() { return jvm.isCurrentThreadCpuTimeSupported(); } - public boolean isThreadAllocatedMemorySupported() { + protected boolean isThreadAllocatedMemorySupported() { return jvm.isThreadAllocatedMemorySupported(); } + @Override public boolean isThreadCpuTimeEnabled() { if (!isThreadCpuTimeSupported() && !isCurrentThreadCpuTimeSupported()) { @@ -105,7 +112,7 @@ return cpuTimeEnabled; } - public boolean isThreadAllocatedMemoryEnabled() { + protected boolean isThreadAllocatedMemoryEnabled() { if (!isThreadAllocatedMemorySupported()) { throw new UnsupportedOperationException( "Thread allocated memory measurement is not supported"); @@ -113,6 +120,7 @@ return allocatedMemoryEnabled; } + @Override public long[] getAllThreadIds() { Util.checkMonitorAccess(); @@ -126,6 +134,7 @@ return ids; } + @Override public ThreadInfo getThreadInfo(long id) { long[] ids = new long[1]; ids[0] = id; @@ -133,6 +142,7 @@ return infos[0]; } + @Override public ThreadInfo getThreadInfo(long id, int maxDepth) { long[] ids = new long[1]; ids[0] = id; @@ -140,6 +150,7 @@ return infos[0]; } + @Override public ThreadInfo[] getThreadInfo(long[] ids) { return getThreadInfo(ids, 0); } @@ -157,6 +168,7 @@ } } + @Override public ThreadInfo[] getThreadInfo(long[] ids, int maxDepth) { verifyThreadIds(ids); @@ -180,6 +192,7 @@ return infos; } + @Override public void setThreadContentionMonitoringEnabled(boolean enable) { if (!isThreadContentionMonitoringSupported()) { throw new UnsupportedOperationException( @@ -213,6 +226,7 @@ return isThreadCpuTimeEnabled(); } + @Override public long getCurrentThreadCpuTime() { if (verifyCurrentThreadCpuTime()) { return getThreadTotalCpuTime0(0); @@ -220,6 +234,7 @@ return -1; } + @Override public long getThreadCpuTime(long id) { long[] ids = new long[1]; ids[0] = id; @@ -251,7 +266,7 @@ return isThreadCpuTimeEnabled(); } - public long[] getThreadCpuTime(long[] ids) { + protected long[] getThreadCpuTime(long[] ids) { boolean verified = verifyThreadCpuTime(ids); int length = ids.length; @@ -272,6 +287,7 @@ return times; } + @Override public long getCurrentThreadUserTime() { if (verifyCurrentThreadCpuTime()) { return getThreadUserCpuTime0(0); @@ -279,6 +295,7 @@ return -1; } + @Override public long getThreadUserTime(long id) { long[] ids = new long[1]; ids[0] = id; @@ -286,7 +303,7 @@ return times[0]; } - public long[] getThreadUserTime(long[] ids) { + protected long[] getThreadUserTime(long[] ids) { boolean verified = verifyThreadCpuTime(ids); int length = ids.length; @@ -307,6 +324,7 @@ return times; } + @Override public void setThreadCpuTimeEnabled(boolean enable) { if (!isThreadCpuTimeSupported() && !isCurrentThreadCpuTimeSupported()) { @@ -324,7 +342,7 @@ } } - public long getThreadAllocatedBytes(long id) { + protected long getThreadAllocatedBytes(long id) { long[] ids = new long[1]; ids[0] = id; final long[] sizes = getThreadAllocatedBytes(ids); @@ -343,7 +361,7 @@ return isThreadAllocatedMemoryEnabled(); } - public long[] getThreadAllocatedBytes(long[] ids) { + protected long[] getThreadAllocatedBytes(long[] ids) { boolean verified = verifyThreadAllocatedMemory(ids); long[] sizes = new long[ids.length]; @@ -355,7 +373,7 @@ return sizes; } - public void setThreadAllocatedMemoryEnabled(boolean enable) { + protected void setThreadAllocatedMemoryEnabled(boolean enable) { if (!isThreadAllocatedMemorySupported()) { throw new UnsupportedOperationException( "Thread allocated memory measurement is not supported."); @@ -371,6 +389,7 @@ } } + @Override public long[] findMonitorDeadlockedThreads() { Util.checkMonitorAccess(); @@ -387,6 +406,7 @@ return ids; } + @Override public long[] findDeadlockedThreads() { if (!isSynchronizerUsageSupported()) { throw new UnsupportedOperationException( @@ -408,15 +428,18 @@ return ids; } + @Override public void resetPeakThreadCount() { Util.checkControlAccess(); resetPeakThreadCount0(); } + @Override public boolean isObjectMonitorUsageSupported() { return jvm.isObjectMonitorUsageSupported(); } + @Override public boolean isSynchronizerUsageSupported() { return jvm.isSynchronizerUsageSupported(); } @@ -436,6 +459,7 @@ Util.checkMonitorAccess(); } + @Override public ThreadInfo[] getThreadInfo(long[] ids, boolean lockedMonitors, boolean lockedSynchronizers) { @@ -448,6 +472,7 @@ return dumpThreads0(ids, lockedMonitors, lockedSynchronizers); } + @Override public ThreadInfo[] dumpAllThreads(boolean lockedMonitors, boolean lockedSynchronizers) { verifyDumpThreads(lockedMonitors, lockedSynchronizers); @@ -477,6 +502,7 @@ // tid == 0 to reset contention times for all threads private static native void resetContentionTimes0(long tid); + @Override public ObjectName getObjectName() { return Util.newObjectName(ManagementFactory.THREAD_MXBEAN_NAME); }
--- a/jdk/src/java.management/share/classes/sun/management/Util.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/classes/sun/management/Util.java Fri Apr 17 09:40:02 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, 2008, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -81,7 +81,7 @@ static void checkMonitorAccess() throws SecurityException { checkAccess(monitorPermission); } - static void checkControlAccess() throws SecurityException { + public static void checkControlAccess() throws SecurityException { checkAccess(controlPermission); } }
--- a/jdk/src/java.management/share/classes/sun/management/VMOptionCompositeData.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2005, 2008, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -import com.sun.management.VMOption; -import com.sun.management.VMOption.Origin; -import javax.management.openmbean.CompositeType; -import javax.management.openmbean.CompositeData; -import javax.management.openmbean.CompositeDataSupport; -import javax.management.openmbean.OpenDataException; - -/** - * A CompositeData for VMOption for the local management support. - * This class avoids the performance penalty paid to the - * construction of a CompositeData use in the local case. - */ -public class VMOptionCompositeData extends LazyCompositeData { - private final VMOption option; - - private VMOptionCompositeData(VMOption option) { - this.option = option; - } - - public VMOption getVMOption() { - return option; - } - - public static CompositeData toCompositeData(VMOption option) { - VMOptionCompositeData vcd = new VMOptionCompositeData(option); - return vcd.getCompositeData(); - } - - protected CompositeData getCompositeData() { - // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH - // vmOptionItemNames! - final Object[] vmOptionItemValues = { - option.getName(), - option.getValue(), - option.isWriteable(), - option.getOrigin().toString(), - }; - - try { - return new CompositeDataSupport(vmOptionCompositeType, - vmOptionItemNames, - vmOptionItemValues); - } catch (OpenDataException e) { - // Should never reach here - throw new AssertionError(e); - } - } - - private static final CompositeType vmOptionCompositeType; - static { - try { - vmOptionCompositeType = (CompositeType) - MappedMXBeanType.toOpenType(VMOption.class); - } catch (OpenDataException e) { - // Should never reach here - throw new AssertionError(e); - } - } - - static CompositeType getVMOptionCompositeType() { - return vmOptionCompositeType; - } - - private static final String NAME = "name"; - private static final String VALUE = "value"; - private static final String WRITEABLE = "writeable"; - private static final String ORIGIN = "origin"; - - private static final String[] vmOptionItemNames = { - NAME, - VALUE, - WRITEABLE, - ORIGIN, - }; - - public static String getName(CompositeData cd) { - return getString(cd, NAME); - } - public static String getValue(CompositeData cd) { - return getString(cd, VALUE); - } - public static Origin getOrigin(CompositeData cd) { - String o = getString(cd, ORIGIN); - return Enum.valueOf(Origin.class, o); - } - public static boolean isWriteable(CompositeData cd) { - return getBoolean(cd, WRITEABLE); - } - - /** Validate if the input CompositeData has the expected - * CompositeType (i.e. contain all attributes with expected - * names and types). - */ - public static void validateCompositeData(CompositeData cd) { - if (cd == null) { - throw new NullPointerException("Null CompositeData"); - } - - if (!isTypeMatched(vmOptionCompositeType, cd.getCompositeType())) { - throw new IllegalArgumentException( - "Unexpected composite type for VMOption"); - } - } - - private static final long serialVersionUID = -2395573975093578470L; -}
--- a/jdk/src/java.management/share/classes/sun/management/spi/PlatformMBeanProvider.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/classes/sun/management/spi/PlatformMBeanProvider.java Fri Apr 17 09:40:02 2015 +0200 @@ -205,7 +205,7 @@ * Instantiates a new PlatformMBeanProvider. * * @throws SecurityException if the subclass (and calling code) does not - * have {@code RuntimePermission("sun.management.spi.PlatformMBeanProvider", "subclass")} + * have {@code RuntimePermission("sun.management.spi.PlatformMBeanProvider.subclass")} */ protected PlatformMBeanProvider () { this(checkSubclassPermission()); @@ -226,7 +226,7 @@ private static Void checkSubclassPermission() { SecurityManager sm = System.getSecurityManager(); if (sm != null) { - sm.checkPermission(new RuntimePermission(PlatformMBeanProvider.class.getName(), "subclass")); + sm.checkPermission(new RuntimePermission(PlatformMBeanProvider.class.getName()+".subclass")); } return null; }
--- a/jdk/src/java.management/share/native/libmanagement/DiagnosticCommandImpl.c Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,194 +0,0 @@ -/* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include <stdlib.h> -#include <jni.h> -#include "management.h" -#include "sun_management_DiagnosticCommandImpl.h" - -JNIEXPORT void JNICALL Java_sun_management_DiagnosticCommandImpl_setNotificationEnabled -(JNIEnv *env, jobject dummy, jboolean enabled) { - if (jmm_version <= JMM_VERSION_1_2_2) { - JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", - "JMX interface to diagnostic framework notifications is not supported by this VM"); - return; - } - jmm_interface->SetDiagnosticFrameworkNotificationEnabled(env, enabled); -} - -JNIEXPORT jobjectArray JNICALL -Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommands - (JNIEnv *env, jobject dummy) -{ - return jmm_interface->GetDiagnosticCommands(env); -} - -jobject getDiagnosticCommandArgumentInfoArray(JNIEnv *env, jstring command, - int num_arg) { - int i; - jobject obj; - jobjectArray result; - dcmdArgInfo* dcmd_arg_info_array; - jclass dcmdArgInfoCls; - jclass arraysCls; - jmethodID mid; - jobject resultList; - - dcmd_arg_info_array = (dcmdArgInfo*) malloc(num_arg * sizeof(dcmdArgInfo)); - /* According to ISO C it is perfectly legal for malloc to return zero if called with a zero argument */ - if (dcmd_arg_info_array == NULL && num_arg != 0) { - return NULL; - } - jmm_interface->GetDiagnosticCommandArgumentsInfo(env, command, - dcmd_arg_info_array); - dcmdArgInfoCls = (*env)->FindClass(env, - "sun/management/DiagnosticCommandArgumentInfo"); - if ((*env)->ExceptionCheck(env)) { - free(dcmd_arg_info_array); - return NULL; - } - - result = (*env)->NewObjectArray(env, num_arg, dcmdArgInfoCls, NULL); - if (result == NULL) { - free(dcmd_arg_info_array); - return NULL; - } - for (i=0; i<num_arg; i++) { - obj = JNU_NewObjectByName(env, - "sun/management/DiagnosticCommandArgumentInfo", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZI)V", - (*env)->NewStringUTF(env,dcmd_arg_info_array[i].name), - (*env)->NewStringUTF(env,dcmd_arg_info_array[i].description), - (*env)->NewStringUTF(env,dcmd_arg_info_array[i].type), - dcmd_arg_info_array[i].default_string == NULL ? NULL: - (*env)->NewStringUTF(env, dcmd_arg_info_array[i].default_string), - dcmd_arg_info_array[i].mandatory, - dcmd_arg_info_array[i].option, - dcmd_arg_info_array[i].multiple, - dcmd_arg_info_array[i].position); - if (obj == NULL) { - free(dcmd_arg_info_array); - return NULL; - } - (*env)->SetObjectArrayElement(env, result, i, obj); - } - free(dcmd_arg_info_array); - arraysCls = (*env)->FindClass(env, "java/util/Arrays"); - if ((*env)->ExceptionCheck(env)) { - return NULL; - } - mid = (*env)->GetStaticMethodID(env, arraysCls, - "asList", "([Ljava/lang/Object;)Ljava/util/List;"); - resultList = (*env)->CallStaticObjectMethod(env, arraysCls, mid, result); - if ((*env)->ExceptionCheck(env)) { - // Make sure we return NULL in case of OOM inside Java - return NULL; - } - return resultList; -} - -/* Throws IllegalArgumentException if at least one of the diagnostic command - * passed in argument is not supported by the JVM - */ -JNIEXPORT jobjectArray JNICALL -Java_sun_management_DiagnosticCommandImpl_getDiagnosticCommandInfo -(JNIEnv *env, jobject dummy, jobjectArray commands) -{ - int i; - jclass dcmdInfoCls; - jobject result; - jobjectArray args; - jobject obj; - jmmOptionalSupport mos; - jint ret = jmm_interface->GetOptionalSupport(env, &mos); - jsize num_commands; - dcmdInfo* dcmd_info_array; - - if (commands == NULL) { - JNU_ThrowNullPointerException(env, "Invalid String Array"); - return NULL; - } - num_commands = (*env)->GetArrayLength(env, commands); - dcmdInfoCls = (*env)->FindClass(env, - "sun/management/DiagnosticCommandInfo"); - if ((*env)->ExceptionCheck(env)) { - return NULL; - } - - result = (*env)->NewObjectArray(env, num_commands, dcmdInfoCls, NULL); - if (result == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); - return NULL; - } - if (num_commands == 0) { - /* Handle the 'zero commands' case specially to avoid calling 'malloc()' */ - /* with a zero argument because that may legally return a NULL pointer. */ - return result; - } - dcmd_info_array = (dcmdInfo*) malloc(num_commands * sizeof(dcmdInfo)); - if (dcmd_info_array == NULL) { - JNU_ThrowOutOfMemoryError(env, NULL); - return NULL; - } - jmm_interface->GetDiagnosticCommandInfo(env, commands, dcmd_info_array); - for (i=0; i<num_commands; i++) { - args = getDiagnosticCommandArgumentInfoArray(env, - (*env)->GetObjectArrayElement(env,commands,i), - dcmd_info_array[i].num_arguments); - if (args == NULL) { - free(dcmd_info_array); - JNU_ThrowOutOfMemoryError(env, 0); - return NULL; - } - obj = JNU_NewObjectByName(env, - "sun/management/DiagnosticCommandInfo", - "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLjava/util/List;)V", - (*env)->NewStringUTF(env,dcmd_info_array[i].name), - (*env)->NewStringUTF(env,dcmd_info_array[i].description), - (*env)->NewStringUTF(env,dcmd_info_array[i].impact), - dcmd_info_array[i].permission_class==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_class), - dcmd_info_array[i].permission_name==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_name), - dcmd_info_array[i].permission_action==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_action), - dcmd_info_array[i].enabled, - args); - if (obj == NULL) { - free(dcmd_info_array); - JNU_ThrowOutOfMemoryError(env, 0); - return NULL; - } - (*env)->SetObjectArrayElement(env, result, i, obj); - } - free(dcmd_info_array); - return result; -} - -/* Throws IllegalArgumentException if the diagnostic command - * passed in argument is not supported by the JVM - */ -JNIEXPORT jstring JNICALL -Java_sun_management_DiagnosticCommandImpl_executeDiagnosticCommand -(JNIEnv *env, jobject dummy, jstring command) { - return jmm_interface->ExecuteDiagnosticCommand(env, command); -}
--- a/jdk/src/java.management/share/native/libmanagement/Flag.c Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,236 +0,0 @@ -/* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <jni.h> -#include "management.h" -#include "sun_management_Flag.h" - -static jobject default_origin = NULL; -static jobject vm_creation_origin = NULL; -static jobject mgmt_origin = NULL; -static jobject envvar_origin = NULL; -static jobject config_file_origin = NULL; -static jobject ergo_origin = NULL; -static jobject attach_origin = NULL; -static jobject other_origin = NULL; - -JNIEXPORT jint JNICALL -Java_sun_management_Flag_getInternalFlagCount - (JNIEnv *env, jclass cls) -{ - jlong count = jmm_interface->GetLongAttribute(env, NULL, - JMM_VM_GLOBAL_COUNT); - return (jint) count; -} - -JNIEXPORT jobjectArray JNICALL - Java_sun_management_Flag_getAllFlagNames -(JNIEnv *env, jclass cls) -{ - return jmm_interface->GetVMGlobalNames(env); -} - -static jobject find_origin_constant(JNIEnv* env, const char* enum_name) { - jvalue field; - field = JNU_GetStaticFieldByName(env, - NULL, - "com/sun/management/VMOption$Origin", - enum_name, - "Lcom/sun/management/VMOption$Origin;"); - return (*env)->NewGlobalRef(env, field.l); -} - -JNIEXPORT void JNICALL -Java_sun_management_Flag_initialize - (JNIEnv *env, jclass cls) -{ - default_origin = find_origin_constant(env, "DEFAULT"); - vm_creation_origin = find_origin_constant(env, "VM_CREATION"); - mgmt_origin = find_origin_constant(env, "MANAGEMENT"); - envvar_origin = find_origin_constant(env, "ENVIRON_VAR"); - config_file_origin = find_origin_constant(env, "CONFIG_FILE"); - ergo_origin = find_origin_constant(env, "ERGONOMIC"); - attach_origin = find_origin_constant(env, "ATTACH_ON_DEMAND"); - other_origin = find_origin_constant(env, "OTHER"); -} - -JNIEXPORT jint JNICALL -Java_sun_management_Flag_getFlags - (JNIEnv *env, jclass cls, jobjectArray names, jobjectArray flags, jint count) -{ - jint num_flags, i, index; - jmmVMGlobal* globals; - size_t gsize; - const char* class_name = "sun/management/Flag"; - const char* signature = "(Ljava/lang/String;Ljava/lang/Object;ZZLcom/sun/management/VMOption$Origin;)V"; - jobject origin; - jobject valueObj; - jobject flag; - - if (flags == NULL) { - JNU_ThrowNullPointerException(env, 0); - return 0; - } - - if (count <= 0) { - JNU_ThrowIllegalArgumentException(env, 0); - return 0; - } - - gsize = (size_t)count * sizeof(jmmVMGlobal); - globals = (jmmVMGlobal*) malloc(gsize); - if (globals == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); - return 0; - } - - memset(globals, 0, gsize); - num_flags = jmm_interface->GetVMGlobals(env, names, globals, count); - if (num_flags == 0) { - free(globals); - return 0; - } - - index = 0; - for (i = 0; i < count; i++) { - if (globals[i].name == NULL) { - continue; - } - switch (globals[i].type) { - case JMM_VMGLOBAL_TYPE_JBOOLEAN: - valueObj = JNU_NewObjectByName(env, "java/lang/Boolean", "(Z)V", - globals[i].value.z); - break; - case JMM_VMGLOBAL_TYPE_JSTRING: - valueObj = globals[i].value.l; - break; - case JMM_VMGLOBAL_TYPE_JLONG: - valueObj = JNU_NewObjectByName(env, "java/lang/Long", "(J)V", - globals[i].value.j); - break; - case JMM_VMGLOBAL_TYPE_JDOUBLE: - valueObj = JNU_NewObjectByName(env, "java/lang/Double", "(D)V", - globals[i].value.d); - break; - default: - // ignore unsupported type - continue; - } - switch (globals[i].origin) { - case JMM_VMGLOBAL_ORIGIN_DEFAULT: - origin = default_origin; - break; - case JMM_VMGLOBAL_ORIGIN_COMMAND_LINE: - origin = vm_creation_origin; - break; - case JMM_VMGLOBAL_ORIGIN_MANAGEMENT: - origin = mgmt_origin; - break; - case JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR: - origin = envvar_origin; - break; - case JMM_VMGLOBAL_ORIGIN_CONFIG_FILE: - origin = config_file_origin; - break; - case JMM_VMGLOBAL_ORIGIN_ERGONOMIC: - origin = ergo_origin; - break; - case JMM_VMGLOBAL_ORIGIN_ATTACH_ON_DEMAND: - origin = attach_origin; - break; - case JMM_VMGLOBAL_ORIGIN_OTHER: - origin = other_origin; - break; - default: - // unknown origin - origin = other_origin; - break; - } - flag = JNU_NewObjectByName(env, class_name, signature, globals[i].name, - valueObj, globals[i].writeable, - globals[i].external, origin); - if (flag == NULL) { - free(globals); - JNU_ThrowOutOfMemoryError(env, 0); - return 0; - } - (*env)->SetObjectArrayElement(env, flags, index, flag); - index++; - } - - if (index != num_flags) { - JNU_ThrowInternalError(env, "Number of Flag objects created unmatched"); - free(globals); - return 0; - } - - free(globals); - - /* return the number of Flag objects created */ - return num_flags; -} - -JNIEXPORT void JNICALL -Java_sun_management_Flag_setLongValue - (JNIEnv *env, jclass cls, jstring name, jlong value) -{ - jvalue v; - v.j = value; - - jmm_interface->SetVMGlobal(env, name, v); -} - -JNIEXPORT void JNICALL -Java_sun_management_Flag_setDoubleValue - (JNIEnv *env, jclass cls, jstring name, jdouble value) -{ - jvalue v; - v.d = value; - - jmm_interface->SetVMGlobal(env, name, v); -} - -JNIEXPORT void JNICALL -Java_sun_management_Flag_setBooleanValue - (JNIEnv *env, jclass cls, jstring name, jboolean value) -{ - jvalue v; - v.z = value; - - jmm_interface->SetVMGlobal(env, name, v); -} - -JNIEXPORT void JNICALL -Java_sun_management_Flag_setStringValue - (JNIEnv *env, jclass cls, jstring name, jstring value) -{ - jvalue v; - v.l = value; - - jmm_interface->SetVMGlobal(env, name, v); -}
--- a/jdk/src/java.management/share/native/libmanagement/GarbageCollectorImpl.c Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/src/java.management/share/native/libmanagement/GarbageCollectorImpl.c Fri Apr 17 09:40:02 2015 +0200 @@ -36,17 +36,3 @@ (JNIEnv *env, jobject mgr) { return jmm_interface->GetLongAttribute(env, mgr, JMM_GC_TIME_MS); } - - -JNIEXPORT void JNICALL Java_sun_management_GarbageCollectorImpl_setNotificationEnabled -(JNIEnv *env, jobject dummy, jobject gc,jboolean enabled) { - - if (gc == NULL) { - JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); - return; - } - if((jmm_version > JMM_VERSION_1_2) - || (jmm_version == JMM_VERSION_1_2 && ((jmm_version&0xFF)>=1))) { - jmm_interface->SetGCNotificationEnabled(env, gc, enabled); - } -}
--- a/jdk/src/java.management/share/native/libmanagement/GcInfoBuilder.c Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,284 +0,0 @@ -/* - * Copyright (c) 2003, 2004, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include <stdlib.h> -#include <stdio.h> -#include <jni.h> -#include "management.h" -#include "sun_management_GcInfoBuilder.h" - -JNIEXPORT jint JNICALL Java_sun_management_GcInfoBuilder_getNumGcExtAttributes - (JNIEnv *env, jobject dummy, jobject gc) { - jlong value; - - if (gc == NULL) { - JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); - return 0; - } - value = jmm_interface->GetLongAttribute(env, gc, - JMM_GC_EXT_ATTRIBUTE_INFO_SIZE); - return (jint) value; -} - -JNIEXPORT void JNICALL Java_sun_management_GcInfoBuilder_fillGcAttributeInfo - (JNIEnv *env, jobject dummy, jobject gc, - jint num_attributes, jobjectArray attributeNames, - jcharArray types, jobjectArray descriptions) { - - jmmExtAttributeInfo* ext_att_info; - jchar* nativeTypes; - jstring attName = NULL; - jstring desc = NULL; - jint ret = 0; - jint i; - - if (gc == NULL) { - JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); - return; - } - - if (num_attributes <= 0) { - JNU_ThrowIllegalArgumentException(env, "Invalid num_attributes"); - return; - } - - ext_att_info = (jmmExtAttributeInfo*) malloc((size_t)num_attributes * - sizeof(jmmExtAttributeInfo)); - if (ext_att_info == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); - return; - } - ret = jmm_interface->GetGCExtAttributeInfo(env, gc, - ext_att_info, num_attributes); - if (ret != num_attributes) { - JNU_ThrowInternalError(env, "Unexpected num_attributes"); - free(ext_att_info); - return; - } - - nativeTypes = (jchar*) malloc((size_t)num_attributes * sizeof(jchar)); - if (nativeTypes == NULL) { - free(ext_att_info); - JNU_ThrowOutOfMemoryError(env, 0); - return; - } - for (i = 0; i < num_attributes; i++) { - nativeTypes[i] = ext_att_info[i].type; - attName = (*env)->NewStringUTF(env, ext_att_info[i].name); - desc = (*env)->NewStringUTF(env, ext_att_info[i].description); - (*env)->SetObjectArrayElement(env, attributeNames, i, attName); - (*env)->SetObjectArrayElement(env, descriptions, i, desc); - } - (*env)->SetCharArrayRegion(env, types, 0, num_attributes, nativeTypes); - - if (ext_att_info != NULL) { - free(ext_att_info); - } - if (nativeTypes != NULL) { - free(nativeTypes); - } -} - -static void setLongValueAtObjectArray(JNIEnv *env, jobjectArray array, - jsize index, jlong value) { - static const char* class_name = "java/lang/Long"; - static const char* signature = "(J)V"; - jobject obj = JNU_NewObjectByName(env, class_name, signature, value); - - (*env)->SetObjectArrayElement(env, array, index, obj); -} - -static void setBooleanValueAtObjectArray(JNIEnv *env, jobjectArray array, - jsize index, jboolean value) { - static const char* class_name = "java/lang/Boolean"; - static const char* signature = "(Z)V"; - jobject obj = JNU_NewObjectByName(env, class_name, signature, value); - - (*env)->SetObjectArrayElement(env, array, index, obj); -} - -static void setByteValueAtObjectArray(JNIEnv *env, jobjectArray array, - jsize index, jbyte value) { - static const char* class_name = "java/lang/Byte"; - static const char* signature = "(B)V"; - jobject obj = JNU_NewObjectByName(env, class_name, signature, value); - - (*env)->SetObjectArrayElement(env, array, index, obj); -} - -static void setIntValueAtObjectArray(JNIEnv *env, jobjectArray array, - jsize index, jint value) { - static const char* class_name = "java/lang/Integer"; - static const char* signature = "(I)V"; - jobject obj = JNU_NewObjectByName(env, class_name, signature, value); - - (*env)->SetObjectArrayElement(env, array, index, obj); -} - -static void setShortValueAtObjectArray(JNIEnv *env, jobjectArray array, - jsize index, jshort value) { - static const char* class_name = "java/lang/Short"; - static const char* signature = "(S)V"; - jobject obj = JNU_NewObjectByName(env, class_name, signature, value); - - (*env)->SetObjectArrayElement(env, array, index, obj); -} - -static void setDoubleValueAtObjectArray(JNIEnv *env, jobjectArray array, - jsize index, jdouble value) { - static const char* class_name = "java/lang/Double"; - static const char* signature = "(D)V"; - jobject obj = JNU_NewObjectByName(env, class_name, signature, value); - - (*env)->SetObjectArrayElement(env, array, index, obj); -} - -static void setFloatValueAtObjectArray(JNIEnv *env, jobjectArray array, - jsize index, jfloat value) { - static const char* class_name = "java/lang/Float"; - static const char* signature = "(D)V"; - jobject obj = JNU_NewObjectByName(env, class_name, signature, value); - - (*env)->SetObjectArrayElement(env, array, index, obj); -} - -static void setCharValueAtObjectArray(JNIEnv *env, jobjectArray array, - jsize index, jchar value) { - static const char* class_name = "java/lang/Character"; - static const char* signature = "(C)V"; - jobject obj = JNU_NewObjectByName(env, class_name, signature, value); - - (*env)->SetObjectArrayElement(env, array, index, obj); -} - -JNIEXPORT jobject JNICALL Java_sun_management_GcInfoBuilder_getLastGcInfo0 - (JNIEnv *env, jobject builder, jobject gc, - jint ext_att_count, jobjectArray ext_att_values, jcharArray ext_att_types, - jobjectArray usageBeforeGC, jobjectArray usageAfterGC) { - - jmmGCStat gc_stat; - jchar* nativeTypes; - jsize i; - jvalue v; - - if (gc == NULL) { - JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); - return 0; - } - - if (ext_att_count <= 0) { - JNU_ThrowIllegalArgumentException(env, "Invalid ext_att_count"); - return 0; - } - - gc_stat.usage_before_gc = usageBeforeGC; - gc_stat.usage_after_gc = usageAfterGC; - gc_stat.gc_ext_attribute_values_size = ext_att_count; - if (ext_att_count > 0) { - gc_stat.gc_ext_attribute_values = (jvalue*) malloc((size_t)ext_att_count * - sizeof(jvalue)); - if (gc_stat.gc_ext_attribute_values == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); - return 0; - } - } else { - gc_stat.gc_ext_attribute_values = NULL; - } - - - jmm_interface->GetLastGCStat(env, gc, &gc_stat); - if (gc_stat.gc_index == 0) { - if (gc_stat.gc_ext_attribute_values != NULL) { - free(gc_stat.gc_ext_attribute_values); - } - return 0; - } - - // convert the ext_att_types to native types - nativeTypes = (jchar*) malloc((size_t)ext_att_count * sizeof(jchar)); - if (nativeTypes == NULL) { - if (gc_stat.gc_ext_attribute_values != NULL) { - free(gc_stat.gc_ext_attribute_values); - } - JNU_ThrowOutOfMemoryError(env, 0); - return 0; - } - (*env)->GetCharArrayRegion(env, ext_att_types, 0, ext_att_count, nativeTypes); - for (i = 0; i < ext_att_count; i++) { - v = gc_stat.gc_ext_attribute_values[i]; - switch (nativeTypes[i]) { - case 'Z': - setBooleanValueAtObjectArray(env, ext_att_values, i, v.z); - break; - case 'B': - setByteValueAtObjectArray(env, ext_att_values, i, v.b); - break; - case 'C': - setCharValueAtObjectArray(env, ext_att_values, i, v.c); - break; - case 'S': - setShortValueAtObjectArray(env, ext_att_values, i, v.s); - break; - case 'I': - setIntValueAtObjectArray(env, ext_att_values, i, v.i); - break; - case 'J': - setLongValueAtObjectArray(env, ext_att_values, i, v.j); - break; - case 'F': - setFloatValueAtObjectArray(env, ext_att_values, i, v.f); - break; - case 'D': - setDoubleValueAtObjectArray(env, ext_att_values, i, v.d); - break; - default: - if (gc_stat.gc_ext_attribute_values != NULL) { - free(gc_stat.gc_ext_attribute_values); - } - if (nativeTypes != NULL) { - free(nativeTypes); - } - JNU_ThrowInternalError(env, "Unsupported attribute type"); - return 0; - } - } - if (gc_stat.gc_ext_attribute_values != NULL) { - free(gc_stat.gc_ext_attribute_values); - } - if (nativeTypes != NULL) { - free(nativeTypes); - } - - return JNU_NewObjectByName(env, - "com/sun/management/GcInfo", - "(Lsun/management/GcInfoBuilder;JJJ[Ljava/lang/management/MemoryUsage;[Ljava/lang/management/MemoryUsage;[Ljava/lang/Object;)V", - builder, - gc_stat.gc_index, - gc_stat.start_time, - gc_stat.end_time, - usageBeforeGC, - usageAfterGC, - ext_att_values); -}
--- a/jdk/src/java.management/share/native/libmanagement/HotSpotDiagnostic.c Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include <jni.h> -#include "jvm.h" -#include "management.h" -#include "sun_management_HotSpotDiagnostic.h" - -JNIEXPORT void JNICALL -Java_sun_management_HotSpotDiagnostic_dumpHeap0 - (JNIEnv *env, jobject dummy, jstring outputfile, jboolean live) -{ - jmm_interface->DumpHeap0(env, outputfile, live); -}
--- a/jdk/src/java.management/unix/classes/sun/management/OperatingSystemImpl.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -/** - * Implementation class for the operating system. - * Standard and committed hotspot-specific metrics if any. - * - * ManagementFactory.getOperatingSystemMXBean() returns an instance - * of this class. - */ -class OperatingSystemImpl extends BaseOperatingSystemImpl - implements com.sun.management.UnixOperatingSystemMXBean { - - OperatingSystemImpl(VMManagement vm) { - super(vm); - } - - public long getCommittedVirtualMemorySize() { - return getCommittedVirtualMemorySize0(); - } - - public long getTotalSwapSpaceSize() { - return getTotalSwapSpaceSize0(); - } - - public long getFreeSwapSpaceSize() { - return getFreeSwapSpaceSize0(); - } - - public long getProcessCpuTime() { - return getProcessCpuTime0(); - } - - public long getFreePhysicalMemorySize() { - return getFreePhysicalMemorySize0(); - } - - public long getTotalPhysicalMemorySize() { - return getTotalPhysicalMemorySize0(); - } - - public long getOpenFileDescriptorCount() { - return getOpenFileDescriptorCount0(); - } - - public long getMaxFileDescriptorCount() { - return getMaxFileDescriptorCount0(); - } - - public double getSystemCpuLoad() { - return getSystemCpuLoad0(); - } - - public double getProcessCpuLoad() { - return getProcessCpuLoad0(); - } - - /* native methods */ - private native long getCommittedVirtualMemorySize0(); - private native long getFreePhysicalMemorySize0(); - private native long getFreeSwapSpaceSize0(); - private native long getMaxFileDescriptorCount0(); - private native long getOpenFileDescriptorCount0(); - private native long getProcessCpuTime0(); - private native double getProcessCpuLoad0(); - private native double getSystemCpuLoad0(); - private native long getTotalPhysicalMemorySize0(); - private native long getTotalSwapSpaceSize0(); - - static { - initialize0(); - } - - private static native void initialize0(); -}
--- a/jdk/src/java.management/unix/native/libmanagement/LinuxOperatingSystem.c Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,333 +0,0 @@ -/* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include <stdio.h> -#include <stdint.h> -#include <stdarg.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <sys/resource.h> -#include <sys/types.h> -#include <dirent.h> -#include <stdlib.h> -#include <dlfcn.h> -#include <pthread.h> -#include <inttypes.h> -#include "sun_management_OperatingSystemImpl.h" - -struct ticks { - uint64_t used; - uint64_t usedKernel; - uint64_t total; -}; - -typedef struct ticks ticks; - -typedef enum { - CPU_LOAD_VM_ONLY, - CPU_LOAD_GLOBAL, -} CpuLoadTarget; - -static struct perfbuf { - int nProcs; - ticks jvmTicks; - ticks cpuTicks; - ticks *cpus; -} counters; - -#define DEC_64 "%"SCNd64 - -static void next_line(FILE *f) { - while (fgetc(f) != '\n'); -} - -/** - * Return the total number of ticks since the system was booted. - * If the usedTicks parameter is not NULL, it will be filled with - * the number of ticks spent on actual processes (user, system or - * nice processes) since system boot. Note that this is the total number - * of "executed" ticks on _all_ CPU:s, that is on a n-way system it is - * n times the number of ticks that has passed in clock time. - * - * Returns a negative value if the reading of the ticks failed. - */ -static int get_totalticks(int which, ticks *pticks) { - FILE *fh; - uint64_t userTicks, niceTicks, systemTicks, idleTicks; - int n; - - if((fh = fopen("/proc/stat", "r")) == NULL) { - return -1; - } - - n = fscanf(fh, "cpu " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64, - &userTicks, &niceTicks, &systemTicks, &idleTicks); - - // Move to next line - next_line(fh); - - //find the line for requested cpu faster to just iterate linefeeds? - if (which != -1) { - int i; - for (i = 0; i < which; i++) { - if (fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64, &userTicks, &niceTicks, &systemTicks, &idleTicks) != 4) { - fclose(fh); - return -2; - } - next_line(fh); - } - n = fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 "\n", - &userTicks, &niceTicks, &systemTicks, &idleTicks); - } - - fclose(fh); - if (n != 4) { - return -2; - } - - pticks->used = userTicks + niceTicks; - pticks->usedKernel = systemTicks; - pticks->total = userTicks + niceTicks + systemTicks + idleTicks; - - return 0; -} - -static int vread_statdata(const char *procfile, const char *fmt, va_list args) { - FILE *f; - int n; - char buf[2048]; - - if ((f = fopen(procfile, "r")) == NULL) { - return -1; - } - - if ((n = fread(buf, 1, sizeof(buf), f)) != -1) { - char *tmp; - - buf[n-1] = '\0'; - /** skip through pid and exec name. the exec name _could be wacky_ (renamed) and - * make scanf go mupp. - */ - if ((tmp = strrchr(buf, ')')) != NULL) { - // skip the ')' and the following space but check that the buffer is long enough - tmp += 2; - if (tmp < buf + n) { - n = vsscanf(tmp, fmt, args); - } - } - } - - fclose(f); - - return n; -} - -static int read_statdata(const char *procfile, const char *fmt, ...) { - int n; - va_list args; - - va_start(args, fmt); - n = vread_statdata(procfile, fmt, args); - va_end(args); - return n; -} - -/** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */ -static int read_ticks(const char *procfile, uint64_t *userTicks, uint64_t *systemTicks) { - return read_statdata(procfile, "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u "DEC_64" "DEC_64, - userTicks, systemTicks - ); -} - -/** - * Return the number of ticks spent in any of the processes belonging - * to the JVM on any CPU. - */ -static int get_jvmticks(ticks *pticks) { - uint64_t userTicks; - uint64_t systemTicks; - - if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) < 0) { - return -1; - } - - // get the total - if (get_totalticks(-1, pticks) < 0) { - return -1; - } - - pticks->used = userTicks; - pticks->usedKernel = systemTicks; - - return 0; -} - -/** - * This method must be called first, before any data can be gathererd. - */ -int perfInit() { - static int initialized=1; - - if (!initialized) { - int i; - - int n = sysconf(_SC_NPROCESSORS_ONLN); - if (n <= 0) { - n = 1; - } - - counters.cpus = calloc(n,sizeof(ticks)); - if (counters.cpus != NULL) { - // For the CPU load - get_totalticks(-1, &counters.cpuTicks); - - for (i = 0; i < n; i++) { - get_totalticks(i, &counters.cpus[i]); - } - // For JVM load - get_jvmticks(&counters.jvmTicks); - initialized = 1; - } - } - - return initialized ? 0 : -1; -} - -#define MAX(a,b) (a>b?a:b) -#define MIN(a,b) (a<b?a:b) - -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - -/** - * Return the load of the CPU as a double. 1.0 means the CPU process uses all - * available time for user or system processes, 0.0 means the CPU uses all time - * being idle. - * - * Returns a negative value if there is a problem in determining the CPU load. - */ - -static double get_cpuload_internal(int which, double *pkernelLoad, CpuLoadTarget target) { - uint64_t udiff, kdiff, tdiff; - ticks *pticks, tmp; - double user_load = -1.0; - int failed = 0; - - *pkernelLoad = 0.0; - - pthread_mutex_lock(&lock); - - if(perfInit() == 0) { - - if (target == CPU_LOAD_VM_ONLY) { - pticks = &counters.jvmTicks; - } else if (which == -1) { - pticks = &counters.cpuTicks; - } else { - pticks = &counters.cpus[which]; - } - - tmp = *pticks; - - if (target == CPU_LOAD_VM_ONLY) { - if (get_jvmticks(pticks) != 0) { - failed = 1; - } - } else if (get_totalticks(which, pticks) < 0) { - failed = 1; - } - - if(!failed) { - // seems like we sometimes end up with less kernel ticks when - // reading /proc/self/stat a second time, timing issue between cpus? - if (pticks->usedKernel < tmp.usedKernel) { - kdiff = 0; - } else { - kdiff = pticks->usedKernel - tmp.usedKernel; - } - tdiff = pticks->total - tmp.total; - udiff = pticks->used - tmp.used; - - if (tdiff == 0) { - user_load = 0; - } else { - if (tdiff < (udiff + kdiff)) { - tdiff = udiff + kdiff; - } - *pkernelLoad = (kdiff / (double)tdiff); - // BUG9044876, normalize return values to sane values - *pkernelLoad = MAX(*pkernelLoad, 0.0); - *pkernelLoad = MIN(*pkernelLoad, 1.0); - - user_load = (udiff / (double)tdiff); - user_load = MAX(user_load, 0.0); - user_load = MIN(user_load, 1.0); - } - } - } - pthread_mutex_unlock(&lock); - return user_load; -} - -double get_cpu_load(int which) { - double u, s; - u = get_cpuload_internal(which, &s, CPU_LOAD_GLOBAL); - if (u < 0) { - return -1.0; - } - // Cap total systemload to 1.0 - return MIN((u + s), 1.0); -} - -double get_process_load() { - double u, s; - u = get_cpuload_internal(-1, &s, CPU_LOAD_VM_ONLY); - if (u < 0) { - return -1.0; - } - return u + s; -} - -JNIEXPORT jdouble JNICALL -Java_sun_management_OperatingSystemImpl_getSystemCpuLoad0 -(JNIEnv *env, jobject dummy) -{ - if(perfInit() == 0) { - return get_cpu_load(-1); - } else { - return -1.0; - } -} - -JNIEXPORT jdouble JNICALL -Java_sun_management_OperatingSystemImpl_getProcessCpuLoad0 -(JNIEnv *env, jobject dummy) -{ - if(perfInit() == 0) { - return get_process_load(); - } else { - return -1.0; - } -}
--- a/jdk/src/java.management/unix/native/libmanagement/MacosxOperatingSystem.c Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,161 +0,0 @@ -/* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "sun_management_OperatingSystemImpl.h" - -#include <sys/time.h> -#include <mach/mach.h> -#include <mach/task_info.h> - -#include "jvm.h" - -JNIEXPORT jdouble JNICALL -Java_sun_management_OperatingSystemImpl_getSystemCpuLoad0 -(JNIEnv *env, jobject dummy) -{ - // This code is influenced by the darwin top source - - kern_return_t kr; - mach_msg_type_number_t count; - host_cpu_load_info_data_t load; - - static jlong last_used = 0; - static jlong last_total = 0; - - count = HOST_CPU_LOAD_INFO_COUNT; - kr = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&load, &count); - if (kr != KERN_SUCCESS) { - return -1; - } - - jlong used = load.cpu_ticks[CPU_STATE_USER] + load.cpu_ticks[CPU_STATE_NICE] + load.cpu_ticks[CPU_STATE_SYSTEM]; - jlong total = used + load.cpu_ticks[CPU_STATE_IDLE]; - - if (last_used == 0 || last_total == 0) { - // First call, just set the last values - last_used = used; - last_total = total; - // return 0 since we have no data, not -1 which indicates error - return 0; - } - - jlong used_delta = used - last_used; - jlong total_delta = total - last_total; - - jdouble cpu = (jdouble) used_delta / total_delta; - - last_used = used; - last_total = total; - - return cpu; -} - - -#define TIME_VALUE_TO_TIMEVAL(a, r) do { \ - (r)->tv_sec = (a)->seconds; \ - (r)->tv_usec = (a)->microseconds; \ -} while (0) - - -#define TIME_VALUE_TO_MICROSECONDS(TV) \ - ((TV).tv_sec * 1000 * 1000 + (TV).tv_usec) - - -JNIEXPORT jdouble JNICALL -Java_sun_management_OperatingSystemImpl_getProcessCpuLoad0 -(JNIEnv *env, jobject dummy) -{ - // This code is influenced by the darwin top source - - struct task_basic_info_64 task_info_data; - struct task_thread_times_info thread_info_data; - struct timeval user_timeval, system_timeval, task_timeval; - struct timeval now; - mach_port_t task = mach_task_self(); - kern_return_t kr; - - static jlong last_task_time = 0; - static jlong last_time = 0; - - mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT; - kr = task_info(task, - TASK_THREAD_TIMES_INFO, - (task_info_t)&thread_info_data, - &thread_info_count); - if (kr != KERN_SUCCESS) { - // Most likely cause: |task| is a zombie. - return -1; - } - - mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT; - kr = task_info(task, - TASK_BASIC_INFO_64, - (task_info_t)&task_info_data, - &count); - if (kr != KERN_SUCCESS) { - // Most likely cause: |task| is a zombie. - return -1; - } - - /* Set total_time. */ - // thread info contains live time... - TIME_VALUE_TO_TIMEVAL(&thread_info_data.user_time, &user_timeval); - TIME_VALUE_TO_TIMEVAL(&thread_info_data.system_time, &system_timeval); - timeradd(&user_timeval, &system_timeval, &task_timeval); - - // ... task info contains terminated time. - TIME_VALUE_TO_TIMEVAL(&task_info_data.user_time, &user_timeval); - TIME_VALUE_TO_TIMEVAL(&task_info_data.system_time, &system_timeval); - timeradd(&user_timeval, &task_timeval, &task_timeval); - timeradd(&system_timeval, &task_timeval, &task_timeval); - - if (gettimeofday(&now, NULL) < 0) { - return -1; - } - jint ncpus = JVM_ActiveProcessorCount(); - jlong time = TIME_VALUE_TO_MICROSECONDS(now) * ncpus; - jlong task_time = TIME_VALUE_TO_MICROSECONDS(task_timeval); - - if ((last_task_time == 0) || (last_time == 0)) { - // First call, just set the last values. - last_task_time = task_time; - last_time = time; - // return 0 since we have no data, not -1 which indicates error - return 0; - } - - jlong task_time_delta = task_time - last_task_time; - jlong time_delta = time - last_time; - if (time_delta == 0) { - return -1; - } - - jdouble cpu = (jdouble) task_time_delta / time_delta; - - last_task_time = task_time; - last_time = time; - - return cpu; - }
--- a/jdk/src/java.management/unix/native/libmanagement/OperatingSystemImpl.c Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,479 +0,0 @@ -/* - * Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "jni.h" -#include "jni_util.h" -#include "jlong.h" -#include "jvm.h" -#include "management.h" -#include "sun_management_OperatingSystemImpl.h" - -#include <sys/types.h> -#include <sys/stat.h> -#if defined(_ALLBSD_SOURCE) -#include <sys/sysctl.h> -#ifdef __APPLE__ -#include <sys/param.h> -#include <sys/mount.h> -#include <mach/mach.h> -#include <sys/proc_info.h> -#include <libproc.h> -#endif -#elif !defined(_AIX) -#include <sys/swap.h> -#endif -#include <sys/resource.h> -#include <sys/times.h> -#ifndef _ALLBSD_SOURCE -#include <sys/sysinfo.h> -#endif -#include <ctype.h> -#include <dirent.h> -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <stdlib.h> -#include <unistd.h> - -#if defined(_AIX) -#include <libperfstat.h> -#endif - -static jlong page_size = 0; - -#if defined(_ALLBSD_SOURCE) || defined(_AIX) -#define MB (1024UL * 1024UL) -#else - -/* This gets us the new structured proc interfaces of 5.6 & later */ -/* - see comment in <sys/procfs.h> */ -#define _STRUCTURED_PROC 1 -#include <sys/procfs.h> - -#endif /* _ALLBSD_SOURCE */ - -static struct dirent* read_dir(DIR* dirp, struct dirent* entry) { -#ifdef __solaris__ - struct dirent* dbuf = readdir(dirp); - return dbuf; -#else /* __linux__ || _ALLBSD_SOURCE */ - struct dirent* p; - if (readdir_r(dirp, entry, &p) == 0) { - return p; - } else { - return NULL; - } -#endif -} - -// true = get available swap in bytes -// false = get total swap in bytes -static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean available) { -#ifdef __solaris__ - long total, avail; - int nswap, i, count; - swaptbl_t *stbl; - char *strtab; - - // First get the number of swap resource entries - if ((nswap = swapctl(SC_GETNSWP, NULL)) == -1) { - throw_internal_error(env, "swapctl failed to get nswap"); - return -1; - } - if (nswap == 0) { - return 0; - } - - // Allocate storage for resource entries - stbl = (swaptbl_t*) malloc(nswap * sizeof(swapent_t) + - sizeof(struct swaptable)); - if (stbl == NULL) { - JNU_ThrowOutOfMemoryError(env, 0); - return -1; - } - - // Allocate storage for the table - strtab = (char*) malloc((nswap + 1) * MAXPATHLEN); - if (strtab == NULL) { - free(stbl); - JNU_ThrowOutOfMemoryError(env, 0); - return -1; - } - - for (i = 0; i < (nswap + 1); i++) { - stbl->swt_ent[i].ste_path = strtab + (i * MAXPATHLEN); - } - stbl->swt_n = nswap + 1; - - // Get the entries - if ((count = swapctl(SC_LIST, stbl)) < 0) { - free(stbl); - free(strtab); - throw_internal_error(env, "swapctl failed to get swap list"); - return -1; - } - - // Sum the entries to get total and free swap - total = 0; - avail = 0; - for (i = 0; i < count; i++) { - total += stbl->swt_ent[i].ste_pages; - avail += stbl->swt_ent[i].ste_free; - } - - free(stbl); - free(strtab); - return available ? ((jlong)avail * page_size) : - ((jlong)total * page_size); -#elif defined(__linux__) - int ret; - FILE *fp; - jlong total = 0, avail = 0; - - struct sysinfo si; - ret = sysinfo(&si); - if (ret != 0) { - throw_internal_error(env, "sysinfo failed to get swap size"); - } - total = (jlong)si.totalswap * si.mem_unit; - avail = (jlong)si.freeswap * si.mem_unit; - - return available ? avail : total; -#elif defined(__APPLE__) - struct xsw_usage vmusage; - size_t size = sizeof(vmusage); - if (sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0) != 0) { - throw_internal_error(env, "sysctlbyname failed"); - } - return available ? (jlong)vmusage.xsu_avail : (jlong)vmusage.xsu_total; -#else /* _ALLBSD_SOURCE */ - /* - * XXXBSD: there's no way available to get swap info in - * FreeBSD. Usage of libkvm is not an option here - */ - // throw_internal_error(env, "Unimplemented in FreeBSD"); - return (0); -#endif -} - -JNIEXPORT void JNICALL -Java_sun_management_OperatingSystemImpl_initialize0 - (JNIEnv *env, jclass cls) -{ - page_size = sysconf(_SC_PAGESIZE); -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getCommittedVirtualMemorySize0 - (JNIEnv *env, jobject mbean) -{ -#ifdef __solaris__ - psinfo_t psinfo; - ssize_t result; - size_t remaining; - char* addr; - int fd; - - fd = open64("/proc/self/psinfo", O_RDONLY, 0); - if (fd < 0) { - throw_internal_error(env, "Unable to open /proc/self/psinfo"); - return -1; - } - - addr = (char *)&psinfo; - for (remaining = sizeof(psinfo_t); remaining > 0;) { - result = read(fd, addr, remaining); - if (result < 0) { - if (errno != EINTR) { - close(fd); - throw_internal_error(env, "Unable to read /proc/self/psinfo"); - return -1; - } - } else { - remaining -= result; - addr += result; - } - } - - close(fd); - return (jlong) psinfo.pr_size * 1024; -#elif defined(__linux__) - FILE *fp; - unsigned long vsize = 0; - - if ((fp = fopen("/proc/self/stat", "r")) == NULL) { - throw_internal_error(env, "Unable to open /proc/self/stat"); - return -1; - } - - // Ignore everything except the vsize entry - if (fscanf(fp, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %*u %*u %*d %lu %*[^\n]\n", &vsize) == EOF) { - throw_internal_error(env, "Unable to get virtual memory usage"); - fclose(fp); - return -1; - } - - fclose(fp); - return (jlong)vsize; -#elif defined(__APPLE__) - struct task_basic_info t_info; - mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; - - kern_return_t res = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count); - if (res != KERN_SUCCESS) { - throw_internal_error(env, "task_info failed"); - } - return t_info.virtual_size; -#else /* _ALLBSD_SOURCE */ - /* - * XXXBSD: there's no way available to do it in FreeBSD, AFAIK. - */ - // throw_internal_error(env, "Unimplemented in FreeBSD"); - return (64 * MB); -#endif -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getTotalSwapSpaceSize0 - (JNIEnv *env, jobject mbean) -{ - return get_total_or_available_swap_space_size(env, JNI_FALSE); -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getFreeSwapSpaceSize0 - (JNIEnv *env, jobject mbean) -{ - return get_total_or_available_swap_space_size(env, JNI_TRUE); -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getProcessCpuTime0 - (JNIEnv *env, jobject mbean) -{ -#ifdef __APPLE__ - struct rusage usage; - if (getrusage(RUSAGE_SELF, &usage) != 0) { - throw_internal_error(env, "getrusage failed"); - return -1; - } - jlong microsecs = - usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec + - usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec; - return microsecs * 1000; -#else - jlong clk_tck, ns_per_clock_tick; - jlong cpu_time_ns; - struct tms time; - - /* - * BSDNOTE: FreeBSD implements _SC_CLK_TCK since FreeBSD 5, so - * add a magic to handle it - */ -#if defined(__solaris__) || defined(_SC_CLK_TCK) - clk_tck = (jlong) sysconf(_SC_CLK_TCK); -#elif defined(__linux__) || defined(_ALLBSD_SOURCE) - clk_tck = 100; -#endif - if (clk_tck == -1) { - throw_internal_error(env, - "sysconf failed - not able to get clock tick"); - return -1; - } - - times(&time); - ns_per_clock_tick = (jlong) 1000 * 1000 * 1000 / (jlong) clk_tck; - cpu_time_ns = ((jlong)time.tms_utime + (jlong) time.tms_stime) * - ns_per_clock_tick; - return cpu_time_ns; -#endif -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getFreePhysicalMemorySize0 - (JNIEnv *env, jobject mbean) -{ -#ifdef __APPLE__ - mach_msg_type_number_t count; - vm_statistics_data_t vm_stats; - kern_return_t res; - - count = HOST_VM_INFO_COUNT; - res = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count); - if (res != KERN_SUCCESS) { - throw_internal_error(env, "host_statistics failed"); - return -1; - } - return (jlong)vm_stats.free_count * page_size; -#elif defined(_ALLBSD_SOURCE) - /* - * XXBSDL no way to do it in FreeBSD - */ - // throw_internal_error(env, "unimplemented in FreeBSD") - return (128 * MB); -#elif defined(_AIX) - perfstat_memory_total_t memory_info; - if (-1 != perfstat_memory_total(NULL, &memory_info, sizeof(perfstat_memory_total_t), 1)) { - return (jlong)(memory_info.real_free * 4L * 1024L); - } - return -1; -#else // solaris / linux - jlong num_avail_physical_pages = sysconf(_SC_AVPHYS_PAGES); - return (num_avail_physical_pages * page_size); -#endif -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getTotalPhysicalMemorySize0 - (JNIEnv *env, jobject mbean) -{ -#ifdef _ALLBSD_SOURCE - jlong result = 0; - int mib[2]; - size_t rlen; - - mib[0] = CTL_HW; - mib[1] = HW_MEMSIZE; - rlen = sizeof(result); - if (sysctl(mib, 2, &result, &rlen, NULL, 0) != 0) { - throw_internal_error(env, "sysctl failed"); - return -1; - } - return result; -#elif defined(_AIX) - perfstat_memory_total_t memory_info; - if (-1 != perfstat_memory_total(NULL, &memory_info, sizeof(perfstat_memory_total_t), 1)) { - return (jlong)(memory_info.real_total * 4L * 1024L); - } - return -1; -#else // solaris / linux - jlong num_physical_pages = sysconf(_SC_PHYS_PAGES); - return (num_physical_pages * page_size); -#endif -} - - - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getOpenFileDescriptorCount0 - (JNIEnv *env, jobject mbean) -{ -#ifdef __APPLE__ - // This code is influenced by the darwin lsof source - pid_t my_pid; - struct proc_bsdinfo bsdinfo; - struct proc_fdinfo *fds; - int nfiles; - kern_return_t kres; - int res; - size_t fds_size; - - kres = pid_for_task(mach_task_self(), &my_pid); - if (kres != KERN_SUCCESS) { - throw_internal_error(env, "pid_for_task failed"); - return -1; - } - - // get the maximum number of file descriptors - res = proc_pidinfo(my_pid, PROC_PIDTBSDINFO, 0, &bsdinfo, PROC_PIDTBSDINFO_SIZE); - if (res <= 0) { - throw_internal_error(env, "proc_pidinfo with PROC_PIDTBSDINFO failed"); - return -1; - } - - // allocate memory to hold the fd information (we don't acutally use this information - // but need it to get the number of open files) - fds_size = bsdinfo.pbi_nfiles * sizeof(struct proc_fdinfo); - fds = malloc(fds_size); - if (fds == NULL) { - JNU_ThrowOutOfMemoryError(env, "could not allocate space for file descriptors"); - return -1; - } - - // get the list of open files - the return value is the number of bytes - // proc_pidinfo filled in - res = proc_pidinfo(my_pid, PROC_PIDLISTFDS, 0, fds, fds_size); - if (res <= 0) { - free(fds); - throw_internal_error(env, "proc_pidinfo failed for PROC_PIDLISTFDS"); - return -1; - } - nfiles = res / sizeof(struct proc_fdinfo); - free(fds); - - return nfiles; -#elif defined(_ALLBSD_SOURCE) - /* - * XXXBSD: there's no way available to do it in FreeBSD, AFAIK. - */ - // throw_internal_error(env, "Unimplemented in FreeBSD"); - return (100); -#else /* solaris/linux */ - DIR *dirp; - struct dirent dbuf; - struct dirent* dentp; - jlong fds = 0; - -#if defined(_AIX) -/* AIX does not understand '/proc/self' - it requires the real process ID */ -#define FD_DIR aix_fd_dir - char aix_fd_dir[32]; /* the pid has at most 19 digits */ - snprintf(aix_fd_dir, 32, "/proc/%d/fd", getpid()); -#else -#define FD_DIR "/proc/self/fd" -#endif - - dirp = opendir(FD_DIR); - if (dirp == NULL) { - throw_internal_error(env, "Unable to open directory /proc/self/fd"); - return -1; - } - - // iterate through directory entries, skipping '.' and '..' - // each entry represents an open file descriptor. - while ((dentp = read_dir(dirp, &dbuf)) != NULL) { - if (isdigit(dentp->d_name[0])) { - fds++; - } - } - - closedir(dirp); - // subtract by 1 which was the fd open for this implementation - return (fds - 1); -#endif -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getMaxFileDescriptorCount0 - (JNIEnv *env, jobject mbean) -{ - struct rlimit rlp; - - if (getrlimit(RLIMIT_NOFILE, &rlp) == -1) { - throw_internal_error(env, "getrlimit failed"); - return -1; - } - return (jlong) rlp.rlim_cur; -}
--- a/jdk/src/java.management/unix/native/libmanagement/SolarisOperatingSystem.c Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,241 +0,0 @@ -/* - * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include <fcntl.h> -#include <kstat.h> -#include <procfs.h> -#include <unistd.h> -#include <stdlib.h> -#include <stdio.h> -#include <string.h> -#include <sys/sysinfo.h> -#include <sys/lwp.h> -#include <pthread.h> -#include <utmpx.h> -#include <dlfcn.h> -#include <sys/loadavg.h> -#include <jni.h> -#include "jvm.h" -#include "sun_management_OperatingSystemImpl.h" - -typedef struct { - kstat_t *kstat; - uint64_t last_idle; - uint64_t last_total; - double last_ratio; -} cpuload_t; - -static cpuload_t *cpu_loads = NULL; -static unsigned int num_cpus; -static kstat_ctl_t *kstat_ctrl = NULL; - -static void map_cpu_kstat_counters() { - kstat_t *kstat; - int i; - - // Get number of CPU(s) - if ((num_cpus = sysconf(_SC_NPROCESSORS_ONLN)) == -1) { - num_cpus = 1; - } - - // Data structure for saving CPU load - if ((cpu_loads = calloc(num_cpus,sizeof(cpuload_t))) == NULL) { - return; - } - - // Get kstat cpu_stat counters for every CPU - // (loop over kstat to find our cpu_stat(s) - i = 0; - for (kstat = kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) { - if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) { - - if (kstat_read(kstat_ctrl, kstat, NULL) == -1) { - // Failed to initialize kstat for this CPU so ignore it - continue; - } - - if (i == num_cpus) { - // Found more cpu_stats than reported CPUs - break; - } - - cpu_loads[i++].kstat = kstat; - } - } -} - -static int init_cpu_kstat_counters() { - static int initialized = 0; - - // Concurrence in this method is prevented by the lock in - // the calling method get_cpu_load(); - if(!initialized) { - if ((kstat_ctrl = kstat_open()) != NULL) { - map_cpu_kstat_counters(); - initialized = 1; - } - } - return initialized ? 0 : -1; -} - -static void update_cpu_kstat_counters() { - if(kstat_chain_update(kstat_ctrl) != 0) { - free(cpu_loads); - map_cpu_kstat_counters(); - } -} - -int read_cpustat(cpuload_t *load, cpu_stat_t *cpu_stat) { - if (load->kstat == NULL) { - // no handle. - return -1; - } - if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == -1) { - // disabling for now, a kstat chain update is likely to happen next time - load->kstat = NULL; - return -1; - } - return 0; -} - -double get_single_cpu_load(unsigned int n) { - cpuload_t *load; - cpu_stat_t cpu_stat; - uint_t *usage; - uint64_t c_idle; - uint64_t c_total; - uint64_t d_idle; - uint64_t d_total; - int i; - - if (n >= num_cpus) { - return -1.0; - } - - load = &cpu_loads[n]; - if (read_cpustat(load, &cpu_stat) < 0) { - return -1.0; - } - - usage = cpu_stat.cpu_sysinfo.cpu; - c_idle = usage[CPU_IDLE]; - - for (c_total = 0, i = 0; i < CPU_STATES; i++) { - c_total += usage[i]; - } - - // Calculate diff against previous snapshot - d_idle = c_idle - load->last_idle; - d_total = c_total - load->last_total; - - /** update if weve moved */ - if (d_total > 0) { - // Save current values for next time around - load->last_idle = c_idle; - load->last_total = c_total; - load->last_ratio = (double) (d_total - d_idle) / d_total; - } - - return load->last_ratio; -} - -int get_info(const char *path, void *info, size_t s, off_t o) { - int fd; - int ret = 0; - if ((fd = open(path, O_RDONLY)) < 0) { - return -1; - } - if (pread(fd, info, s, o) != s) { - ret = -1; - } - close(fd); - return ret; -} - -#define MIN(a, b) ((a < b) ? a : b) - -static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; - -/** - * Return the cpu load (0-1) for proc number 'which' (or average all if which == -1) - */ -double get_cpu_load(int which) { - double load =.0; - - pthread_mutex_lock(&lock); - if(init_cpu_kstat_counters()==0) { - - update_cpu_kstat_counters(); - - if (which == -1) { - unsigned int i; - double t; - - for (t = .0, i = 0; i < num_cpus; i++) { - t += get_single_cpu_load(i); - } - - // Cap total systemload to 1.0 - load = MIN((t / num_cpus), 1.0); - } else { - load = MIN(get_single_cpu_load(which), 1.0); - } - } else { - load = -1.0; - } - pthread_mutex_unlock(&lock); - - return load; -} - -/** - * Return the cpu load (0-1) for the current process (i.e the JVM) - * or -1.0 if the get_info() call failed - */ -double get_process_load(void) { - psinfo_t info; - - // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s - // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000. - if (get_info("/proc/self/psinfo",&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) == 0) { - return (double) info.pr_pctcpu / 0x8000; - } - return -1.0; -} - -JNIEXPORT jdouble JNICALL -Java_sun_management_OperatingSystemImpl_getSystemCpuLoad0 -(JNIEnv *env, jobject dummy) -{ - return get_cpu_load(-1); -} - -JNIEXPORT jdouble JNICALL -Java_sun_management_OperatingSystemImpl_getProcessCpuLoad0 -(JNIEnv *env, jobject dummy) -{ - return get_process_load(); -} -
--- a/jdk/src/java.management/windows/classes/sun/management/OperatingSystemImpl.java Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,97 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -package sun.management; - -import com.sun.management.OperatingSystemMXBean; - -/** - * Implementation class for the operating system. - * Standard and committed hotspot-specific metrics if any. - * - * ManagementFactory.getOperatingSystemMXBean() returns an instance - * of this class. - */ -class OperatingSystemImpl extends BaseOperatingSystemImpl - implements OperatingSystemMXBean { - - // psapiLock is a lock to make sure only one thread loading - // PSAPI DLL. - private static Object psapiLock = new Object(); - - OperatingSystemImpl(VMManagement vm) { - super(vm); - } - - public long getCommittedVirtualMemorySize() { - synchronized (psapiLock) { - return getCommittedVirtualMemorySize0(); - } - } - - public long getTotalSwapSpaceSize() { - return getTotalSwapSpaceSize0(); - } - - public long getFreeSwapSpaceSize() { - return getFreeSwapSpaceSize0(); - } - - public long getProcessCpuTime() { - return getProcessCpuTime0(); - } - - public long getFreePhysicalMemorySize() { - return getFreePhysicalMemorySize0(); - } - - public long getTotalPhysicalMemorySize() { - return getTotalPhysicalMemorySize0(); - } - - public double getSystemCpuLoad() { - return getSystemCpuLoad0(); - } - - public double getProcessCpuLoad() { - return getProcessCpuLoad0(); - } - - /* native methods */ - private native long getCommittedVirtualMemorySize0(); - private native long getFreePhysicalMemorySize0(); - private native long getFreeSwapSpaceSize0(); - private native double getProcessCpuLoad0(); - private native long getProcessCpuTime0(); - private native double getSystemCpuLoad0(); - private native long getTotalPhysicalMemorySize0(); - private native long getTotalSwapSpaceSize0(); - - static { - initialize0(); - } - - private static native void initialize0(); -}
--- a/jdk/src/java.management/windows/native/libmanagement/OperatingSystemImpl.c Wed Apr 15 13:27:39 2015 +0200 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1363 +0,0 @@ -/* - * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. - * - * This code is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License version 2 only, as - * published by the Free Software Foundation. Oracle designates this - * particular file as subject to the "Classpath" exception as provided - * by Oracle in the LICENSE file that accompanied this code. - * - * This code is distributed in the hope that it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License - * version 2 for more details (a copy is included in the LICENSE file that - * accompanied this code). - * - * You should have received a copy of the GNU General Public License version - * 2 along with this work; if not, write to the Free Software Foundation, - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA - * or visit www.oracle.com if you need additional information or have any - * questions. - */ - -#include "jni.h" -#include "jni_util.h" -#include "jlong.h" -#include "jvm.h" -#include "management.h" -#include "sun_management_OperatingSystemImpl.h" - -#include <psapi.h> -#include <errno.h> -#include <stdlib.h> - -#include <malloc.h> -#pragma warning (push,0) -#include <windows.h> -#pragma warning (pop) -#include <stdio.h> -#include <time.h> -#include <stdint.h> -#include <assert.h> - -/* Disable warnings due to broken header files from Microsoft... */ -#pragma warning(push, 3) -#include <pdh.h> -#include <pdhmsg.h> -#include <process.h> -#pragma warning(pop) - -typedef unsigned __int32 juint; -typedef unsigned __int64 julong; - -static void set_low(jlong* value, jint low) { - *value &= (jlong)0xffffffff << 32; - *value |= (jlong)(julong)(juint)low; -} - -static void set_high(jlong* value, jint high) { - *value &= (jlong)(julong)(juint)0xffffffff; - *value |= (jlong)high << 32; -} - -static jlong jlong_from(jint h, jint l) { - jlong result = 0; // initialization to avoid warning - set_high(&result, h); - set_low(&result, l); - return result; -} - -static HANDLE main_process; - -static void perfInit(void); - -JNIEXPORT void JNICALL -Java_sun_management_OperatingSystemImpl_initialize0 - (JNIEnv *env, jclass cls) -{ - main_process = GetCurrentProcess(); - perfInit(); -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getCommittedVirtualMemorySize0 - (JNIEnv *env, jobject mbean) -{ - PROCESS_MEMORY_COUNTERS pmc; - if (GetProcessMemoryInfo(main_process, &pmc, sizeof(PROCESS_MEMORY_COUNTERS)) == 0) { - return (jlong)-1L; - } else { - return (jlong) pmc.PagefileUsage; - } -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getTotalSwapSpaceSize0 - (JNIEnv *env, jobject mbean) -{ - MEMORYSTATUSEX ms; - ms.dwLength = sizeof(ms); - GlobalMemoryStatusEx(&ms); - return (jlong) ms.ullTotalPageFile; -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getFreeSwapSpaceSize0 - (JNIEnv *env, jobject mbean) -{ - MEMORYSTATUSEX ms; - ms.dwLength = sizeof(ms); - GlobalMemoryStatusEx(&ms); - return (jlong) ms.ullAvailPageFile; -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getProcessCpuTime0 - (JNIEnv *env, jobject mbean) -{ - - FILETIME process_creation_time, process_exit_time, - process_user_time, process_kernel_time; - - // Using static variables declared above - // Units are 100-ns intervals. Convert to ns. - GetProcessTimes(main_process, &process_creation_time, - &process_exit_time, - &process_kernel_time, &process_user_time); - return (jlong_from(process_user_time.dwHighDateTime, - process_user_time.dwLowDateTime) + - jlong_from(process_kernel_time.dwHighDateTime, - process_kernel_time.dwLowDateTime)) * 100; -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getFreePhysicalMemorySize0 - (JNIEnv *env, jobject mbean) -{ - MEMORYSTATUSEX ms; - ms.dwLength = sizeof(ms); - GlobalMemoryStatusEx(&ms); - return (jlong) ms.ullAvailPhys; -} - -JNIEXPORT jlong JNICALL -Java_sun_management_OperatingSystemImpl_getTotalPhysicalMemorySize0 - (JNIEnv *env, jobject mbean) -{ - MEMORYSTATUSEX ms; - ms.dwLength = sizeof(ms); - GlobalMemoryStatusEx(&ms); - return (jlong) ms.ullTotalPhys; -} - -/* Performance Data Helper API (PDH) support */ - -typedef PDH_STATUS (WINAPI *PdhAddCounterFunc)( - HQUERY hQuery, - LPCSTR szFullCounterPath, - DWORD dwUserData, - HCOUNTER *phCounter - ); -typedef PDH_STATUS (WINAPI *PdhOpenQueryFunc)( - LPCWSTR szDataSource, - DWORD dwUserData, - HQUERY *phQuery - ); -typedef PDH_STATUS (WINAPI *PdhCollectQueryDataFunc)( - HQUERY hQuery - ); - -typedef PDH_STATUS (WINAPI *PdhEnumObjectItemsFunc)( - LPCTSTR szDataSource, - LPCTSTR szMachineName, - LPCTSTR szObjectName, - LPTSTR mszCounterList, - LPDWORD pcchCounterListLength, - LPTSTR mszInstanceList, - LPDWORD pcchInstanceListLength, - DWORD dwDetailLevel, - DWORD dwFlags - ); -typedef PDH_STATUS (WINAPI *PdhRemoveCounterFunc)( - HCOUNTER hCounter - ); -typedef PDH_STATUS (WINAPI *PdhLookupPerfNameByIndexFunc)( - LPCSTR szMachineName, - DWORD dwNameIndex, - LPSTR szNameBuffer, - LPDWORD pcchNameBufferSize - ); -typedef DWORD (WINAPI *PdhCloseQueryFunc)( - HQUERY hQuery - ); - -typedef DWORD (WINAPI *PdhGetFormattedCounterValueFunc)( - HCOUNTER hCounter, - DWORD dwFormat, - LPDWORD lpdwType, - PPDH_FMT_COUNTERVALUE pValue - ); - -static PdhAddCounterFunc PdhAddCounter_i; -static PdhOpenQueryFunc PdhOpenQuery_i; -static PdhCloseQueryFunc PdhCloseQuery_i; -static PdhCollectQueryDataFunc PdhCollectQueryData_i; -static PdhGetFormattedCounterValueFunc PdhGetFormattedCounterValue_i; -static PdhEnumObjectItemsFunc PdhEnumObjectItems_i; -static PdhRemoveCounterFunc PdhRemoveCounter_i; -static PdhLookupPerfNameByIndexFunc PdhLookupPerfNameByIndex_i; - -/* - * Struct for PDH queries. - */ -typedef struct { - HQUERY query; - uint64_t lastUpdate; // Last time query was updated (ticks) -} UpdateQueryS, *UpdateQueryP; - -// Min time between query updates (ticks) -static const int MIN_UPDATE_INTERVAL = 500; - -/* - * Struct for a PDH query with multiple counters. - */ -typedef struct { - UpdateQueryS query; - HCOUNTER* counters; - int noOfCounters; -} MultipleCounterQueryS, *MultipleCounterQueryP; - -/* - * Struct for a PDH query with a single counter. - */ -typedef struct { - UpdateQueryS query; - HCOUNTER counter; -} SingleCounterQueryS, *SingleCounterQueryP; - - -typedef struct { - CRITICAL_SECTION cs; - DWORD owningThread; - DWORD recursionCount; -} PdhCriticalSectionS, *PdhCriticalSectionP; - -static PdhCriticalSectionS initializationLock; - -static void InitializePdhCriticalSection(PdhCriticalSectionP criticalSection) { - assert(criticalSection); - - InitializeCriticalSection(&criticalSection->cs); - criticalSection->owningThread = 0; - criticalSection->recursionCount = 0; -} - -static void EnterPdhCriticalSection(PdhCriticalSectionP criticalSection) { - assert(criticalSection); - - EnterCriticalSection(&criticalSection->cs); - criticalSection->recursionCount++; - if (!criticalSection->owningThread) { - criticalSection->owningThread = GetCurrentThreadId(); - } -} - -static void LeavePdhCriticalSection(PdhCriticalSectionP criticalSection) { - assert(criticalSection); - assert(GetCurrentThreadId() == criticalSection->owningThread); - assert(criticalSection->recursionCount >= 1); - - criticalSection->recursionCount--; - if (!criticalSection->recursionCount) { - criticalSection->owningThread = 0; - } - LeaveCriticalSection(&criticalSection->cs); -} - -/* - * INFO: Using PDH APIs Correctly in a Localized Language (Q287159) - * http://support.microsoft.com/default.aspx?scid=kb;EN-US;q287159 - * The index value for the base system counters and objects like processor, - * process, thread, memory, and so forth are always the same irrespective - * of the localized version of the operating system or service pack installed. - * To find the correct index for an object or counter, inspect the registry key/value: - * [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009\Counter] - */ -static const DWORD PDH_PROCESSOR_IDX = 238; -static const DWORD PDH_PROCESSOR_TIME_IDX = 6; -static const DWORD PDH_PROCESS_IDX = 230; -static const DWORD PDH_ID_PROCESS_IDX = 784; - -/* useful pdh fmt's */ -static const char* const OBJECT_COUNTER_FMT = "\\%s\\%s"; -static const size_t OBJECT_COUNTER_FMT_LEN = 2; -static const char* const OBJECT_WITH_INSTANCES_COUNTER_FMT = "\\%s(%s)\\%s"; -static const size_t OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN = 4; -static const char* const PROCESS_OBJECT_INSTANCE_COUNTER_FMT = "\\%s(%s#%s)\\%s"; -static const size_t PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN = 5; - -static const char* pdhProcessImageName = NULL; /* "java" */ -static char* pdhIDProcessCounterFmt = NULL; /* "\Process(java#%d)\ID Process" */ - -static int numberOfJavaProcessesAtInitialization = 0; - -/* - * Currently used CPU queries/counters and variables - */ -static SingleCounterQueryP processTotalCPULoad = NULL; -static MultipleCounterQueryP multiCounterCPULoad = NULL; -static double cpuFactor = .0; -static DWORD numCpus = 0; - -/* - * Seems WinXP PDH returns PDH_MORE_DATA whenever we send in a NULL buffer. - * Let's just ignore it, since we make sure we have enough buffer anyway. - */ -static int -pdhFail(PDH_STATUS pdhStat) { - return pdhStat != ERROR_SUCCESS && pdhStat != PDH_MORE_DATA; -} - -static const char* -allocateAndCopy(const char* const originalString) { - size_t len; - char* allocatedString; - - assert(originalString); - - len = strlen(originalString); - - allocatedString = malloc(len + 1); - - if (!allocatedString) { - return NULL; - } - - strncpy(allocatedString, originalString, len); - allocatedString[len] = '\0'; - - return allocatedString; -} - -/* - * Allocates memory into the supplied pointer and - * fills it with the localized PDH artifact description, if indexed correctly. - * Caller owns the memory from the point of returning from this function. - * - * @param index the PDH counter index as specified in the registry - * @param ppBuffer pointer to a char*. - * @return 0 if successful, negative on failure. - */ -static int -lookupNameByIndex(DWORD index, char** ppBuffer) { - DWORD size; - - assert(ppBuffer); - - /* determine size needed */ - if (PdhLookupPerfNameByIndex_i(NULL, index, NULL, &size) != PDH_MORE_DATA) { - /* invalid index? */ - return -1; - } - - *ppBuffer = malloc((size_t)size); - - if (!*ppBuffer) { - return -1; - } - - if (PdhLookupPerfNameByIndex_i(NULL, index, *ppBuffer, &size) != ERROR_SUCCESS) { - free(*ppBuffer); - *ppBuffer = NULL; - return -1; - } - - /* windows vista does not null-terminate the string - * (although the docs says it will) */ - (*ppBuffer)[size - 1] = '\0'; - - return 0; -} - -/* -* Construct a fully qualified PDH path -* -* @param objectName a PDH Object string representation (required) -* @param counterName a PDH Counter string representation (required) -* @param imageName a process image name string, ex. "java" (opt) -* @param instance an instance string, ex. "0", "1", ... (opt) -* @return the fully qualified PDH path. -* -* Caller will own the returned malloc:ed string -*/ -static const char* -makeFullCounterPath(const char* const objectName, - const char* const counterName, - const char* const imageName, - const char* const instance) { - - size_t fullCounterPathLen; - char* fullCounterPath; - - assert(objectName); - assert(counterName); - - fullCounterPathLen = strlen(objectName); - fullCounterPathLen += strlen(counterName); - - if (imageName) { - /* - * For paths using the "Process" Object. - * - * Examples: - * abstract: "\Process(imageName#instance)\Counter" - * actual: "\Process(java#2)\ID Process" - */ - fullCounterPathLen += PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN; - fullCounterPathLen += strlen(imageName); - - /* - * imageName must be passed together with an associated - * instance "number" ("0", "1", "2", ...). - * This is required in order to create valid "Process" Object paths. - * - * Examples: "\Process(java#0)", \Process(java#1"), ... - */ - assert(instance); - - fullCounterPathLen += strlen(instance); - - fullCounterPath = malloc(fullCounterPathLen + 1); - - if (!fullCounterPath) { - return NULL; - } - - _snprintf(fullCounterPath, - fullCounterPathLen, - PROCESS_OBJECT_INSTANCE_COUNTER_FMT, - objectName, - imageName, - instance, - counterName); - } else { - if (instance) { - /* - * For paths where the Object has multiple instances. - * - * Examples: - * abstract: "\Object(instance)\Counter" - * actual: "\Processor(0)\% Privileged Time" - */ - fullCounterPathLen += strlen(instance); - fullCounterPathLen += OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN; - } else { - /* - * For "normal" paths. - * - * Examples: - * abstract: "\Object\Counter" - * actual: "\Memory\Available Mbytes" - */ - fullCounterPathLen += OBJECT_COUNTER_FMT_LEN; - } - - fullCounterPath = malloc(fullCounterPathLen + 1); - - if (!fullCounterPath) { - return NULL; - } - - if (instance) { - _snprintf(fullCounterPath, - fullCounterPathLen, - OBJECT_WITH_INSTANCES_COUNTER_FMT, - objectName, - instance, - counterName); - } else { - _snprintf(fullCounterPath, - fullCounterPathLen, - OBJECT_COUNTER_FMT, - objectName, - counterName); - } - } - - fullCounterPath[fullCounterPathLen] = '\0'; - - return fullCounterPath; -} - -/* - * Resolves an index for a PDH artifact to - * a localized, malloc:ed string representation. - * Caller will own the returned malloc:ed string. - * - * @param pdhArtifactIndex PDH index - * @return malloc:ed string representation - * of the requested pdh artifact (localized). - * NULL on failure. - */ -static const char* -getPdhLocalizedArtifact(DWORD pdhArtifactIndex) { - char* pdhLocalizedArtifactString; - - if (lookupNameByIndex(pdhArtifactIndex, - &pdhLocalizedArtifactString) != 0) { - return NULL; - } - - return pdhLocalizedArtifactString; -} - -static void -pdhCleanup(HQUERY* const query, HCOUNTER* const counter) { - if (counter && *counter) { - PdhRemoveCounter_i(*counter); - *counter = NULL; - } - if (query && *query) { - PdhCloseQuery_i(*query); - *query = NULL; - } -} - -static void -destroySingleCounter(SingleCounterQueryP counterQuery) { - if (counterQuery) { - pdhCleanup(&counterQuery->query.query, &counterQuery->counter); - } -} - -static void -destroyMultiCounter(MultipleCounterQueryP multiCounterQuery) { - int i; - if (multiCounterQuery) { - if (multiCounterQuery->counters) { - for (i = 0; i < multiCounterQuery->noOfCounters; i++) { - pdhCleanup(NULL, &multiCounterQuery->counters[i]); - } - free(multiCounterQuery->counters); - multiCounterQuery->counters = NULL; - } - pdhCleanup(&multiCounterQuery->query.query, NULL); - } -} - -static int -openQuery(HQUERY* const query) { - assert(query); - - if (PdhOpenQuery_i(NULL, 0, query) != ERROR_SUCCESS) { - return -1; - } - - return 0; -} - -static int -addCounter(HQUERY query, - const char* const fullCounterPath, - HCOUNTER* const counter) { - - assert(fullCounterPath); - assert(counter); - - if (PdhAddCounter_i(query, - fullCounterPath, - 0, - counter) != ERROR_SUCCESS) { - return -1; - } - - return 0; -} - -/* - * Sets up the supplied SingleCounterQuery to listen for the specified counter. - * - * @param counterQuery the counter query to set up. - * @param fullCounterPath the string specifying the full path to the counter. - * @returns 0 if successful, negative on failure. - */ -static int -initializeSingleCounterQuery(SingleCounterQueryP counterQuery, - const char* const fullCounterPath) { - assert(counterQuery); - assert(fullCounterPath); - - if (openQuery(&counterQuery->query.query) == 0) { - if (addCounter(counterQuery->query.query, - fullCounterPath, - &counterQuery->counter) == 0) { - return 0; - } - } - - return -1; -} - -/* - * Sets up a SingleCounterQuery - * - * param counter the counter query to set up. - * param localizedObject string representing the PDH object to query - * param localizedCounter string representing the PDH counter to query - * param processImageName if the counter query needs the process image name ("java") - * param instance if the counter has instances, this is the instance ("\Processor(0)\") - where 0 is the instance - * param firstSampleOnInit for counters that need two queries to yield their values, - the first query can be issued just after initialization - * - * @returns 0 if successful, negative on failure. - */ -static int -initializeSingleCounter(SingleCounterQueryP const counter, - const char* const localizedObject, - const char* const localizedCounter, - const char* const processImageName, - const char* const instance, - BOOL firstSampleOnInit) { - int retValue = -1; - - const char* fullCounterPath = makeFullCounterPath(localizedObject, - localizedCounter, - processImageName, - instance); - - if (fullCounterPath) { - - assert(counter); - - if (initializeSingleCounterQuery(counter, fullCounterPath) == 0) { - /* - * According to the MSDN documentation, rate counters must be read twice: - * - * "Obtaining the value of rate counters such as Page faults/sec requires that - * PdhCollectQueryData be called twice, with a specific time interval between - * the two calls, before calling PdhGetFormattedCounterValue. Call Sleep to - * implement the waiting period between the two calls to PdhCollectQueryData." - * - * Take the first sample here already to allow for the next (first) "real" sample - * to succeed. - */ - if (firstSampleOnInit) { - PdhCollectQueryData_i(counter->query.query); - } - - retValue = 0; - } - free((char*)fullCounterPath); - } - - return retValue; -} - -static void -perfInit(void) { - InitializePdhCriticalSection(&initializationLock); -} - -static int -getProcessID() { - static int myPid = 0; - if (0 == myPid) { - myPid = _getpid(); - } - return myPid; -} - -/* - * Working against the Process object and it's related counters is inherently problematic - * when using the PDH API: - * - * For PDH, a process is not primarily identified by it's process id, - * but with a sequential number, for example \Process(java#0), \Process(java#1), .... - * The really bad part is that this list is reset as soon as one process exits: - * If \Process(java#1) exits, \Process(java#3) now becomes \Process(java#2) etc. - * - * The PDH query api requires a process identifier to be submitted when registering - * a query, but as soon as the list resets, the query is invalidated (since the name - * changed). - * - * Solution: - * The #number identifier for a Process query can only decrease after process creation. - * - * Therefore we create an array of counter queries for all process object instances - * up to and including ourselves: - * - * Ex. we come in as third process instance (java#2), we then create and register - * queries for the following Process object instances: - * java#0, java#1, java#2 - * - * currentQueryIndexForProcess() keeps track of the current "correct" query - * (in order to keep this index valid when the list resets from underneath, - * ensure to call getCurrentQueryIndexForProcess() before every query involving - * Process object instance data). - */ -static int -currentQueryIndexForProcess(void) { - HQUERY tmpQuery = NULL; - HCOUNTER handleCounter = NULL; - int retValue = -1; - - assert(pdhProcessImageName); - assert(pdhIDProcessCounterFmt); - - if (openQuery(&tmpQuery) == 0) { - int index; - - /* iterate over all instance indexes and try to find our own pid */ - for (index = 0; index < INT_MAX; ++index) { - char fullIDProcessCounterPath[MAX_PATH]; - PDH_FMT_COUNTERVALUE counterValue; - PDH_STATUS res; - - _snprintf(fullIDProcessCounterPath, - MAX_PATH, - pdhIDProcessCounterFmt, - index); - - if (addCounter(tmpQuery, fullIDProcessCounterPath, &handleCounter) != 0) { - break; - } - - res = PdhCollectQueryData_i(tmpQuery); - - if (PDH_INVALID_HANDLE == res || PDH_NO_DATA == res) { - break; - } - - PdhGetFormattedCounterValue_i(handleCounter, - PDH_FMT_LONG, - NULL, - &counterValue); - /* - * This check seems to be needed for Win2k SMP boxes, since - * they for some reason don't return PDH_NO_DATA for non existing - * counters. - */ - if (counterValue.CStatus != PDH_CSTATUS_VALID_DATA) { - break; - } - - if ((LONG)getProcessID() == counterValue.longValue) { - retValue = index; - break; - } - } - } - - pdhCleanup(&tmpQuery, &handleCounter); - - return retValue; -} - -/* - * If successful, returns the #index corresponding to our PID - * as resolved by the pdh query: - * "\Process(java#index)\ID Process" (or localized equivalent) - * - * This function should be called before attempting to read - * from any Process related counter(s), and the return value - * is the index to be used for indexing an array of Process object query's: - * - * Example: - * processTotalCPULoad[currentQueryIndex].query - * - * Returns -1 on failure. - */ -static int -getCurrentQueryIndexForProcess() { - int currentQueryIndex = currentQueryIndexForProcess(); - - assert(currentQueryIndex >= 0 && - currentQueryIndex < numberOfJavaProcessesAtInitialization); - - return currentQueryIndex; -} - -/* - * Returns the PDH string identifying the current process image name. - * Use this name as a qualifier when getting counters from the PDH Process Object - * representing your process. - - * Example: - * "\Process(java#0)\Virtual Bytes" - where "java" is the PDH process - * image name. - * - * Please note that the process image name is not necessarily "java", - * hence the use of GetModuleFileName() to detect the process image name. - * - * @return the process image name to be used when retrieving - * PDH counters from the current process. The caller will - own the returned malloc:ed string. NULL if failure. - */ -static const char* -getPdhProcessImageName() { - char moduleName[MAX_PATH]; - char* processImageName; - char* dotPos; - - // Find our module name and use it to extract the image name used by PDH - DWORD getmfnReturn = GetModuleFileName(NULL, moduleName, sizeof(moduleName)); - - if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - return NULL; - } - - if (getmfnReturn >= MAX_PATH || 0 == getmfnReturn) { - return NULL; - } - - processImageName = strrchr(moduleName, '\\'); //drop path - processImageName++; //skip slash - dotPos = strrchr(processImageName, '.'); //drop .exe - dotPos[0] = '\0'; - - return allocateAndCopy(processImageName); -} - -/* - * Sets up the supplied MultipleCounterQuery to check on the processors via PDH CPU counters. - * TODO: Refactor and prettify as with the the SingleCounter queries - * if more MultipleCounterQueries are discovered/needed. - * - * @param multiCounterCPULoad a pointer to a MultipleCounterQueryS, will be filled in with - * the necessary info to check the PDH processor counters. - * @return 0 if successful, negative on failure. - */ -static int -initializeMultipleCounterForCPUs(MultipleCounterQueryP multiCounterCPULoad) { - DWORD cSize = 0; - DWORD iSize = 0; - DWORD pCount; - DWORD index; - char* processor = NULL; //'Processor' == PDH_PROCESSOR_IDX - char* time = NULL; //'Time' == PDH_PROCESSOR_TIME_IDX - char* instances = NULL; - char* tmp; - int retValue = -1; - PDH_STATUS pdhStat; - - if (lookupNameByIndex(PDH_PROCESSOR_IDX, &processor) != 0) { - goto end; - } - - if (lookupNameByIndex(PDH_PROCESSOR_TIME_IDX, &time) != 0) { - goto end; - } - - //ok, now we have enough to enumerate all processors. - pdhStat = PdhEnumObjectItems_i( - NULL, // reserved - NULL, // local machine - processor, // object to enumerate - NULL, // pass in NULL buffers - &cSize, // and 0 length to get - NULL, // required size - &iSize, // of the buffers in chars - PERF_DETAIL_WIZARD, // counter detail level - 0); - - if (pdhFail(pdhStat)) { - goto end; - } - - instances = calloc(iSize, 1); - - if (!instances) { - goto end; - } - - cSize = 0; - - pdhStat = PdhEnumObjectItems_i( - NULL, // reserved - NULL, // local machine - processor, // object to enumerate - NULL, // pass in NULL buffers - &cSize, - instances, // now allocated to be filled in - &iSize, // and size is known - PERF_DETAIL_WIZARD, // counter detail level - 0); - - if (pdhFail(pdhStat)) { - goto end; - } - - // enumerate the Processor instances ("\Processor(0)", "\Processor(1)", ..., "\Processor(_Total)") - for (pCount = 0, tmp = instances; *tmp != '\0'; tmp = &tmp[strlen(tmp)+1], pCount++); - - assert(pCount == numCpus+1); - - //ok, we now have the number of Processor instances - allocate an HCOUNTER for each - multiCounterCPULoad->counters = (HCOUNTER*)malloc(pCount * sizeof(HCOUNTER)); - - if (!multiCounterCPULoad->counters) { - goto end; - } - - multiCounterCPULoad->noOfCounters = pCount; - - if (openQuery(&multiCounterCPULoad->query.query) != 0) { - goto end; - } - - // fetch instance and register its corresponding HCOUNTER with the query - for (index = 0, tmp = instances; *tmp != '\0'; tmp = &tmp[strlen(tmp)+1], ++index) { - const char* const fullCounterPath = makeFullCounterPath(processor, time, NULL, tmp); - - if (!fullCounterPath) { - goto end; - } - - retValue = addCounter(multiCounterCPULoad->query.query, - fullCounterPath, - &multiCounterCPULoad->counters[index]); - - free((char*)fullCounterPath); - - if (retValue != 0) { - goto end; - } - } - - // Query once to initialize the counters which require at least two samples - // (like the % CPU usage) to calculate correctly. - PdhCollectQueryData_i(multiCounterCPULoad->query.query); - - end: - if (processor) { - free(processor); - } - - if (time) { - free(time); - } - - if (instances) { - free(instances); - } - - return retValue; -} - -/* - * Dynamically sets up function pointers to the PDH library. - * - * @param h HMODULE for the PDH library - * @return 0 on success, negative on failure. - */ -static int -bindPdhFunctionPointers(HMODULE h) { - assert(h); - assert(GetCurrentThreadId() == initializationLock.owningThread); - - /* The 'A' at the end means the ANSI (not the UNICODE) vesions of the methods */ - PdhAddCounter_i = (PdhAddCounterFunc)GetProcAddress(h, "PdhAddCounterA"); - PdhOpenQuery_i = (PdhOpenQueryFunc)GetProcAddress(h, "PdhOpenQueryA"); - PdhCloseQuery_i = (PdhCloseQueryFunc)GetProcAddress(h, "PdhCloseQuery"); - PdhCollectQueryData_i = (PdhCollectQueryDataFunc)GetProcAddress(h, "PdhCollectQueryData"); - PdhGetFormattedCounterValue_i = (PdhGetFormattedCounterValueFunc)GetProcAddress(h, "PdhGetFormattedCounterValue"); - PdhEnumObjectItems_i = (PdhEnumObjectItemsFunc)GetProcAddress(h, "PdhEnumObjectItemsA"); - PdhRemoveCounter_i = (PdhRemoveCounterFunc)GetProcAddress(h, "PdhRemoveCounter"); - PdhLookupPerfNameByIndex_i = (PdhLookupPerfNameByIndexFunc)GetProcAddress(h, "PdhLookupPerfNameByIndexA"); - - if (!PdhAddCounter_i || !PdhOpenQuery_i || - !PdhCloseQuery_i || !PdhCollectQueryData_i || - !PdhGetFormattedCounterValue_i || !PdhEnumObjectItems_i || - !PdhRemoveCounter_i || !PdhLookupPerfNameByIndex_i) - { - return -1; - } - return 0; -} - -/* - * Returns the counter value as a double for the specified query. - * Will collect the query data and update the counter values as necessary. - * - * @param query the query to update (if needed). - * @param c the counter to read. - * @param value where to store the formatted value. - * @param format the format to use (i.e. PDH_FMT_DOUBLE, PDH_FMT_LONG etc) - * @return 0 if no error - * -1 if PdhCollectQueryData fails - * -2 if PdhGetFormattedCounterValue fails - */ -static int -getPerformanceData(UpdateQueryP query, HCOUNTER c, PDH_FMT_COUNTERVALUE* value, DWORD format) { - clock_t now = clock(); - - /* - * Need to limit how often we update the query - * to minimize the Heisenberg effect. - * (PDH behaves erratically if the counters are - * queried too often, especially counters that - * store and use values from two consecutive updates, - * like cpu load.) - */ - if (now - query->lastUpdate > MIN_UPDATE_INTERVAL) { - if (PdhCollectQueryData_i(query->query) != ERROR_SUCCESS) { - return -1; - } - query->lastUpdate = now; - } - - if (PdhGetFormattedCounterValue_i(c, format, NULL, value) != ERROR_SUCCESS) { - return -2; - } - - return 0; -} - -static int -allocateAndInitializePdhConstants() { - const char* pdhLocalizedProcessObject = NULL; - const char* pdhLocalizedIDProcessCounter = NULL; - size_t pdhIDProcessCounterFmtLen; - int currentQueryIndex; - int retValue = -1; - - assert(GetCurrentThreadId() == initializationLock.owningThread); - - assert(!pdhProcessImageName); - pdhProcessImageName = getPdhProcessImageName(); - if (!pdhProcessImageName) { - goto end; - } - - pdhLocalizedProcessObject = getPdhLocalizedArtifact(PDH_PROCESS_IDX); - if (!pdhLocalizedProcessObject) { - goto end; - } - - pdhLocalizedIDProcessCounter = getPdhLocalizedArtifact(PDH_ID_PROCESS_IDX); - if (!pdhLocalizedIDProcessCounter) { - goto end; - } - - assert(!pdhIDProcessCounterFmt); - - pdhIDProcessCounterFmtLen = strlen(pdhProcessImageName); - pdhIDProcessCounterFmtLen += strlen(pdhLocalizedProcessObject); - pdhIDProcessCounterFmtLen += strlen(pdhLocalizedIDProcessCounter); - pdhIDProcessCounterFmtLen += PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN; - pdhIDProcessCounterFmtLen += 2; // "%d" - - assert(pdhIDProcessCounterFmtLen < MAX_PATH); - pdhIDProcessCounterFmt = malloc(pdhIDProcessCounterFmtLen + 1); - if (!pdhIDProcessCounterFmt) { - goto end; - } - - /* "\Process(java#%d)\ID Process" */ - _snprintf(pdhIDProcessCounterFmt, - pdhIDProcessCounterFmtLen, - PROCESS_OBJECT_INSTANCE_COUNTER_FMT, - pdhLocalizedProcessObject, - pdhProcessImageName, - "%d", - pdhLocalizedIDProcessCounter); - - pdhIDProcessCounterFmt[pdhIDProcessCounterFmtLen] = '\0'; - - assert(0 == numberOfJavaProcessesAtInitialization); - currentQueryIndex = currentQueryIndexForProcess(); - if (-1 == currentQueryIndex) { - goto end; - } - - numberOfJavaProcessesAtInitialization = currentQueryIndex + 1; - assert(numberOfJavaProcessesAtInitialization >= 1); - - retValue = 0; - - end: - - if (pdhLocalizedProcessObject) { - free((char*)pdhLocalizedProcessObject); - } - - if (pdhLocalizedIDProcessCounter) { - free((char*)pdhLocalizedIDProcessCounter); - } - - return retValue; -} - -static void -deallocatePdhConstants() { - assert(GetCurrentThreadId() == initializationLock.owningThread); - - if (pdhProcessImageName) { - free((char*)pdhProcessImageName); - pdhProcessImageName = NULL; - } - - if (pdhIDProcessCounterFmt) { - free(pdhIDProcessCounterFmt); - pdhIDProcessCounterFmt = NULL; - } - - numberOfJavaProcessesAtInitialization = 0; -} - -static int -initializeCPUCounters() { - SYSTEM_INFO si; - char* localizedProcessObject; - char* localizedProcessorTimeCounter; - int i; - int retValue = -1; - - assert(GetCurrentThreadId() == initializationLock.owningThread); - - assert(0 == numCpus); - GetSystemInfo(&si); - numCpus = si.dwNumberOfProcessors; - assert(numCpus >= 1); - - /* Initialize the denominator for the jvm load calculations */ - assert(.0 == cpuFactor); - cpuFactor = numCpus * 100; - - if (lookupNameByIndex(PDH_PROCESS_IDX, - &localizedProcessObject) == 0) { - - if (lookupNameByIndex(PDH_PROCESSOR_TIME_IDX, - &localizedProcessorTimeCounter) == 0) { - - assert(processTotalCPULoad); - assert(pdhProcessImageName); - - for (i = 0; i < numberOfJavaProcessesAtInitialization; ++i) { - char instanceIndexBuffer[32]; - retValue = initializeSingleCounter(&processTotalCPULoad[i], - localizedProcessObject, - localizedProcessorTimeCounter, - pdhProcessImageName, - itoa(i, instanceIndexBuffer, 10), - TRUE); - if (retValue != 0) { - break; - } - } - free(localizedProcessorTimeCounter); - } - free(localizedProcessObject); - } - - if (retValue != 0) { - return -1; - } - - assert(multiCounterCPULoad); - return initializeMultipleCounterForCPUs(multiCounterCPULoad); -} - -static void -deallocateCPUCounters() { - int i; - - assert(GetCurrentThreadId() == initializationLock.owningThread); - - if (processTotalCPULoad) { - for (i = 0; i < numberOfJavaProcessesAtInitialization; ++i) { - destroySingleCounter(&processTotalCPULoad[i]); - } - free(processTotalCPULoad); - processTotalCPULoad = NULL; - } - - if (multiCounterCPULoad) { - destroyMultiCounter(multiCounterCPULoad); - free(multiCounterCPULoad); - multiCounterCPULoad = NULL; - } - - cpuFactor = .0; - numCpus = 0; -} - -static void -pdhInitErrorHandler(HMODULE h) { - assert(GetCurrentThreadId() == initializationLock.owningThread); - - deallocatePdhConstants(); - - if (h) { - FreeLibrary(h); - } -} - -/* - * Helper to initialize the PDH library, function pointers and constants. - * - * @return 0 if successful, negative on failure. - */ -static int -pdhInit() { - static BOOL initialized = FALSE; - int retValue; - - if (initialized) { - return 0; - } - - retValue = 0; - - EnterPdhCriticalSection(&initializationLock); { - if (!initialized) { - HMODULE h = NULL; - if ((h = LoadLibrary("pdh.dll")) == NULL) { - retValue = -1; - } else if (bindPdhFunctionPointers(h) < 0) { - retValue = -1; - } else if (allocateAndInitializePdhConstants() < 0) { - retValue = -1; - } - - if (0 == retValue) { - initialized = TRUE; - } else { - pdhInitErrorHandler(h); - } - } - } LeavePdhCriticalSection(&initializationLock); - - return retValue; -} - -static int -allocateCPUCounters() { - assert(GetCurrentThreadId() == initializationLock.owningThread); - assert(numberOfJavaProcessesAtInitialization >= 1); - assert(!processTotalCPULoad); - assert(!multiCounterCPULoad); - - /* - * Create an array of Process object queries, for each instance - * up to and including our own (java#0, java#1, java#2, ...). - */ - processTotalCPULoad = calloc(numberOfJavaProcessesAtInitialization, - sizeof(SingleCounterQueryS)); - - if (!processTotalCPULoad) { - return -1; - } - - multiCounterCPULoad = calloc(1, sizeof(MultipleCounterQueryS)); - - if (!multiCounterCPULoad) { - return -1; - } - - return 0; -} - -static int -initializePdhCPUCounters() { - static BOOL initialized = FALSE; - int retValue; - - if (initialized) { - return 0; - } - - retValue = 0; - - EnterPdhCriticalSection(&initializationLock); { - if (!initialized) { - if (pdhInit() < 0) { - retValue = -1; - } else if (allocateCPUCounters() < 0) { - retValue = -1; - } else if (initializeCPUCounters() < 0) { - retValue = -1; - } - - if (0 == retValue) { - initialized = TRUE; - } else { - deallocateCPUCounters(); - } - } - } LeavePdhCriticalSection(&initializationLock); - - return retValue; -} - -static int -perfCPUInit() { - return initializePdhCPUCounters(); -} - -static double -perfGetProcessCPULoad() { - PDH_FMT_COUNTERVALUE cv; - int currentQueryIndex; - - if (perfCPUInit() < 0) { - // warn? - return -1.0; - } - - currentQueryIndex = getCurrentQueryIndexForProcess(); - - if (getPerformanceData(&processTotalCPULoad[currentQueryIndex].query, - processTotalCPULoad[currentQueryIndex].counter, - &cv, - PDH_FMT_DOUBLE | PDH_FMT_NOCAP100) == 0) { - double d = cv.doubleValue / cpuFactor; - d = min(1, d); - d = max(0, d); - return d; - } - return -1.0; -} - -static double -perfGetCPULoad(int which) { - PDH_FMT_COUNTERVALUE cv; - HCOUNTER c; - - if (perfCPUInit() < 0) { - // warn? - return -1.0; - } - - if (-1 == which) { - c = multiCounterCPULoad->counters[multiCounterCPULoad->noOfCounters - 1]; - } else { - if (which < multiCounterCPULoad->noOfCounters) { - c = multiCounterCPULoad->counters[which]; - } else { - return -1.0; - } - } - if (getPerformanceData(&multiCounterCPULoad->query, c, &cv, PDH_FMT_DOUBLE ) == 0) { - return cv.doubleValue / 100; - } - return -1.0; -} - -JNIEXPORT jdouble JNICALL -Java_sun_management_OperatingSystemImpl_getSystemCpuLoad0 -(JNIEnv *env, jobject dummy) -{ - return perfGetCPULoad(-1); -} - -JNIEXPORT jdouble JNICALL -Java_sun_management_OperatingSystemImpl_getProcessCpuLoad0 -(JNIEnv *env, jobject dummy) -{ - return perfGetProcessCPULoad(); -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,333 @@ +/* + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <stdio.h> +#include <stdint.h> +#include <stdarg.h> +#include <unistd.h> +#include <errno.h> +#include <string.h> +#include <sys/resource.h> +#include <sys/types.h> +#include <dirent.h> +#include <stdlib.h> +#include <dlfcn.h> +#include <pthread.h> +#include <inttypes.h> +#include "com_sun_management_internal_OperatingSystemImpl.h" + +struct ticks { + uint64_t used; + uint64_t usedKernel; + uint64_t total; +}; + +typedef struct ticks ticks; + +typedef enum { + CPU_LOAD_VM_ONLY, + CPU_LOAD_GLOBAL, +} CpuLoadTarget; + +static struct perfbuf { + int nProcs; + ticks jvmTicks; + ticks cpuTicks; + ticks *cpus; +} counters; + +#define DEC_64 "%"SCNd64 + +static void next_line(FILE *f) { + while (fgetc(f) != '\n'); +} + +/** + * Return the total number of ticks since the system was booted. + * If the usedTicks parameter is not NULL, it will be filled with + * the number of ticks spent on actual processes (user, system or + * nice processes) since system boot. Note that this is the total number + * of "executed" ticks on _all_ CPU:s, that is on a n-way system it is + * n times the number of ticks that has passed in clock time. + * + * Returns a negative value if the reading of the ticks failed. + */ +static int get_totalticks(int which, ticks *pticks) { + FILE *fh; + uint64_t userTicks, niceTicks, systemTicks, idleTicks; + int n; + + if((fh = fopen("/proc/stat", "r")) == NULL) { + return -1; + } + + n = fscanf(fh, "cpu " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64, + &userTicks, &niceTicks, &systemTicks, &idleTicks); + + // Move to next line + next_line(fh); + + //find the line for requested cpu faster to just iterate linefeeds? + if (which != -1) { + int i; + for (i = 0; i < which; i++) { + if (fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64, &userTicks, &niceTicks, &systemTicks, &idleTicks) != 4) { + fclose(fh); + return -2; + } + next_line(fh); + } + n = fscanf(fh, "cpu%*d " DEC_64 " " DEC_64 " " DEC_64 " " DEC_64 "\n", + &userTicks, &niceTicks, &systemTicks, &idleTicks); + } + + fclose(fh); + if (n != 4) { + return -2; + } + + pticks->used = userTicks + niceTicks; + pticks->usedKernel = systemTicks; + pticks->total = userTicks + niceTicks + systemTicks + idleTicks; + + return 0; +} + +static int vread_statdata(const char *procfile, const char *fmt, va_list args) { + FILE *f; + int n; + char buf[2048]; + + if ((f = fopen(procfile, "r")) == NULL) { + return -1; + } + + if ((n = fread(buf, 1, sizeof(buf), f)) != -1) { + char *tmp; + + buf[n-1] = '\0'; + /** skip through pid and exec name. the exec name _could be wacky_ (renamed) and + * make scanf go mupp. + */ + if ((tmp = strrchr(buf, ')')) != NULL) { + // skip the ')' and the following space but check that the buffer is long enough + tmp += 2; + if (tmp < buf + n) { + n = vsscanf(tmp, fmt, args); + } + } + } + + fclose(f); + + return n; +} + +static int read_statdata(const char *procfile, const char *fmt, ...) { + int n; + va_list args; + + va_start(args, fmt); + n = vread_statdata(procfile, fmt, args); + va_end(args); + return n; +} + +/** read user and system ticks from a named procfile, assumed to be in 'stat' format then. */ +static int read_ticks(const char *procfile, uint64_t *userTicks, uint64_t *systemTicks) { + return read_statdata(procfile, "%*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u "DEC_64" "DEC_64, + userTicks, systemTicks + ); +} + +/** + * Return the number of ticks spent in any of the processes belonging + * to the JVM on any CPU. + */ +static int get_jvmticks(ticks *pticks) { + uint64_t userTicks; + uint64_t systemTicks; + + if (read_ticks("/proc/self/stat", &userTicks, &systemTicks) < 0) { + return -1; + } + + // get the total + if (get_totalticks(-1, pticks) < 0) { + return -1; + } + + pticks->used = userTicks; + pticks->usedKernel = systemTicks; + + return 0; +} + +/** + * This method must be called first, before any data can be gathererd. + */ +int perfInit() { + static int initialized=1; + + if (!initialized) { + int i; + + int n = sysconf(_SC_NPROCESSORS_ONLN); + if (n <= 0) { + n = 1; + } + + counters.cpus = calloc(n,sizeof(ticks)); + if (counters.cpus != NULL) { + // For the CPU load + get_totalticks(-1, &counters.cpuTicks); + + for (i = 0; i < n; i++) { + get_totalticks(i, &counters.cpus[i]); + } + // For JVM load + get_jvmticks(&counters.jvmTicks); + initialized = 1; + } + } + + return initialized ? 0 : -1; +} + +#define MAX(a,b) (a>b?a:b) +#define MIN(a,b) (a<b?a:b) + +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + +/** + * Return the load of the CPU as a double. 1.0 means the CPU process uses all + * available time for user or system processes, 0.0 means the CPU uses all time + * being idle. + * + * Returns a negative value if there is a problem in determining the CPU load. + */ + +static double get_cpuload_internal(int which, double *pkernelLoad, CpuLoadTarget target) { + uint64_t udiff, kdiff, tdiff; + ticks *pticks, tmp; + double user_load = -1.0; + int failed = 0; + + *pkernelLoad = 0.0; + + pthread_mutex_lock(&lock); + + if(perfInit() == 0) { + + if (target == CPU_LOAD_VM_ONLY) { + pticks = &counters.jvmTicks; + } else if (which == -1) { + pticks = &counters.cpuTicks; + } else { + pticks = &counters.cpus[which]; + } + + tmp = *pticks; + + if (target == CPU_LOAD_VM_ONLY) { + if (get_jvmticks(pticks) != 0) { + failed = 1; + } + } else if (get_totalticks(which, pticks) < 0) { + failed = 1; + } + + if(!failed) { + // seems like we sometimes end up with less kernel ticks when + // reading /proc/self/stat a second time, timing issue between cpus? + if (pticks->usedKernel < tmp.usedKernel) { + kdiff = 0; + } else { + kdiff = pticks->usedKernel - tmp.usedKernel; + } + tdiff = pticks->total - tmp.total; + udiff = pticks->used - tmp.used; + + if (tdiff == 0) { + user_load = 0; + } else { + if (tdiff < (udiff + kdiff)) { + tdiff = udiff + kdiff; + } + *pkernelLoad = (kdiff / (double)tdiff); + // BUG9044876, normalize return values to sane values + *pkernelLoad = MAX(*pkernelLoad, 0.0); + *pkernelLoad = MIN(*pkernelLoad, 1.0); + + user_load = (udiff / (double)tdiff); + user_load = MAX(user_load, 0.0); + user_load = MIN(user_load, 1.0); + } + } + } + pthread_mutex_unlock(&lock); + return user_load; +} + +double get_cpu_load(int which) { + double u, s; + u = get_cpuload_internal(which, &s, CPU_LOAD_GLOBAL); + if (u < 0) { + return -1.0; + } + // Cap total systemload to 1.0 + return MIN((u + s), 1.0); +} + +double get_process_load() { + double u, s; + u = get_cpuload_internal(-1, &s, CPU_LOAD_VM_ONLY); + if (u < 0) { + return -1.0; + } + return u + s; +} + +JNIEXPORT jdouble JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0 +(JNIEnv *env, jobject dummy) +{ + if(perfInit() == 0) { + return get_cpu_load(-1); + } else { + return -1.0; + } +} + +JNIEXPORT jdouble JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0 +(JNIEnv *env, jobject dummy) +{ + if(perfInit() == 0) { + return get_process_load(); + } else { + return -1.0; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/macosx/native/libmanagement_ext/UnixOperatingSystem.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "com_sun_management_internal_OperatingSystemImpl.h" + +#include <sys/time.h> +#include <mach/mach.h> +#include <mach/task_info.h> + +#include "jvm.h" + +JNIEXPORT jdouble JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0 +(JNIEnv *env, jobject dummy) +{ + // This code is influenced by the darwin top source + + kern_return_t kr; + mach_msg_type_number_t count; + host_cpu_load_info_data_t load; + + static jlong last_used = 0; + static jlong last_total = 0; + + count = HOST_CPU_LOAD_INFO_COUNT; + kr = host_statistics(mach_host_self(), HOST_CPU_LOAD_INFO, (host_info_t)&load, &count); + if (kr != KERN_SUCCESS) { + return -1; + } + + jlong used = load.cpu_ticks[CPU_STATE_USER] + load.cpu_ticks[CPU_STATE_NICE] + load.cpu_ticks[CPU_STATE_SYSTEM]; + jlong total = used + load.cpu_ticks[CPU_STATE_IDLE]; + + if (last_used == 0 || last_total == 0) { + // First call, just set the last values + last_used = used; + last_total = total; + // return 0 since we have no data, not -1 which indicates error + return 0; + } + + jlong used_delta = used - last_used; + jlong total_delta = total - last_total; + + jdouble cpu = (jdouble) used_delta / total_delta; + + last_used = used; + last_total = total; + + return cpu; +} + + +#define TIME_VALUE_TO_TIMEVAL(a, r) do { \ + (r)->tv_sec = (a)->seconds; \ + (r)->tv_usec = (a)->microseconds; \ +} while (0) + + +#define TIME_VALUE_TO_MICROSECONDS(TV) \ + ((TV).tv_sec * 1000 * 1000 + (TV).tv_usec) + + +JNIEXPORT jdouble JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0 +(JNIEnv *env, jobject dummy) +{ + // This code is influenced by the darwin top source + + struct task_basic_info_64 task_info_data; + struct task_thread_times_info thread_info_data; + struct timeval user_timeval, system_timeval, task_timeval; + struct timeval now; + mach_port_t task = mach_task_self(); + kern_return_t kr; + + static jlong last_task_time = 0; + static jlong last_time = 0; + + mach_msg_type_number_t thread_info_count = TASK_THREAD_TIMES_INFO_COUNT; + kr = task_info(task, + TASK_THREAD_TIMES_INFO, + (task_info_t)&thread_info_data, + &thread_info_count); + if (kr != KERN_SUCCESS) { + // Most likely cause: |task| is a zombie. + return -1; + } + + mach_msg_type_number_t count = TASK_BASIC_INFO_64_COUNT; + kr = task_info(task, + TASK_BASIC_INFO_64, + (task_info_t)&task_info_data, + &count); + if (kr != KERN_SUCCESS) { + // Most likely cause: |task| is a zombie. + return -1; + } + + /* Set total_time. */ + // thread info contains live time... + TIME_VALUE_TO_TIMEVAL(&thread_info_data.user_time, &user_timeval); + TIME_VALUE_TO_TIMEVAL(&thread_info_data.system_time, &system_timeval); + timeradd(&user_timeval, &system_timeval, &task_timeval); + + // ... task info contains terminated time. + TIME_VALUE_TO_TIMEVAL(&task_info_data.user_time, &user_timeval); + TIME_VALUE_TO_TIMEVAL(&task_info_data.system_time, &system_timeval); + timeradd(&user_timeval, &task_timeval, &task_timeval); + timeradd(&system_timeval, &task_timeval, &task_timeval); + + if (gettimeofday(&now, NULL) < 0) { + return -1; + } + jint ncpus = JVM_ActiveProcessorCount(); + jlong time = TIME_VALUE_TO_MICROSECONDS(now) * ncpus; + jlong task_time = TIME_VALUE_TO_MICROSECONDS(task_timeval); + + if ((last_task_time == 0) || (last_time == 0)) { + // First call, just set the last values. + last_task_time = task_time; + last_time = time; + // return 0 since we have no data, not -1 which indicates error + return 0; + } + + jlong task_time_delta = task_time - last_task_time; + jlong time_delta = time - last_time; + if (time_delta == 0) { + return -1; + } + + jdouble cpu = (jdouble) task_time_delta / time_delta; + + last_task_time = task_time; + last_time = time; + + return cpu; + }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/META-INF/services/sun.management.spi.PlatformMBeanProvider Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,25 @@ +# +# Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. +# +# This code is free software; you can redistribute it and/or modify it +# under the terms of the GNU General Public License version 2 only, as +# published by the Free Software Foundation. Oracle designates this +# particular file as subject to the "Classpath" exception as provided +# by Oracle in the LICENSE file that accompanied this code. +# +# This code is distributed in the hope that it will be useful, but WITHOUT +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +# version 2 for more details (a copy is included in the LICENSE file that +# accompanied this code). +# +# You should have received a copy of the GNU General Public License version +# 2 along with this work; if not, write to the Free Software Foundation, +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA +# or visit www.oracle.com if you need additional information or have any +# questions. +# +com.sun.management.internal.PlatformMBeanProviderImpl
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/DiagnosticCommandMBean.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management; + +import java.lang.management.PlatformManagedObject; +import javax.management.DynamicMBean; + +/** + * Management interface for the diagnostic commands for the HotSpot Virtual Machine. + * + * <p>The {@code DiagnosticCommandMBean} is registered to the + * {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer + * platform MBeanServer} as are other platform MBeans. + * + * <p>The {@link javax.management.ObjectName ObjectName} for uniquely identifying + * the diagnostic MBean within an MBeanServer is: + * <blockquote> + * {@code com.sun.management:type=DiagnosticCommand} + * </blockquote> + * + * <p>This MBean is a {@link javax.management.DynamicMBean DynamicMBean} + * and also a {@link javax.management.NotificationEmitter}. + * The {@code DiagnosticCommandMBean} is generated at runtime and is subject to + * modifications during the lifetime of the Java virtual machine. + * + * A <em>diagnostic command</em> is represented as an operation of + * the {@code DiagnosticCommandMBean} interface. Each diagnostic command has: + * <ul> + * <li>the diagnostic command name which is the name being referenced in + * the HotSpot Virtual Machine</li> + * <li>the MBean operation name which is the + * {@linkplain javax.management.MBeanOperationInfo#getName() name} + * generated for the diagnostic command operation invocation. + * The MBean operation name is implementation dependent</li> + * </ul> + * + * The recommended way to transform a diagnostic command name into a MBean + * operation name is as follows: + * <ul> + * <li>All characters from the first one to the first dot are set to be + * lower-case characters</li> + * <li>Every dot or underline character is removed and the following + * character is set to be an upper-case character</li> + * <li>All other characters are copied without modification</li> + * </ul> + * + * <p>The diagnostic command name is always provided with the meta-data on the + * operation in a field named {@code dcmd.name} (see below). + * + * <p>A diagnostic command may or may not support options or arguments. + * All the operations return {@code String} and either take + * no parameter for operations that do not support any option or argument, + * or take a {@code String[]} parameter for operations that support at least + * one option or argument. + * Each option or argument must be stored in a single String. + * Options or arguments split across several String instances are not supported. + * + * <p>The distinction between options and arguments: options are identified by + * the option name while arguments are identified by their position in the + * command line. Options and arguments are processed in the order of the array + * passed to the invocation method. + * + * <p>Like any operation of a dynamic MBean, each of these operations is + * described by {@link javax.management.MBeanOperationInfo MBeanOperationInfo} + * instance. Here's the values returned by this object: + * <ul> + * <li>{@link javax.management.MBeanOperationInfo#getName() getName()} + * returns the operation name generated from the diagnostic command name</li> + * <li>{@link javax.management.MBeanOperationInfo#getDescription() getDescription()} + * returns the diagnostic command description + * (the same as the one return in the 'help' command)</li> + * <li>{@link javax.management.MBeanOperationInfo#getImpact() getImpact()} + * returns <code>ACTION_INFO</code></li> + * <li>{@link javax.management.MBeanOperationInfo#getReturnType() getReturnType()} + * returns {@code java.lang.String}</li> + * <li>{@link javax.management.MBeanOperationInfo#getDescriptor() getDescriptor()} + * returns a Descriptor instance (see below)</li> + * </ul> + * + * <p>The {@link javax.management.Descriptor Descriptor} + * is a collection of fields containing additional + * meta-data for a JMX element. A field is a name and an associated value. + * The additional meta-data provided for an operation associated with a + * diagnostic command are described in the table below: + * <p> + * + * <table border="1" cellpadding="5"> + * <tr> + * <th>Name</th><th>Type</th><th>Description</th> + * </tr> + * <tr> + * <td>dcmd.name</td><td>String</td> + * <td>The original diagnostic command name (not the operation name)</td> + * </tr> + * <tr> + * <td>dcmd.description</td><td>String</td> + * <td>The diagnostic command description</td> + * </tr> + * <tr> + * <td>dcmd.help</td><td>String</td> + * <td>The full help message for this diagnostic command (same output as + * the one produced by the 'help' command)</td> + * </tr> + * <tr> + * <td>dcmd.vmImpact</td><td>String</td> + * <td>The impact of the diagnostic command, + * this value is the same as the one printed in the 'impact' + * section of the help message of the diagnostic command, and it + * is different from the getImpact() of the MBeanOperationInfo</td> + * </tr> + * <tr> + * <td>dcmd.enabled</td><td>boolean</td> + * <td>True if the diagnostic command is enabled, false otherwise</td> + * </tr> + * <tr> + * <td>dcmd.permissionClass</td><td>String</td> + * <td>Some diagnostic command might require a specific permission to be + * executed, in addition to the MBeanPermission to invoke their + * associated MBean operation. This field returns the fully qualified + * name of the permission class or null if no permission is required + * </td> + * </tr> + * <tr> + * <td>dcmd.permissionName</td><td>String</td> + * <td>The fist argument of the permission required to execute this + * diagnostic command or null if no permission is required</td> + * </tr> + * <tr> + * <td>dcmd.permissionAction</td><td>String</td> + * <td>The second argument of the permission required to execute this + * diagnostic command or null if the permission constructor has only + * one argument (like the ManagementPermission) or if no permission + * is required</td> + * </tr> + * <tr> + * <td>dcmd.arguments</td><td>Descriptor</td> + * <td>A Descriptor instance containing the descriptions of options and + * arguments supported by the diagnostic command (see below)</td> + * </tr> + * </table> + * <p> + * + * <p>The description of parameters (options or arguments) of a diagnostic + * command is provided within a Descriptor instance. In this Descriptor, + * each field name is a parameter name, and each field value is itself + * a Descriptor instance. The fields provided in this second Descriptor + * instance are described in the table below: + * + * <table border="1" cellpadding="5"> + * <tr> + * <th>Name</th><th>Type</th><th>Description</th> + * </tr> + * <tr> + * <td>dcmd.arg.name</td><td>String</td> + * <td>The name of the parameter</td> + * </tr> + * <tr> + * <td>dcmd.arg.type</td><td>String</td> + * <td>The type of the parameter. The returned String is the name of a type + * recognized by the diagnostic command parser. These types are not + * Java types and are implementation dependent. + * </td> + * </tr> + * <tr> + * <td>dcmd.arg.description</td><td>String</td> + * <td>The parameter description</td> + * </tr> + * <tr> + * <td>dcmd.arg.isMandatory</td><td>boolean</td> + * <td>True if the parameter is mandatory, false otherwise</td> + * </tr> + * <tr> + * <td>dcmd.arg.isOption</td><td>boolean</td> + * <td>True if the parameter is an option, false if it is an argument</td> + * </tr> + * <tr> + * <td>dcmd.arg.isMultiple</td><td>boolean</td> + * <td>True if the parameter can be specified several times, false + * otherwise</td> + * </tr> + * </table> + * + * <p>When the set of diagnostic commands currently supported by the Java + * Virtual Machine is modified, the {@code DiagnosticCommandMBean} emits + * a {@link javax.management.Notification} with a + * {@linkplain javax.management.Notification#getType() type} of + * <a href="{@docRoot}/../../../../api/javax/management/MBeanInfo.html#info-changed"> + * {@code "jmx.mbean.info.changed"}</a> and a + * {@linkplain javax.management.Notification#getUserData() userData} that + * is the new {@code MBeanInfo}. + * + * @since 1.8 + */ +public interface DiagnosticCommandMBean extends DynamicMBean +{ + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/GarbageCollectionNotificationInfo.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,235 @@ +/* + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management; + +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataView; +import javax.management.openmbean.CompositeType; +import com.sun.management.internal.GarbageCollectionNotifInfoCompositeData; + +/** + * The information about a garbage collection + * + * <p> + * A garbage collection notification is emitted by {@link GarbageCollectorMXBean} + * when the Java virtual machine completes a garbage collection action + * The notification emitted will contain the garbage collection notification + * information about the status of the memory: + * <u1> + * <li>The name of the garbage collector used to perform the collection.</li> + * <li>The action performed by the garbage collector.</li> + * <li>The cause of the garbage collection action.</li> + * <li>A {@link GcInfo} object containing some statistics about the GC cycle + (start time, end time) and the memory usage before and after + the GC cycle.</li> + * </u1> + * + * <p> + * A {@link CompositeData CompositeData} representing + * the {@code GarbageCollectionNotificationInfo} object + * is stored in the + * {@linkplain javax.management.Notification#setUserData userdata} + * of a {@linkplain javax.management.Notification notification}. + * The {@link #from from} method is provided to convert from + * a {@code CompositeData} to a {@code GarbageCollectionNotificationInfo} + * object. For example: + * + * <blockquote><pre> + * Notification notif; + * + * // receive the notification emitted by a GarbageCollectorMXBean and set to notif + * ... + * + * String notifType = notif.getType(); + * if (notifType.equals(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION)) { + * // retrieve the garbage collection notification information + * CompositeData cd = (CompositeData) notif.getUserData(); + * GarbageCollectionNotificationInfo info = GarbageCollectionNotificationInfo.from(cd); + * .... + * } + * </pre></blockquote> + * + * <p> + * The type of the notification emitted by a {@code GarbageCollectorMXBean} is: + * <ul> + * <li>A {@linkplain #GARBAGE_COLLECTION_NOTIFICATION garbage collection notification}. + * <br>Used by every notification emitted by the garbage collector, the details about + * the notification are provided in the {@linkplain #getGcAction action} String + * <p></li> + * </ul> + **/ + +@jdk.Exported +public class GarbageCollectionNotificationInfo implements CompositeDataView { + + private final String gcName; + private final String gcAction; + private final String gcCause; + private final GcInfo gcInfo; + private final CompositeData cdata; + + /** + * Notification type denoting that + * the Java virtual machine has completed a garbage collection cycle. + * This notification is emitted by a {@link GarbageCollectorMXBean}. + * The value of this notification type is + * {@code com.sun.management.gc.notification}. + */ + public static final String GARBAGE_COLLECTION_NOTIFICATION = + "com.sun.management.gc.notification"; + + /** + * Constructs a {@code GarbageCollectionNotificationInfo} object. + * + * @param gcName The name of the garbage collector used to perform the collection + * @param gcAction The name of the action performed by the garbage collector + * @param gcCause The cause of the garbage collection action + * @param gcInfo a GcInfo object providing statistics about the GC cycle + */ + public GarbageCollectionNotificationInfo(String gcName, + String gcAction, + String gcCause, + GcInfo gcInfo) { + if (gcName == null) { + throw new NullPointerException("Null gcName"); + } + if (gcAction == null) { + throw new NullPointerException("Null gcAction"); + } + if (gcCause == null) { + throw new NullPointerException("Null gcCause"); + } + this.gcName = gcName; + this.gcAction = gcAction; + this.gcCause = gcCause; + this.gcInfo = gcInfo; + this.cdata = new GarbageCollectionNotifInfoCompositeData(this); + } + + GarbageCollectionNotificationInfo(CompositeData cd) { + GarbageCollectionNotifInfoCompositeData.validateCompositeData(cd); + + this.gcName = GarbageCollectionNotifInfoCompositeData.getGcName(cd); + this.gcAction = GarbageCollectionNotifInfoCompositeData.getGcAction(cd); + this.gcCause = GarbageCollectionNotifInfoCompositeData.getGcCause(cd); + this.gcInfo = GarbageCollectionNotifInfoCompositeData.getGcInfo(cd); + this.cdata = cd; + } + + /** + * Returns the name of the garbage collector used to perform the collection + * + * @return the name of the garbage collector used to perform the collection + */ + public String getGcName() { + return gcName; + } + + /** + * Returns the action performed by the garbage collector + * + * @return the action performed by the garbage collector + */ + public String getGcAction() { + return gcAction; + } + + /** + * Returns the cause of the garbage collection + * + * @return the cause of the garbage collection + */ + public String getGcCause() { + return gcCause; + } + + /** + * Returns the GC information related to the last garbage collection + * + * @return the GC information related to the + * last garbage collection + */ + public GcInfo getGcInfo() { + return gcInfo; + } + + /** + * Returns a {@code GarbageCollectionNotificationInfo} object represented by the + * given {@code CompositeData}. + * The given {@code CompositeData} must contain + * the following attributes: + * <blockquote> + * <table border> + * <tr> + * <th align=left>Attribute Name</th> + * <th align=left>Type</th> + * </tr> + * <tr> + * <td>gcName</td> + * <td>{@code java.lang.String}</td> + * </tr> + * <tr> + * <td>gcAction</td> + * <td>{@code java.lang.String}</td> + * </tr> + * <tr> + * <td>gcCause</td> + * <td>{@code java.lang.String}</td> + * </tr> + * <tr> + * <td>gcInfo</td> + * <td>{@code javax.management.openmbean.CompositeData}</td> + * </tr> + * </table> + * </blockquote> + * + * @param cd {@code CompositeData} representing a + * {@code GarbageCollectionNotificationInfo} + * + * @throws IllegalArgumentException if {@code cd} does not + * represent a {@code GarbaageCollectionNotificationInfo} object. + * + * @return a {@code GarbageCollectionNotificationInfo} object represented + * by {@code cd} if {@code cd} is not {@code null}; + * {@code null} otherwise. + */ + public static GarbageCollectionNotificationInfo from(CompositeData cd) { + if (cd == null) { + return null; + } + + if (cd instanceof GarbageCollectionNotifInfoCompositeData) { + return ((GarbageCollectionNotifInfoCompositeData) cd).getGarbageCollectionNotifInfo(); + } else { + return new GarbageCollectionNotificationInfo(cd); + } + } + + public CompositeData toCompositeData(CompositeType ct) { + return cdata; + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/GarbageCollectorMXBean.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeType; + +/** + * Platform-specific management interface for a garbage collector + * which performs collections in cycles. + * + * <p> This platform extension is only available to the garbage + * collection implementation that supports this extension. + * + * @author Mandy Chung + * @since 1.5 + */ +@jdk.Exported +public interface GarbageCollectorMXBean + extends java.lang.management.GarbageCollectorMXBean { + + /** + * Returns the GC information about the most recent GC. + * This method returns a {@link GcInfo}. + * If no GC information is available, <tt>null</tt> is returned. + * The collector-specific attributes, if any, can be obtained + * via the {@link CompositeData CompositeData} interface. + * <p> + * <b>MBeanServer access:</b> + * The mapped type of <tt>GcInfo</tt> is <tt>CompositeData</tt> + * with attributes specified in {@link GcInfo#from GcInfo}. + * + * @return a <tt>GcInfo</tt> object representing + * the most GC information; or <tt>null</tt> if no GC + * information available. + */ + public GcInfo getLastGcInfo(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/GcInfo.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,288 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management; + +import java.lang.management.MemoryUsage; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataView; +import javax.management.openmbean.CompositeType; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import com.sun.management.internal.GcInfoCompositeData; +import com.sun.management.internal.GcInfoBuilder; + +/** + * Garbage collection information. It contains the following + * information for one garbage collection as well as GC-specific + * attributes: + * <blockquote> + * <ul> + * <li>Start time</li> + * <li>End time</li> + * <li>Duration</li> + * <li>Memory usage before the collection starts</li> + * <li>Memory usage after the collection ends</li> + * </ul> + * </blockquote> + * + * <p> + * <tt>GcInfo</tt> is a {@link CompositeData CompositeData} + * The GC-specific attributes can be obtained via the CompositeData + * interface. This is a historical relic, and other classes should + * not copy this pattern. Use {@link CompositeDataView} instead. + * + * <h4>MXBean Mapping</h4> + * <tt>GcInfo</tt> is mapped to a {@link CompositeData CompositeData} + * with attributes as specified in the {@link #from from} method. + * + * @author Mandy Chung + * @since 1.5 + */ +@jdk.Exported +public class GcInfo implements CompositeData, CompositeDataView { + private final long index; + private final long startTime; + private final long endTime; + private final Map<String, MemoryUsage> usageBeforeGc; + private final Map<String, MemoryUsage> usageAfterGc; + private final Object[] extAttributes; + private final CompositeData cdata; + private final GcInfoBuilder builder; + + private GcInfo(GcInfoBuilder builder, + long index, long startTime, long endTime, + MemoryUsage[] muBeforeGc, + MemoryUsage[] muAfterGc, + Object[] extAttributes) { + this.builder = builder; + this.index = index; + this.startTime = startTime; + this.endTime = endTime; + String[] poolNames = builder.getPoolNames(); + this.usageBeforeGc = new HashMap<String, MemoryUsage>(poolNames.length); + this.usageAfterGc = new HashMap<String, MemoryUsage>(poolNames.length); + for (int i = 0; i < poolNames.length; i++) { + this.usageBeforeGc.put(poolNames[i], muBeforeGc[i]); + this.usageAfterGc.put(poolNames[i], muAfterGc[i]); + } + this.extAttributes = extAttributes; + this.cdata = new GcInfoCompositeData(this, builder, extAttributes); + } + + private GcInfo(CompositeData cd) { + GcInfoCompositeData.validateCompositeData(cd); + + this.index = GcInfoCompositeData.getId(cd); + this.startTime = GcInfoCompositeData.getStartTime(cd); + this.endTime = GcInfoCompositeData.getEndTime(cd); + this.usageBeforeGc = GcInfoCompositeData.getMemoryUsageBeforeGc(cd); + this.usageAfterGc = GcInfoCompositeData.getMemoryUsageAfterGc(cd); + this.extAttributes = null; + this.builder = null; + this.cdata = cd; + } + + /** + * Returns the identifier of this garbage collection which is + * the number of collections that this collector has done. + * + * @return the identifier of this garbage collection which is + * the number of collections that this collector has done. + */ + public long getId() { + return index; + } + + /** + * Returns the start time of this GC in milliseconds + * since the Java virtual machine was started. + * + * @return the start time of this GC. + */ + public long getStartTime() { + return startTime; + } + + /** + * Returns the end time of this GC in milliseconds + * since the Java virtual machine was started. + * + * @return the end time of this GC. + */ + public long getEndTime() { + return endTime; + } + + /** + * Returns the elapsed time of this GC in milliseconds. + * + * @return the elapsed time of this GC in milliseconds. + */ + public long getDuration() { + return endTime - startTime; + } + + /** + * Returns the memory usage of all memory pools + * at the beginning of this GC. + * This method returns + * a <tt>Map</tt> of the name of a memory pool + * to the memory usage of the corresponding + * memory pool before GC starts. + * + * @return a <tt>Map</tt> of memory pool names to the memory + * usage of a memory pool before GC starts. + */ + public Map<String, MemoryUsage> getMemoryUsageBeforeGc() { + return Collections.unmodifiableMap(usageBeforeGc); + } + + /** + * Returns the memory usage of all memory pools + * at the end of this GC. + * This method returns + * a <tt>Map</tt> of the name of a memory pool + * to the memory usage of the corresponding + * memory pool when GC finishes. + * + * @return a <tt>Map</tt> of memory pool names to the memory + * usage of a memory pool when GC finishes. + */ + public Map<String, MemoryUsage> getMemoryUsageAfterGc() { + return Collections.unmodifiableMap(usageAfterGc); + } + + /** + * Returns a <tt>GcInfo</tt> object represented by the + * given <tt>CompositeData</tt>. The given + * <tt>CompositeData</tt> must contain + * all the following attributes: + * + * <p> + * <blockquote> + * <table border> + * <tr> + * <th align=left>Attribute Name</th> + * <th align=left>Type</th> + * </tr> + * <tr> + * <td>index</td> + * <td><tt>java.lang.Long</tt></td> + * </tr> + * <tr> + * <td>startTime</td> + * <td><tt>java.lang.Long</tt></td> + * </tr> + * <tr> + * <td>endTime</td> + * <td><tt>java.lang.Long</tt></td> + * </tr> + * <tr> + * <td>memoryUsageBeforeGc</td> + * <td><tt>javax.management.openmbean.TabularData</tt></td> + * </tr> + * <tr> + * <td>memoryUsageAfterGc</td> + * <td><tt>javax.management.openmbean.TabularData</tt></td> + * </tr> + * </table> + * </blockquote> + * + * @throws IllegalArgumentException if <tt>cd</tt> does not + * represent a <tt>GcInfo</tt> object with the attributes + * described above. + * + * @return a <tt>GcInfo</tt> object represented by <tt>cd</tt> + * if <tt>cd</tt> is not <tt>null</tt>; <tt>null</tt> otherwise. + */ + public static GcInfo from(CompositeData cd) { + if (cd == null) { + return null; + } + + if (cd instanceof GcInfoCompositeData) { + return ((GcInfoCompositeData) cd).getGcInfo(); + } else { + return new GcInfo(cd); + } + + } + + // Implementation of the CompositeData interface + public boolean containsKey(String key) { + return cdata.containsKey(key); + } + + public boolean containsValue(Object value) { + return cdata.containsValue(value); + } + + public boolean equals(Object obj) { + return cdata.equals(obj); + } + + public Object get(String key) { + return cdata.get(key); + } + + public Object[] getAll(String[] keys) { + return cdata.getAll(keys); + } + + public CompositeType getCompositeType() { + return cdata.getCompositeType(); + } + + public int hashCode() { + return cdata.hashCode(); + } + + public String toString() { + return cdata.toString(); + } + + public Collection<?> values() { + return cdata.values(); + } + + /** + * <p>Return the {@code CompositeData} representation of this + * {@code GcInfo}, including any GC-specific attributes. The + * returned value will have at least all the attributes described + * in the {@link #from(CompositeData) from} method, plus optionally + * other attributes. + * + * @param ct the {@code CompositeType} that the caller expects. + * This parameter is ignored and can be null. + * + * @return the {@code CompositeData} representation. + */ + public CompositeData toCompositeData(CompositeType ct) { + return cdata; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2005, 2014, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management; + +import java.lang.management.PlatformManagedObject; + +/** + * Diagnostic management interface for the HotSpot Virtual Machine. + * + * <p>The diagnostic MBean is registered to the platform MBeanServer + * as are other platform MBeans. + * + * <p>The <tt>ObjectName</tt> for uniquely identifying the diagnostic + * MXBean within an MBeanServer is: + * <blockquote> + * <tt>com.sun.management:type=HotSpotDiagnostic</tt> + * </blockquote> +.* + * It can be obtained by calling the + * {@link PlatformManagedObject#getObjectName} method. + * + * All methods throw a {@code NullPointerException} if any input argument is + * {@code null} unless it's stated otherwise. + * + * @see java.lang.management.ManagementFactory#getPlatformMXBeans(Class) + */ +@jdk.Exported +public interface HotSpotDiagnosticMXBean extends PlatformManagedObject { + /** + * Dumps the heap to the <tt>outputFile</tt> file in the same + * format as the hprof heap dump. + * <p> + * If this method is called remotely from another process, + * the heap dump output is written to a file named <tt>outputFile</tt> + * on the machine where the target VM is running. If outputFile is + * a relative path, it is relative to the working directory where + * the target VM was started. + * + * @param outputFile the system-dependent filename + * @param live if <tt>true</tt> dump only <i>live</i> objects + * i.e. objects that are reachable from others + * @throws IOException if the <tt>outputFile</tt> + * cannot be created, opened, or written to. + * @throws UnsupportedOperationException if this operation is not supported. + * @throws NullPointerException if <tt>outputFile</tt> is <tt>null</tt>. + * @throws SecurityException + * If a security manager exists and its {@link + * java.lang.SecurityManager#checkWrite(java.lang.String)} + * method denies write access to the named file + * or the caller does not have ManagmentPermission("control"). + */ + public void dumpHeap(String outputFile, boolean live) throws java.io.IOException; + + /** + * Returns a list of <tt>VMOption</tt> objects for all diagnostic options. + * A diagnostic option is a {@link VMOption#isWriteable writeable} + * VM option that can be set dynamically mainly for troubleshooting + * and diagnosis. + * + * @return a list of <tt>VMOption</tt> objects for all diagnostic options. + */ + public java.util.List<VMOption> getDiagnosticOptions(); + + /** + * Returns a <tt>VMOption</tt> object for a VM option of the given + * name. + * + * @return a <tt>VMOption</tt> object for a VM option of the given name. + * @throws NullPointerException if name is <tt>null</tt>. + * @throws IllegalArgumentException if a VM option of the given name + * does not exist. + */ + public VMOption getVMOption(String name); + + /** + * Sets a VM option of the given name to the specified value. + * The new value will be reflected in a new <tt>VMOption</tt> + * object returned by the {@link #getVMOption} method or + * the {@link #getDiagnosticOptions} method. This method does + * not change the value of this <tt>VMOption</tt> object. + * + * @param name Name of a VM option + * @param value New value of the VM option to be set + * + * @throws IllegalArgumentException if the VM option of the given name + * does not exist. + * @throws IllegalArgumentException if the new value is invalid. + * @throws IllegalArgumentException if the VM option is not writable. + * @throws NullPointerException if name or value is <tt>null</tt>. + * + * @throws java.lang.SecurityException + * if a security manager exists and the caller does not have + * ManagementPermission("control"). + */ + public void setVMOption(String name, String value); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/OperatingSystemMXBean.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management; + +/** + * Platform-specific management interface for the operating system + * on which the Java virtual machine is running. + * + * <p> + * The <tt>OperatingSystemMXBean</tt> object returned by + * {@link java.lang.management.ManagementFactory#getOperatingSystemMXBean()} + * is an instance of the implementation class of this interface + * or {@link UnixOperatingSystemMXBean} interface depending on + * its underlying operating system. + * + * @author Mandy Chung + * @since 1.5 + */ +@jdk.Exported +public interface OperatingSystemMXBean extends + java.lang.management.OperatingSystemMXBean { + + /** + * Returns the amount of virtual memory that is guaranteed to + * be available to the running process in bytes, + * or <tt>-1</tt> if this operation is not supported. + * + * @return the amount of virtual memory that is guaranteed to + * be available to the running process in bytes, + * or <tt>-1</tt> if this operation is not supported. + */ + public long getCommittedVirtualMemorySize(); + + /** + * Returns the total amount of swap space in bytes. + * + * @return the total amount of swap space in bytes. + */ + public long getTotalSwapSpaceSize(); + + /** + * Returns the amount of free swap space in bytes. + * + * @return the amount of free swap space in bytes. + */ + public long getFreeSwapSpaceSize(); + + /** + * Returns the CPU time used by the process on which the Java + * virtual machine is running in nanoseconds. The returned value + * is of nanoseconds precision but not necessarily nanoseconds + * accuracy. This method returns <tt>-1</tt> if the + * the platform does not support this operation. + * + * @return the CPU time used by the process in nanoseconds, + * or <tt>-1</tt> if this operation is not supported. + */ + public long getProcessCpuTime(); + + /** + * Returns the amount of free physical memory in bytes. + * + * @return the amount of free physical memory in bytes. + */ + public long getFreePhysicalMemorySize(); + + /** + * Returns the total amount of physical memory in bytes. + * + * @return the total amount of physical memory in bytes. + */ + public long getTotalPhysicalMemorySize(); + + /** + * Returns the "recent cpu usage" for the whole system. This value is a + * double in the [0.0,1.0] interval. A value of 0.0 means that all CPUs + * were idle during the recent period of time observed, while a value + * of 1.0 means that all CPUs were actively running 100% of the time + * during the recent period being observed. All values betweens 0.0 and + * 1.0 are possible depending of the activities going on in the system. + * If the system recent cpu usage is not available, the method returns a + * negative value. + * + * @return the "recent cpu usage" for the whole system; a negative + * value if not available. + * @since 1.7 + */ + public double getSystemCpuLoad(); + + /** + * Returns the "recent cpu usage" for the Java Virtual Machine process. + * This value is a double in the [0.0,1.0] interval. A value of 0.0 means + * that none of the CPUs were running threads from the JVM process during + * the recent period of time observed, while a value of 1.0 means that all + * CPUs were actively running threads from the JVM 100% of the time + * during the recent period being observed. Threads from the JVM include + * the application threads as well as the JVM internal threads. All values + * betweens 0.0 and 1.0 are possible depending of the activities going on + * in the JVM process and the whole system. If the Java Virtual Machine + * recent CPU usage is not available, the method returns a negative value. + * + * @return the "recent cpu usage" for the Java Virtual Machine process; + * a negative value if not available. + * @since 1.7 + */ + public double getProcessCpuLoad(); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/ThreadMXBean.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2011, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management; + +import java.util.Map; + +/** + * Platform-specific management interface for the thread system + * of the Java virtual machine. + * <p> + * This platform extension is only available to a thread + * implementation that supports this extension. + * + * @author Paul Hohensee + * @since 6u25 + */ + +@jdk.Exported +public interface ThreadMXBean extends java.lang.management.ThreadMXBean { + /** + * Returns the total CPU time for each thread whose ID is + * in the input array {@code ids} in nanoseconds. + * The returned values are of nanoseconds precision but + * not necessarily nanoseconds accuracy. + * <p> + * This method is equivalent to calling the + * {@link ThreadMXBean#getThreadCpuTime(long)} + * method for each thread ID in the input array {@code ids} and setting the + * returned value in the corresponding element of the returned array. + * + * @param ids an array of thread IDs. + * @return an array of long values, each of which is the amount of CPU + * time the thread whose ID is in the corresponding element of the input + * array of IDs has used, + * if the thread of a specified ID exists, the thread is alive, + * and CPU time measurement is enabled; + * {@code -1} otherwise. + * + * @throws NullPointerException if {@code ids} is {@code null} + * @throws IllegalArgumentException if any element in the input array + * {@code ids} is {@code <=} {@code 0}. + * @throws java.lang.UnsupportedOperationException if the Java + * virtual machine implementation does not support CPU time + * measurement. + * + * @see ThreadMXBean#getThreadCpuTime(long) + * @see #getThreadUserTime + * @see ThreadMXBean#isThreadCpuTimeSupported + * @see ThreadMXBean#isThreadCpuTimeEnabled + * @see ThreadMXBean#setThreadCpuTimeEnabled + */ + public long[] getThreadCpuTime(long[] ids); + + /** + * Returns the CPU time that each thread whose ID is in the input array + * {@code ids} has executed in user mode in nanoseconds. + * The returned values are of nanoseconds precision but + * not necessarily nanoseconds accuracy. + * <p> + * This method is equivalent to calling the + * {@link ThreadMXBean#getThreadUserTime(long)} + * method for each thread ID in the input array {@code ids} and setting the + * returned value in the corresponding element of the returned array. + * + * @param ids an array of thread IDs. + * @return an array of long values, each of which is the amount of user + * mode CPU time the thread whose ID is in the corresponding element of + * the input array of IDs has used, + * if the thread of a specified ID exists, the thread is alive, + * and CPU time measurement is enabled; + * {@code -1} otherwise. + * + * @throws NullPointerException if {@code ids} is {@code null} + * @throws IllegalArgumentException if any element in the input array + * {@code ids} is {@code <=} {@code 0}. + * @throws java.lang.UnsupportedOperationException if the Java + * virtual machine implementation does not support CPU time + * measurement. + * + * @see ThreadMXBean#getThreadUserTime(long) + * @see #getThreadCpuTime + * @see ThreadMXBean#isThreadCpuTimeSupported + * @see ThreadMXBean#isThreadCpuTimeEnabled + * @see ThreadMXBean#setThreadCpuTimeEnabled + */ + public long[] getThreadUserTime(long[] ids); + + /** + * Returns an approximation of the total amount of memory, in bytes, + * allocated in heap memory for the thread of the specified ID. + * The returned value is an approximation because some Java virtual machine + * implementations may use object allocation mechanisms that result in a + * delay between the time an object is allocated and the time its size is + * recorded. + * <p> + * If the thread of the specified ID is not alive or does not exist, + * this method returns {@code -1}. If thread memory allocation measurement + * is disabled, this method returns {@code -1}. + * A thread is alive if it has been started and has not yet died. + * <p> + * If thread memory allocation measurement is enabled after the thread has + * started, the Java virtual machine implementation may choose any time up + * to and including the time that the capability is enabled as the point + * where thread memory allocation measurement starts. + * + * @param id the thread ID of a thread + * @return an approximation of the total memory allocated, in bytes, in + * heap memory for a thread of the specified ID + * if the thread of the specified ID exists, the thread is alive, + * and thread memory allocation measurement is enabled; + * {@code -1} otherwise. + * + * @throws IllegalArgumentException if {@code id} {@code <=} {@code 0}. + * @throws java.lang.UnsupportedOperationException if the Java virtual + * machine implementation does not support thread memory allocation + * measurement. + * + * @see #isThreadAllocatedMemorySupported + * @see #isThreadAllocatedMemoryEnabled + * @see #setThreadAllocatedMemoryEnabled + */ + public long getThreadAllocatedBytes(long id); + + /** + * Returns an approximation of the total amount of memory, in bytes, + * allocated in heap memory for each thread whose ID is in the input + * array {@code ids}. + * The returned values are approximations because some Java virtual machine + * implementations may use object allocation mechanisms that result in a + * delay between the time an object is allocated and the time its size is + * recorded. + * <p> + * This method is equivalent to calling the + * {@link #getThreadAllocatedBytes(long)} + * method for each thread ID in the input array {@code ids} and setting the + * returned value in the corresponding element of the returned array. + * + * @param ids an array of thread IDs. + * @return an array of long values, each of which is an approximation of + * the total memory allocated, in bytes, in heap memory for the thread + * whose ID is in the corresponding element of the input array of IDs. + * + * @throws NullPointerException if {@code ids} is {@code null} + * @throws IllegalArgumentException if any element in the input array + * {@code ids} is {@code <=} {@code 0}. + * @throws java.lang.UnsupportedOperationException if the Java virtual + * machine implementation does not support thread memory allocation + * measurement. + * + * @see #getThreadAllocatedBytes(long) + * @see #isThreadAllocatedMemorySupported + * @see #isThreadAllocatedMemoryEnabled + * @see #setThreadAllocatedMemoryEnabled + */ + public long[] getThreadAllocatedBytes(long[] ids); + + /** + * Tests if the Java virtual machine implementation supports thread memory + * allocation measurement. + * + * @return + * {@code true} + * if the Java virtual machine implementation supports thread memory + * allocation measurement; + * {@code false} otherwise. + */ + public boolean isThreadAllocatedMemorySupported(); + + /** + * Tests if thread memory allocation measurement is enabled. + * + * @return {@code true} if thread memory allocation measurement is enabled; + * {@code false} otherwise. + * + * @throws java.lang.UnsupportedOperationException if the Java virtual + * machine does not support thread memory allocation measurement. + * + * @see #isThreadAllocatedMemorySupported + */ + public boolean isThreadAllocatedMemoryEnabled(); + + /** + * Enables or disables thread memory allocation measurement. The default + * is platform dependent. + * + * @param enable {@code true} to enable; + * {@code false} to disable. + * + * @throws java.lang.UnsupportedOperationException if the Java virtual + * machine does not support thread memory allocation measurement. + * + * @throws java.lang.SecurityException if a security manager + * exists and the caller does not have + * ManagementPermission("control"). + * + * @see #isThreadAllocatedMemorySupported + */ + public void setThreadAllocatedMemoryEnabled(boolean enable); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/UnixOperatingSystemMXBean.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management; + +/** + * Platform-specific management interface for the Unix + * operating system on which the Java virtual machine is running. + * + * @author Mandy Chung + * @since 1.5 + */ +@jdk.Exported +public interface UnixOperatingSystemMXBean extends + com.sun.management.OperatingSystemMXBean { + + /** + * Returns the number of open file descriptors. + * + * @return the number of open file descriptors. + */ + public long getOpenFileDescriptorCount(); + + /** + * Returns the maximum number of file descriptors. + * + * @return the maximum number of file descriptors. + */ + public long getMaxFileDescriptorCount(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/VMOption.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management; + +import com.sun.management.internal.VMOptionCompositeData; +import javax.management.openmbean.CompositeData; + +/** + * Information about a VM option including its value and + * where the value came from which is referred as its + * {@link VMOption.Origin <i>origin</i>}. + * <p> + * Each VM option has a default value. A VM option can + * be set at VM creation time typically as a command line + * argument to the launcher or an argument passed to the + * VM created using the JNI invocation interface. + * In addition, a VM option may be set via an environment + * variable or a configuration file. A VM option can also + * be set dynamically via a management interface after + * the VM was started. + * + * A <tt>VMOption</tt> contains the value of a VM option + * and the origin of that value at the time this <tt>VMOption</tt> + * object was constructed. The value of the VM option + * may be changed after the <tt>VMOption</tt> object was constructed, + * + * @see <a href="{@docRoot}/../../../../technotes/guides/vm/index.html"> + * Java Virtual Machine</a> + * @author Mandy Chung + * @since 1.6 + */ +@jdk.Exported +public class VMOption { + private String name; + private String value; + private boolean writeable; + private Origin origin; + + /** + * Origin of the value of a VM option. It tells where the + * value of a VM option came from. + * + * @since 1.6 + */ + @jdk.Exported + public enum Origin { + /** + * The VM option has not been set and its value + * is the default value. + */ + DEFAULT, + /** + * The VM option was set at VM creation time typically + * as a command line argument to the launcher or + * an argument passed to the VM created using the + * JNI invocation interface. + */ + VM_CREATION, + /** + * The VM option was set via an environment variable. + */ + ENVIRON_VAR, + /** + * The VM option was set via a configuration file. + */ + CONFIG_FILE, + /** + * The VM option was set via the management interface after the VM + * was started. + */ + MANAGEMENT, + /** + * The VM option was set via the VM ergonomic support. + */ + ERGONOMIC, + /** + * The VM option was set using the attach framework. + * @since 1.9 + */ + ATTACH_ON_DEMAND, + /** + * The VM option was set via some other mechanism. + */ + OTHER + } + + /** + * Constructs a <tt>VMOption</tt>. + * + * @param name Name of a VM option. + * @param value Value of a VM option. + * @param writeable <tt>true</tt> if a VM option can be set dynamically, + * or <tt>false</tt> otherwise. + * @param origin where the value of a VM option came from. + * + * @throws NullPointerException if the name or value is <tt>null</tt> + */ + public VMOption(String name, String value, boolean writeable, Origin origin) { + this.name = name; + this.value = value; + this.writeable = writeable; + this.origin = origin; + } + + /** + * Constructs a <tt>VMOption</tt> object from a + * {@link CompositeData CompositeData}. + */ + private VMOption(CompositeData cd) { + // validate the input composite data + VMOptionCompositeData.validateCompositeData(cd); + + this.name = VMOptionCompositeData.getName(cd); + this.value = VMOptionCompositeData.getValue(cd); + this.writeable = VMOptionCompositeData.isWriteable(cd); + this.origin = VMOptionCompositeData.getOrigin(cd); + } + + /** + * Returns the name of this VM option. + * + * @return the name of this VM option. + */ + public String getName() { + return name; + } + + /** + * Returns the value of this VM option at the time when + * this <tt>VMOption</tt> was created. The value could have been changed. + * + * @return the value of the VM option at the time when + * this <tt>VMOption</tt> was created. + */ + public String getValue() { + return value; + } + + /** + * Returns the origin of the value of this VM option. That is, + * where the value of this VM option came from. + * + * @return where the value of this VM option came from. + */ + public Origin getOrigin() { + return origin; + } + + /** + * Tests if this VM option is writeable. If this VM option is writeable, + * it can be set by the {@link HotSpotDiagnosticMXBean#setVMOption + * HotSpotDiagnosticMXBean.setVMOption} method. + * + * @return <tt>true</tt> if this VM option is writeable; <tt>false</tt> + * otherwise. + */ + public boolean isWriteable() { + return writeable; + } + + public String toString() { + return "VM option: " + getName() + + " value: " + value + " " + + " origin: " + origin + " " + + (writeable ? "(read-write)" : "(read-only)"); + } + + /** + * Returns a <tt>VMOption</tt> object represented by the + * given <tt>CompositeData</tt>. The given <tt>CompositeData</tt> + * must contain the following attributes: + * <p> + * <blockquote> + * <table border> + * <tr> + * <th align=left>Attribute Name</th> + * <th align=left>Type</th> + * </tr> + * <tr> + * <td>name</td> + * <td><tt>java.lang.String</tt></td> + * </tr> + * <tr> + * <td>value</td> + * <td><tt>java.lang.String</tt></td> + * </tr> + * <tr> + * <td>origin</td> + * <td><tt>java.lang.String</tt></td> + * </tr> + * <tr> + * <td>writeable</td> + * <td><tt>java.lang.Boolean</tt></td> + * </tr> + * </table> + * </blockquote> + * + * @param cd <tt>CompositeData</tt> representing a <tt>VMOption</tt> + * + * @throws IllegalArgumentException if <tt>cd</tt> does not + * represent a <tt>VMOption</tt> with the attributes described + * above. + * + * @return a <tt>VMOption</tt> object represented by <tt>cd</tt> + * if <tt>cd</tt> is not <tt>null</tt>; + * <tt>null</tt> otherwise. + */ + public static VMOption from(CompositeData cd) { + if (cd == null) { + return null; + } + + if (cd instanceof VMOptionCompositeData) { + return ((VMOptionCompositeData) cd).getVMOption(); + } else { + return new VMOption(cd); + } + + } + + // for sun.management.MappedMXBeanType + static CompositeData toCompositeData(VMOption option) { + return VMOptionCompositeData.toCompositeData(option); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/DiagnosticCommandArgumentInfo.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +/** + * Diagnostic Command Argument information. It contains the description + * of one parameter of the diagnostic command. A parameter can either be an + * option or an argument. Options are identified by the option name while + * arguments are identified by their position in the command line. The generic + * syntax of a diagnostic command is: + * <blockquote> + * <command name> [<option>=<value>] [<argument_value>] + * </blockquote> + * Example: + * <blockquote> + * command_name option1=value1 option2=value argumentA argumentB argumentC + * </blockquote> + * In this command line, the diagnostic command receives five parameters, two + * options named {@code option1} and {@code option2}, and three arguments. + * argumentA's position is 0, argumentB's position is 1 and argumentC's + * position is 2. + * + * @since 1.8 + */ + +class DiagnosticCommandArgumentInfo { + private final String name; + private final String description; + private final String type; + private final String defaultValue; + private final boolean mandatory; + private final boolean option; + private final boolean multiple; + private final int position; + + /** + * Returns the argument name. + * + * @return the argument name + */ + String getName() { + return name; + } + + /** + * Returns the argument description. + * + * @return the argument description + */ + String getDescription() { + return description; + } + + /** + * Returns the argument type. + * + * @return the argument type + */ + String getType() { + return type; + } + + /** + * Returns the default value as a String if a default value + * is defined, null otherwise. + * + * @return the default value as a String if a default value + * is defined, null otherwise. + */ + String getDefault() { + return defaultValue; + } + + /** + * Returns {@code true} if the argument is mandatory, + * {@code false} otherwise. + * + * @return {@code true} if the argument is mandatory, + * {@code false} otherwise + */ + boolean isMandatory() { + return mandatory; + } + + /** + * Returns {@code true} if the argument is an option, + * {@code false} otherwise. Options have to be specified using the + * <key>=<value> syntax on the command line, while other + * arguments are specified with a single <value> field and are + * identified by their position on command line. + * + * @return {@code true} if the argument is an option, + * {@code false} otherwise + */ + boolean isOption() { + return option; + } + + /** + * Returns {@code true} if the argument can be specified multiple times, + * {@code false} otherwise. + * + * @return {@code true} if the argument can be specified multiple times, + * {@code false} otherwise + */ + boolean isMultiple() { + return multiple; + } + + /** + * Returns the expected position of this argument if it is not an option, + * -1 otherwise. Argument position if defined from left to right, + * starting at zero and ignoring the diagnostic command name and + * options. + * + * @return the expected position of this argument if it is not an option, + * -1 otherwise. + */ + int getPosition() { + return position; + } + + DiagnosticCommandArgumentInfo(String name, String description, + String type, String defaultValue, + boolean mandatory, boolean option, + boolean multiple, int position) { + this.name = name; + this.description = description; + this.type = type; + this.defaultValue = defaultValue; + this.mandatory = mandatory; + this.option = option; + this.multiple = multiple; + this.position = position; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/DiagnosticCommandImpl.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,411 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +import com.sun.management.DiagnosticCommandMBean; +import java.lang.reflect.Constructor; +import java.lang.reflect.InvocationTargetException; +import java.security.Permission; +import java.util.*; +import javax.management.Attribute; +import javax.management.AttributeList; +import javax.management.AttributeNotFoundException; +import javax.management.Descriptor; +import javax.management.ImmutableDescriptor; +import javax.management.InvalidAttributeValueException; +import javax.management.ListenerNotFoundException; +import javax.management.MBeanException; +import javax.management.MBeanInfo; +import javax.management.MBeanNotificationInfo; +import javax.management.MBeanOperationInfo; +import javax.management.MBeanParameterInfo; +import javax.management.MalformedObjectNameException; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.ObjectName; +import javax.management.ReflectionException; +import sun.management.ManagementFactoryHelper; +import sun.management.NotificationEmitterSupport; +import sun.management.VMManagement; + +/** + * Implementation class for the diagnostic commands subsystem. + * + * @since 1.8 + */ +public class DiagnosticCommandImpl extends NotificationEmitterSupport + implements DiagnosticCommandMBean { + + private final VMManagement jvm; + private volatile Map<String, Wrapper> wrappers = null; + private static final String strClassName = "".getClass().getName(); + private static final String strArrayClassName = String[].class.getName(); + private final boolean isSupported; + private static DiagnosticCommandImpl diagCommandMBean = null; + + static synchronized DiagnosticCommandMBean getDiagnosticCommandMBean() { + VMManagement jvm = ManagementFactoryHelper.getVMManagement(); + + // Remote Diagnostic Commands may not be supported + if (diagCommandMBean == null && jvm.isRemoteDiagnosticCommandsSupported()) { + diagCommandMBean = new DiagnosticCommandImpl(jvm); + } + return diagCommandMBean; + } + + @Override + public Object getAttribute(String attribute) throws AttributeNotFoundException, + MBeanException, ReflectionException { + throw new AttributeNotFoundException(attribute); + } + + @Override + public void setAttribute(Attribute attribute) throws AttributeNotFoundException, + InvalidAttributeValueException, MBeanException, ReflectionException { + throw new AttributeNotFoundException(attribute.getName()); + } + + @Override + public AttributeList getAttributes(String[] attributes) { + return new AttributeList(); + } + + @Override + public AttributeList setAttributes(AttributeList attributes) { + return new AttributeList(); + } + + private class Wrapper { + + String name; + String cmd; + DiagnosticCommandInfo info; + Permission permission; + + Wrapper(String name, String cmd, DiagnosticCommandInfo info) + throws InstantiationException { + this.name = name; + this.cmd = cmd; + this.info = info; + this.permission = null; + Exception cause = null; + if (info.getPermissionClass() != null) { + try { + Class<?> c = Class.forName(info.getPermissionClass()); + if (info.getPermissionAction() == null) { + try { + Constructor<?> constructor = c.getConstructor(String.class); + permission = (Permission) constructor.newInstance(info.getPermissionName()); + + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException ex) { + cause = ex; + } + } + if (permission == null) { + try { + Constructor<?> constructor = c.getConstructor(String.class, String.class); + permission = (Permission) constructor.newInstance( + info.getPermissionName(), + info.getPermissionAction()); + } catch (InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException ex) { + cause = ex; + } + } + } catch (ClassNotFoundException ex) { } + if (permission == null) { + InstantiationException iex = + new InstantiationException("Unable to instantiate required permission"); + iex.initCause(cause); + } + } + } + + public String execute(String[] args) { + if (permission != null) { + SecurityManager sm = System.getSecurityManager(); + if (sm != null) { + sm.checkPermission(permission); + } + } + if(args == null) { + return executeDiagnosticCommand(cmd); + } else { + StringBuilder sb = new StringBuilder(); + sb.append(cmd); + for(int i=0; i<args.length; i++) { + if(args[i] == null) { + throw new IllegalArgumentException("Invalid null argument"); + } + sb.append(" "); + sb.append(args[i]); + } + return executeDiagnosticCommand(sb.toString()); + } + } + } + + DiagnosticCommandImpl(VMManagement jvm) { + this.jvm = jvm; + isSupported = jvm.isRemoteDiagnosticCommandsSupported(); + } + + private static class OperationInfoComparator implements Comparator<MBeanOperationInfo> { + @Override + public int compare(MBeanOperationInfo o1, MBeanOperationInfo o2) { + return o1.getName().compareTo(o2.getName()); + } + } + + @Override + public MBeanInfo getMBeanInfo() { + SortedSet<MBeanOperationInfo> operations = new TreeSet<>(new OperationInfoComparator()); + Map<String, Wrapper> wrappersmap; + if (!isSupported) { + wrappersmap = Collections.emptyMap(); + } else { + try { + String[] command = getDiagnosticCommands(); + DiagnosticCommandInfo[] info = getDiagnosticCommandInfo(command); + MBeanParameterInfo stringArgInfo[] = new MBeanParameterInfo[]{ + new MBeanParameterInfo("arguments", strArrayClassName, + "Array of Diagnostic Commands Arguments and Options") + }; + wrappersmap = new HashMap<>(); + for (int i = 0; i < command.length; i++) { + String name = transform(command[i]); + try { + Wrapper w = new Wrapper(name, command[i], info[i]); + wrappersmap.put(name, w); + operations.add(new MBeanOperationInfo( + w.name, + w.info.getDescription(), + (w.info.getArgumentsInfo() == null + || w.info.getArgumentsInfo().isEmpty()) + ? null : stringArgInfo, + strClassName, + MBeanOperationInfo.ACTION_INFO, + commandDescriptor(w))); + } catch (InstantiationException ex) { + // If for some reasons the creation of a diagnostic command + // wrappers fails, the diagnostic command is just ignored + // and won't appear in the DynamicMBean + } + } + } catch (IllegalArgumentException | UnsupportedOperationException e) { + wrappersmap = Collections.emptyMap(); + } + } + wrappers = Collections.unmodifiableMap(wrappersmap); + HashMap<String, Object> map = new HashMap<>(); + map.put("immutableInfo", "false"); + map.put("interfaceClassName","com.sun.management.DiagnosticCommandMBean"); + map.put("mxbean", "false"); + Descriptor desc = new ImmutableDescriptor(map); + return new MBeanInfo( + this.getClass().getName(), + "Diagnostic Commands", + null, // attributes + null, // constructors + operations.toArray(new MBeanOperationInfo[operations.size()]), // operations + getNotificationInfo(), // notifications + desc); + } + + @Override + public Object invoke(String actionName, Object[] params, String[] signature) + throws MBeanException, ReflectionException { + if (!isSupported) { + throw new UnsupportedOperationException(); + } + if (wrappers == null) { + getMBeanInfo(); + } + Wrapper w = wrappers.get(actionName); + if (w != null) { + if (w.info.getArgumentsInfo().isEmpty() + && (params == null || params.length == 0) + && (signature == null || signature.length == 0)) { + return w.execute(null); + } else if((params != null && params.length == 1) + && (signature != null && signature.length == 1 + && signature[0] != null + && signature[0].compareTo(strArrayClassName) == 0)) { + return w.execute((String[]) params[0]); + } + } + throw new ReflectionException(new NoSuchMethodException(actionName)); + } + + private static String transform(String name) { + StringBuilder sb = new StringBuilder(); + boolean toLower = true; + boolean toUpper = false; + for (int i = 0; i < name.length(); i++) { + char c = name.charAt(i); + if (c == '.' || c == '_') { + toLower = false; + toUpper = true; + } else { + if (toUpper) { + toUpper = false; + sb.append(Character.toUpperCase(c)); + } else if(toLower) { + sb.append(Character.toLowerCase(c)); + } else { + sb.append(c); + } + } + } + return sb.toString(); + } + + private Descriptor commandDescriptor(Wrapper w) throws IllegalArgumentException { + HashMap<String, Object> map = new HashMap<>(); + map.put("dcmd.name", w.info.getName()); + map.put("dcmd.description", w.info.getDescription()); + map.put("dcmd.vmImpact", w.info.getImpact()); + map.put("dcmd.permissionClass", w.info.getPermissionClass()); + map.put("dcmd.permissionName", w.info.getPermissionName()); + map.put("dcmd.permissionAction", w.info.getPermissionAction()); + map.put("dcmd.enabled", w.info.isEnabled()); + StringBuilder sb = new StringBuilder(); + sb.append("help "); + sb.append(w.info.getName()); + map.put("dcmd.help", executeDiagnosticCommand(sb.toString())); + if (w.info.getArgumentsInfo() != null && !w.info.getArgumentsInfo().isEmpty()) { + HashMap<String, Object> allargmap = new HashMap<>(); + for (DiagnosticCommandArgumentInfo arginfo : w.info.getArgumentsInfo()) { + HashMap<String, Object> argmap = new HashMap<>(); + argmap.put("dcmd.arg.name", arginfo.getName()); + argmap.put("dcmd.arg.type", arginfo.getType()); + argmap.put("dcmd.arg.description", arginfo.getDescription()); + argmap.put("dcmd.arg.isMandatory", arginfo.isMandatory()); + argmap.put("dcmd.arg.isMultiple", arginfo.isMultiple()); + boolean isOption = arginfo.isOption(); + argmap.put("dcmd.arg.isOption", isOption); + if(!isOption) { + argmap.put("dcmd.arg.position", arginfo.getPosition()); + } else { + argmap.put("dcmd.arg.position", -1); + } + allargmap.put(arginfo.getName(), new ImmutableDescriptor(argmap)); + } + map.put("dcmd.arguments", new ImmutableDescriptor(allargmap)); + } + return new ImmutableDescriptor(map); + } + + private final static String notifName = + "javax.management.Notification"; + + private final static String[] diagFramNotifTypes = { + "jmx.mbean.info.changed" + }; + + private MBeanNotificationInfo[] notifInfo = null; + + @Override + public MBeanNotificationInfo[] getNotificationInfo() { + synchronized (this) { + if (notifInfo == null) { + notifInfo = new MBeanNotificationInfo[1]; + notifInfo[0] = + new MBeanNotificationInfo(diagFramNotifTypes, + notifName, + "Diagnostic Framework Notification"); + } + } + return notifInfo; + } + + private static long seqNumber = 0; + private static long getNextSeqNumber() { + return ++seqNumber; + } + + private void createDiagnosticFrameworkNotification() { + + if (!hasListeners()) { + return; + } + ObjectName on = null; + try { + on = ObjectName.getInstance(PlatformMBeanProviderImpl.DIAGNOSTIC_COMMAND_MBEAN_NAME); + } catch (MalformedObjectNameException e) { } + Notification notif = new Notification("jmx.mbean.info.changed", + on, + getNextSeqNumber()); + notif.setUserData(getMBeanInfo()); + sendNotification(notif); + } + + @Override + public synchronized void addNotificationListener(NotificationListener listener, + NotificationFilter filter, + Object handback) { + boolean before = hasListeners(); + super.addNotificationListener(listener, filter, handback); + boolean after = hasListeners(); + if (!before && after) { + setNotificationEnabled(true); + } + } + + @Override + public synchronized void removeNotificationListener(NotificationListener listener) + throws ListenerNotFoundException { + boolean before = hasListeners(); + super.removeNotificationListener(listener); + boolean after = hasListeners(); + if (before && !after) { + setNotificationEnabled(false); + } + } + + @Override + public synchronized void removeNotificationListener(NotificationListener listener, + NotificationFilter filter, + Object handback) + throws ListenerNotFoundException { + boolean before = hasListeners(); + super.removeNotificationListener(listener, filter, handback); + boolean after = hasListeners(); + if (before && !after) { + setNotificationEnabled(false); + } + } + + private native void setNotificationEnabled(boolean enabled); + private native String[] getDiagnosticCommands(); + private native DiagnosticCommandInfo[] getDiagnosticCommandInfo(String[] commands); + private native String executeDiagnosticCommand(String command); + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/DiagnosticCommandInfo.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +import java.util.List; + +/** + * Diagnostic command information. It contains the description of a + * diagnostic command. + * + * @since 1.8 + */ + +class DiagnosticCommandInfo { + private final String name; + private final String description; + private final String impact; + private final String permissionClass; + private final String permissionName; + private final String permissionAction; + private final boolean enabled; + private final List<DiagnosticCommandArgumentInfo> arguments; + + /** + * Returns the diagnostic command name. + * + * @return the diagnostic command name + */ + String getName() { + return name; + } + + /** + * Returns the diagnostic command description. + * + * @return the diagnostic command description + */ + String getDescription() { + return description; + } + + /** + * Returns the potential impact of the diagnostic command execution + * on the Java virtual machine behavior. + * + * @return the potential impact of the diagnostic command execution + * on the Java virtual machine behavior + */ + String getImpact() { + return impact; + } + + /** + * Returns the name of the permission class required to be allowed + * to invoke the diagnostic command, or null if no permission + * is required. + * + * @return the name of the permission class name required to be allowed + * to invoke the diagnostic command, or null if no permission + * is required + */ + String getPermissionClass() { + return permissionClass; + } + + /** + * Returns the permission name required to be allowed to invoke the + * diagnostic command, or null if no permission is required. + * + * @return the permission name required to be allowed to invoke the + * diagnostic command, or null if no permission is required + */ + String getPermissionName() { + return permissionName; + } + + /** + * Returns the permission action required to be allowed to invoke the + * diagnostic command, or null if no permission is required or + * if the permission has no action specified. + * + * @return the permission action required to be allowed to invoke the + * diagnostic command, or null if no permission is required or + * if the permission has no action specified + */ + String getPermissionAction() { + return permissionAction; + } + + /** + * Returns {@code true} if the diagnostic command is enabled, + * {@code false} otherwise. The enabled/disabled + * status of a diagnostic command can evolve during + * the lifetime of the Java virtual machine. + * + * @return {@code true} if the diagnostic command is enabled, + * {@code false} otherwise + */ + boolean isEnabled() { + return enabled; + } + + /** + * Returns the list of the diagnostic command arguments description. + * If the diagnostic command has no arguments, it returns an empty list. + * + * @return a list of the diagnostic command arguments description + */ + List<DiagnosticCommandArgumentInfo> getArgumentsInfo() { + return arguments; + } + + DiagnosticCommandInfo(String name, String description, + String impact, String permissionClass, + String permissionName, String permissionAction, + boolean enabled, + List<DiagnosticCommandArgumentInfo> arguments) + { + this.name = name; + this.description = description; + this.impact = impact; + this.permissionClass = permissionClass; + this.permissionName = permissionName; + this.permissionAction = permissionAction; + this.enabled = enabled; + this.arguments = arguments; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/Flag.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +import java.util.*; +import com.sun.management.VMOption; +import com.sun.management.VMOption.Origin; +import java.security.AccessController; + +/** + * Flag class is a helper class for constructing a VMOption. + * It has the static methods for getting the Flag objects, each + * corresponds to one VMOption. + * + */ +class Flag { + private String name; + private Object value; + private Origin origin; + private boolean writeable; + private boolean external; + + Flag(String name, Object value, boolean writeable, + boolean external, Origin origin) { + this.name = name; + this.value = value == null ? "" : value ; + this.origin = origin; + this.writeable = writeable; + this.external = external; + } + + Object getValue() { + return value; + } + + boolean isWriteable() { + return writeable; + } + + boolean isExternal() { + return external; + } + + VMOption getVMOption() { + return new VMOption(name, value.toString(), writeable, origin); + } + + static Flag getFlag(String name) { + String[] names = new String[1]; + names[0] = name; + + List<Flag> flags = getFlags(names, 1); + if (flags.isEmpty()) { + return null; + } else { + // flags should have only one element + return flags.get(0); + } + } + + static List<Flag> getAllFlags() { + int numFlags = getInternalFlagCount(); + + // Get all internal flags with names = null + return getFlags(null, numFlags); + } + + private static List<Flag> getFlags(String[] names, int numFlags) { + Flag[] flags = new Flag[numFlags]; + int count = getFlags(names, flags, numFlags); + + List<Flag> result = new ArrayList<>(); + for (Flag f : flags) { + if (f != null) { + result.add(f); + } + } + return result; + } + + private static native String[] getAllFlagNames(); + // getFlags sets each element in the given flags array + // with a Flag object only if the name is valid and the + // type is supported. The flags array may contain null elements. + private static native int getFlags(String[] names, Flag[] flags, int count); + private static native int getInternalFlagCount(); + + // These set* methods are synchronized on the class object + // to avoid multiple threads updating the same flag at the same time. + static synchronized native void setLongValue(String name, long value); + static synchronized native void setDoubleValue(String name, double value); + static synchronized native void setBooleanValue(String name, boolean value); + static synchronized native void setStringValue(String name, String value); + + static { + AccessController.doPrivileged( + new java.security.PrivilegedAction<Void>() { + public Void run() { + System.loadLibrary("management"); + return null; + } + }); + initialize(); + } + private static native void initialize(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/GarbageCollectionNotifInfoCompositeData.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +import com.sun.management.GarbageCollectionNotificationInfo; +import com.sun.management.GcInfo; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.OpenDataException; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.lang.reflect.Field; +import java.util.HashMap; +import sun.management.LazyCompositeData; +import static sun.management.LazyCompositeData.getString; +import sun.management.Util; + +/** + * A CompositeData for GarbageCollectionNotificationInfo for the local management support. + * This class avoids the performance penalty paid to the + * construction of a CompositeData use in the local case. + */ +public class GarbageCollectionNotifInfoCompositeData extends LazyCompositeData { + private final GarbageCollectionNotificationInfo gcNotifInfo; + + public GarbageCollectionNotifInfoCompositeData(GarbageCollectionNotificationInfo info) { + this.gcNotifInfo = info; + } + + public GarbageCollectionNotificationInfo getGarbageCollectionNotifInfo() { + return gcNotifInfo; + } + + public static CompositeData toCompositeData(GarbageCollectionNotificationInfo info) { + GarbageCollectionNotifInfoCompositeData gcnicd = + new GarbageCollectionNotifInfoCompositeData(info); + return gcnicd.getCompositeData(); + } + + private CompositeType getCompositeTypeByBuilder() { + final GcInfoBuilder builder = AccessController.doPrivileged (new PrivilegedAction<GcInfoBuilder>() { + public GcInfoBuilder run() { + try { + Class<?> cl = Class.forName("com.sun.management.GcInfo"); + Field f = cl.getDeclaredField("builder"); + f.setAccessible(true); + return (GcInfoBuilder)f.get(gcNotifInfo.getGcInfo()); + } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + return null; + } + } + }); + CompositeType gict = null; + synchronized(compositeTypeByBuilder) { + gict = compositeTypeByBuilder.get(builder); + if(gict == null) { + OpenType<?>[] gcNotifInfoItemTypes = new OpenType<?>[] { + SimpleType.STRING, + SimpleType.STRING, + SimpleType.STRING, + builder.getGcInfoCompositeType(), + }; + try { + final String typeName = + "sun.management.GarbageCollectionNotifInfoCompositeType"; + gict = new CompositeType(typeName, + "CompositeType for GC notification info", + gcNotifInfoItemNames, + gcNotifInfoItemNames, + gcNotifInfoItemTypes); + compositeTypeByBuilder.put(builder,gict); + } catch (OpenDataException e) { + // shouldn't reach here + throw new RuntimeException(e); + } + } + } + return gict; + } + + protected CompositeData getCompositeData() { + // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH + // gcNotifInfoItemNames! + final Object[] gcNotifInfoItemValues; + gcNotifInfoItemValues = new Object[] { + gcNotifInfo.getGcName(), + gcNotifInfo.getGcAction(), + gcNotifInfo.getGcCause(), + GcInfoCompositeData.toCompositeData(gcNotifInfo.getGcInfo()) + }; + + CompositeType gict = getCompositeTypeByBuilder(); + + try { + return new CompositeDataSupport(gict, + gcNotifInfoItemNames, + gcNotifInfoItemValues); + } catch (OpenDataException e) { + // Should never reach here + throw new AssertionError(e); + } + } + + // private static MappedMXBeanType gcInfoMapType; + private static final String GC_NAME = "gcName"; + private static final String GC_ACTION = "gcAction"; + private static final String GC_CAUSE = "gcCause"; + private static final String GC_INFO = "gcInfo"; + private static final String[] gcNotifInfoItemNames = { + GC_NAME, + GC_ACTION, + GC_CAUSE, + GC_INFO + }; + private static HashMap<GcInfoBuilder,CompositeType> compositeTypeByBuilder = + new HashMap<>(); + + public static String getGcName(CompositeData cd) { + String gcname = getString(cd, GC_NAME); + if (gcname == null) { + throw new IllegalArgumentException("Invalid composite data: " + + "Attribute " + GC_NAME + " has null value"); + } + return gcname; + } + + public static String getGcAction(CompositeData cd) { + String gcaction = getString(cd, GC_ACTION); + if (gcaction == null) { + throw new IllegalArgumentException("Invalid composite data: " + + "Attribute " + GC_ACTION + " has null value"); + } + return gcaction; + } + + public static String getGcCause(CompositeData cd) { + String gccause = getString(cd, GC_CAUSE); + if (gccause == null) { + throw new IllegalArgumentException("Invalid composite data: " + + "Attribute " + GC_CAUSE + " has null value"); + } + return gccause; + } + + public static GcInfo getGcInfo(CompositeData cd) { + CompositeData gcInfoData = (CompositeData) cd.get(GC_INFO); + return GcInfo.from(gcInfoData); + } + + /** Validate if the input CompositeData has the expected + * CompositeType (i.e. contain all attributes with expected + * names and types). + */ + public static void validateCompositeData(CompositeData cd) { + if (cd == null) { + throw new NullPointerException("Null CompositeData"); + } + + if (!isTypeMatched( getBaseGcNotifInfoCompositeType(), cd.getCompositeType())) { + throw new IllegalArgumentException( + "Unexpected composite type for GarbageCollectionNotificationInfo"); + } + } + + // This is only used for validation. + private static CompositeType baseGcNotifInfoCompositeType = null; + private static synchronized CompositeType getBaseGcNotifInfoCompositeType() { + if (baseGcNotifInfoCompositeType == null) { + try { + OpenType<?>[] baseGcNotifInfoItemTypes = new OpenType<?>[] { + SimpleType.STRING, + SimpleType.STRING, + SimpleType.STRING, + GcInfoCompositeData.getBaseGcInfoCompositeType() + }; + baseGcNotifInfoCompositeType = + new CompositeType("sun.management.BaseGarbageCollectionNotifInfoCompositeType", + "CompositeType for Base GarbageCollectionNotificationInfo", + gcNotifInfoItemNames, + gcNotifInfoItemNames, + baseGcNotifInfoItemTypes); + } catch (OpenDataException e) { + // shouldn't reach here + throw new RuntimeException(e); + } + } + return baseGcNotifInfoCompositeType; + } + + private static final long serialVersionUID = -1805123446483771292L; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/GarbageCollectorExtImpl.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +import com.sun.management.GarbageCollectionNotificationInfo; +import com.sun.management.GarbageCollectorMXBean; +import com.sun.management.GcInfo; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryPoolMXBean; +import java.util.List; +import javax.management.ListenerNotFoundException; +import javax.management.MBeanNotificationInfo; +import javax.management.Notification; +import javax.management.NotificationFilter; +import javax.management.NotificationListener; +import javax.management.openmbean.CompositeData; +import sun.management.GarbageCollectorImpl; + +/** + * Implementation class for the garbage collector. + * Standard and committed hotspot-specific metrics if any. + * + * ManagementFactory.getGarbageCollectorMXBeans() returns a list + * of instances of this class. + */ +public class GarbageCollectorExtImpl extends GarbageCollectorImpl + implements GarbageCollectorMXBean { + + public GarbageCollectorExtImpl(String name) { + super(name); + } + + // The memory pools are static and won't be changed. + // TODO: If the hotspot implementation begins to have pools + // dynamically created and removed, this needs to be modified. + private String[] poolNames = null; + private synchronized String[] getAllPoolNames() { + if (poolNames == null) { + List<MemoryPoolMXBean> pools = ManagementFactory.getMemoryPoolMXBeans(); + poolNames = new String[pools.size()]; + int i = 0; + for (MemoryPoolMXBean m : pools) { + poolNames[i++] = m.getName(); + } + } + return poolNames; + } + + public GcInfo getLastGcInfo() { + GcInfo info = getGcInfoBuilder().getLastGcInfo(); + return info; + } + + private final static String notifName = + "javax.management.Notification"; + + private final static String[] gcNotifTypes = { + GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION + }; + + private MBeanNotificationInfo[] notifInfo = null; + public MBeanNotificationInfo[] getNotificationInfo() { + synchronized (this) { + if (notifInfo == null) { + notifInfo = new MBeanNotificationInfo[1]; + notifInfo[0] = new MBeanNotificationInfo(gcNotifTypes, + notifName, + "GC Notification"); + } + } + return notifInfo; + } + + private static long seqNumber = 0; + private static long getNextSeqNumber() { + return ++seqNumber; + } + + protected void createGCNotification(long timestamp, + String gcName, + String gcAction, + String gcCause, + GcInfo gcInfo) { + if (!hasListeners()) { + return; + } + Notification notif = new Notification(GarbageCollectionNotificationInfo.GARBAGE_COLLECTION_NOTIFICATION, + getObjectName(), + getNextSeqNumber(), + timestamp, + gcName); + GarbageCollectionNotificationInfo info = + new GarbageCollectionNotificationInfo(gcName, + gcAction, + gcCause, + gcInfo); + + CompositeData cd = + GarbageCollectionNotifInfoCompositeData.toCompositeData(info); + notif.setUserData(cd); + sendNotification(notif); + } + + public synchronized void addNotificationListener(NotificationListener listener, + NotificationFilter filter, + Object handback) + { + boolean before = hasListeners(); + super.addNotificationListener(listener, filter, handback); + boolean after = hasListeners(); + if (!before && after) { + setNotificationEnabled(this, true); + } + } + + public synchronized void removeNotificationListener(NotificationListener listener) + throws ListenerNotFoundException { + boolean before = hasListeners(); + super.removeNotificationListener(listener); + boolean after = hasListeners(); + + if (before && !after) { + setNotificationEnabled(this,false); + } + } + + public synchronized void removeNotificationListener(NotificationListener listener, + NotificationFilter filter, + Object handback) + throws ListenerNotFoundException + { + boolean before = hasListeners(); + super.removeNotificationListener(listener,filter,handback); + boolean after = hasListeners(); + if (before && !after) { + setNotificationEnabled(this,false); + } + } + + private GcInfoBuilder gcInfoBuilder; + // Invoked also by the VM + private synchronized GcInfoBuilder getGcInfoBuilder() { + if(gcInfoBuilder == null) { + gcInfoBuilder = new GcInfoBuilder(this, getAllPoolNames()); + } + return gcInfoBuilder; + } + + private native void setNotificationEnabled(GarbageCollectorMXBean gc, + boolean enabled); + + // Invoked by the VM + private static java.lang.management.GarbageCollectorMXBean + createGarbageCollector(String name, String type) { + + return new GarbageCollectorExtImpl(name); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/GcInfoBuilder.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.management.internal; + +import java.lang.management.GarbageCollectorMXBean; +import java.lang.management.MemoryUsage; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.SimpleType; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.OpenDataException; +import com.sun.management.GcInfo; +import sun.management.Util; + +/** + * Helper class to build composite data. + */ +public class GcInfoBuilder { + private final GarbageCollectorMXBean gc; + private final String[] poolNames; + private String[] allItemNames; + + // GC-specific composite type: + // Each GarbageCollectorMXBean may have different GC-specific attributes + // the CompositeType for the GcInfo could be different. + private CompositeType gcInfoCompositeType; + + // GC-specific items + private final int gcExtItemCount; + private final String[] gcExtItemNames; + private final String[] gcExtItemDescs; + private final char[] gcExtItemTypes; + + GcInfoBuilder(GarbageCollectorMXBean gc, String[] poolNames) { + this.gc = gc; + this.poolNames = poolNames; + this.gcExtItemCount = getNumGcExtAttributes(gc); + this.gcExtItemNames = new String[gcExtItemCount]; + this.gcExtItemDescs = new String[gcExtItemCount]; + this.gcExtItemTypes = new char[gcExtItemCount]; + + // Fill the information about extension attributes + fillGcAttributeInfo(gc, gcExtItemCount, gcExtItemNames, + gcExtItemTypes, gcExtItemDescs); + + // lazily build the CompositeType for the GcInfo + // including the GC-specific extension attributes + this.gcInfoCompositeType = null; + } + + GcInfo getLastGcInfo() { + MemoryUsage[] usageBeforeGC = new MemoryUsage[poolNames.length]; + MemoryUsage[] usageAfterGC = new MemoryUsage[poolNames.length]; + Object[] values = new Object[gcExtItemCount]; + + return getLastGcInfo0(gc, gcExtItemCount, values, gcExtItemTypes, + usageBeforeGC, usageAfterGC); + } + + public String[] getPoolNames() { + return poolNames; + } + + int getGcExtItemCount() { + return gcExtItemCount; + } + + // Returns the CompositeType for the GcInfo including + // the extension attributes + synchronized CompositeType getGcInfoCompositeType() { + if (gcInfoCompositeType != null) + return gcInfoCompositeType; + + // First, fill with the attributes in the GcInfo + String[] gcInfoItemNames = GcInfoCompositeData.getBaseGcInfoItemNames(); + OpenType<?>[] gcInfoItemTypes = GcInfoCompositeData.getBaseGcInfoItemTypes(); + int numGcInfoItems = gcInfoItemNames.length; + + int itemCount = numGcInfoItems + gcExtItemCount; + allItemNames = new String[itemCount]; + String[] allItemDescs = new String[itemCount]; + OpenType<?>[] allItemTypes = new OpenType<?>[itemCount]; + + System.arraycopy(gcInfoItemNames, 0, allItemNames, 0, numGcInfoItems); + System.arraycopy(gcInfoItemNames, 0, allItemDescs, 0, numGcInfoItems); + System.arraycopy(gcInfoItemTypes, 0, allItemTypes, 0, numGcInfoItems); + + // Then fill with the extension GC-specific attributes, if any. + if (gcExtItemCount > 0) { + fillGcAttributeInfo(gc, gcExtItemCount, gcExtItemNames, + gcExtItemTypes, gcExtItemDescs); + System.arraycopy(gcExtItemNames, 0, allItemNames, + numGcInfoItems, gcExtItemCount); + System.arraycopy(gcExtItemDescs, 0, allItemDescs, + numGcInfoItems, gcExtItemCount); + for (int i = numGcInfoItems, j = 0; j < gcExtItemCount; i++, j++) { + switch (gcExtItemTypes[j]) { + case 'Z': + allItemTypes[i] = SimpleType.BOOLEAN; + break; + case 'B': + allItemTypes[i] = SimpleType.BYTE; + break; + case 'C': + allItemTypes[i] = SimpleType.CHARACTER; + break; + case 'S': + allItemTypes[i] = SimpleType.SHORT; + break; + case 'I': + allItemTypes[i] = SimpleType.INTEGER; + break; + case 'J': + allItemTypes[i] = SimpleType.LONG; + break; + case 'F': + allItemTypes[i] = SimpleType.FLOAT; + break; + case 'D': + allItemTypes[i] = SimpleType.DOUBLE; + break; + default: + throw new AssertionError( + "Unsupported type [" + gcExtItemTypes[i] + "]"); + } + } + } + + CompositeType gict = null; + try { + final String typeName = + "sun.management." + gc.getName() + ".GcInfoCompositeType"; + + gict = new CompositeType(typeName, + "CompositeType for GC info for " + + gc.getName(), + allItemNames, + allItemDescs, + allItemTypes); + } catch (OpenDataException e) { + // shouldn't reach here + throw new RuntimeException(e); + } + gcInfoCompositeType = gict; + + return gcInfoCompositeType; + } + + synchronized String[] getItemNames() { + if (allItemNames == null) { + // initialize when forming the composite type + getGcInfoCompositeType(); + } + return allItemNames; + } + + // Retrieve information about extension attributes + private native int getNumGcExtAttributes(GarbageCollectorMXBean gc); + private native void fillGcAttributeInfo(GarbageCollectorMXBean gc, + int numAttributes, + String[] attributeNames, + char[] types, + String[] descriptions); + + /** + * Returns the last GcInfo + * + * @param gc GarbageCollectorMXBean that the gc info is associated with. + * @param numExtAtts number of extension attributes + * @param extAttValues Values of extension attributes to be filled. + * @param before Memory usage before GC to be filled. + * @param after Memory usage after GC to be filled. + */ + private native GcInfo getLastGcInfo0(GarbageCollectorMXBean gc, + int numExtAtts, + Object[] extAttValues, + char[] extAttTypes, + MemoryUsage[] before, + MemoryUsage[] after); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/GcInfoCompositeData.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,275 @@ +/* + * Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +import java.lang.management.MemoryUsage; +import java.lang.reflect.Method; +import java.lang.reflect.Field; +import java.util.Map; +import java.io.InvalidObjectException; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.TabularData; +import javax.management.openmbean.SimpleType; +import javax.management.openmbean.OpenType; +import javax.management.openmbean.OpenDataException; +import com.sun.management.GcInfo; +import java.security.AccessController; +import java.security.PrivilegedAction; +import sun.management.LazyCompositeData; +import static sun.management.LazyCompositeData.getLong; +import sun.management.MappedMXBeanType; +import sun.management.Util; + +/** + * A CompositeData for GcInfo for the local management support. + * This class avoids the performance penalty paid to the + * construction of a CompositeData use in the local case. + */ +public class GcInfoCompositeData extends LazyCompositeData { + private final GcInfo info; + private final GcInfoBuilder builder; + private final Object[] gcExtItemValues; + + public GcInfoCompositeData(GcInfo info, + GcInfoBuilder builder, + Object[] gcExtItemValues) { + this.info = info; + this.builder = builder; + this.gcExtItemValues = gcExtItemValues; + } + + public GcInfo getGcInfo() { + return info; + } + + public static CompositeData toCompositeData(final GcInfo info) { + final GcInfoBuilder builder = AccessController.doPrivileged (new PrivilegedAction<GcInfoBuilder>() { + public GcInfoBuilder run() { + try { + Class<?> cl = Class.forName("com.sun.management.GcInfo"); + Field f = cl.getDeclaredField("builder"); + f.setAccessible(true); + return (GcInfoBuilder)f.get(info); + } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + return null; + } + } + }); + final Object[] extAttr = AccessController.doPrivileged (new PrivilegedAction<Object[]>() { + public Object[] run() { + try { + Class<?> cl = Class.forName("com.sun.management.GcInfo"); + Field f = cl.getDeclaredField("extAttributes"); + f.setAccessible(true); + return (Object[])f.get(info); + } catch(ClassNotFoundException | NoSuchFieldException | IllegalAccessException e) { + return null; + } + } + }); + GcInfoCompositeData gcicd = + new GcInfoCompositeData(info,builder,extAttr); + return gcicd.getCompositeData(); + } + + protected CompositeData getCompositeData() { + // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH + // baseGcInfoItemNames! + final Object[] baseGcInfoItemValues; + + try { + baseGcInfoItemValues = new Object[] { + info.getId(), + info.getStartTime(), + info.getEndTime(), + info.getDuration(), + memoryUsageMapType.toOpenTypeData(info.getMemoryUsageBeforeGc()), + memoryUsageMapType.toOpenTypeData(info.getMemoryUsageAfterGc()), + }; + } catch (OpenDataException e) { + // Should never reach here + throw new AssertionError(e); + } + + // Get the item values for the extension attributes + final int gcExtItemCount = builder.getGcExtItemCount(); + if (gcExtItemCount == 0 && + gcExtItemValues != null && gcExtItemValues.length != 0) { + throw new AssertionError("Unexpected Gc Extension Item Values"); + } + + if (gcExtItemCount > 0 && (gcExtItemValues == null || + gcExtItemCount != gcExtItemValues.length)) { + throw new AssertionError("Unmatched Gc Extension Item Values"); + } + + Object[] values = new Object[baseGcInfoItemValues.length + + gcExtItemCount]; + System.arraycopy(baseGcInfoItemValues, 0, values, 0, + baseGcInfoItemValues.length); + + if (gcExtItemCount > 0) { + System.arraycopy(gcExtItemValues, 0, values, + baseGcInfoItemValues.length, gcExtItemCount); + } + + try { + return new CompositeDataSupport(builder.getGcInfoCompositeType(), + builder.getItemNames(), + values); + } catch (OpenDataException e) { + // Should never reach here + throw new AssertionError(e); + } + } + + private static final String ID = "id"; + private static final String START_TIME = "startTime"; + private static final String END_TIME = "endTime"; + private static final String DURATION = "duration"; + private static final String MEMORY_USAGE_BEFORE_GC = "memoryUsageBeforeGc"; + private static final String MEMORY_USAGE_AFTER_GC = "memoryUsageAfterGc"; + + private static final String[] baseGcInfoItemNames = { + ID, + START_TIME, + END_TIME, + DURATION, + MEMORY_USAGE_BEFORE_GC, + MEMORY_USAGE_AFTER_GC, + }; + + + private static MappedMXBeanType memoryUsageMapType; + static { + try { + Method m = GcInfo.class.getMethod("getMemoryUsageBeforeGc"); + memoryUsageMapType = + MappedMXBeanType.getMappedType(m.getGenericReturnType()); + } catch (NoSuchMethodException | OpenDataException e) { + // Should never reach here + throw new AssertionError(e); + } + } + + static String[] getBaseGcInfoItemNames() { + return baseGcInfoItemNames; + } + + private static OpenType<?>[] baseGcInfoItemTypes = null; + static synchronized OpenType<?>[] getBaseGcInfoItemTypes() { + if (baseGcInfoItemTypes == null) { + OpenType<?> memoryUsageOpenType = memoryUsageMapType.getOpenType(); + baseGcInfoItemTypes = new OpenType<?>[] { + SimpleType.LONG, + SimpleType.LONG, + SimpleType.LONG, + SimpleType.LONG, + + memoryUsageOpenType, + memoryUsageOpenType, + }; + } + return baseGcInfoItemTypes; + } + + public static long getId(CompositeData cd) { + return getLong(cd, ID); + } + public static long getStartTime(CompositeData cd) { + return getLong(cd, START_TIME); + } + public static long getEndTime(CompositeData cd) { + return getLong(cd, END_TIME); + } + + public static Map<String, MemoryUsage> + getMemoryUsageBeforeGc(CompositeData cd) { + try { + TabularData td = (TabularData) cd.get(MEMORY_USAGE_BEFORE_GC); + return cast(memoryUsageMapType.toJavaTypeData(td)); + } catch (InvalidObjectException | OpenDataException e) { + // Should never reach here + throw new AssertionError(e); + } + } + + @SuppressWarnings("unchecked") + public static Map<String, MemoryUsage> cast(Object x) { + return (Map<String, MemoryUsage>) x; + } + public static Map<String, MemoryUsage> + getMemoryUsageAfterGc(CompositeData cd) { + try { + TabularData td = (TabularData) cd.get(MEMORY_USAGE_AFTER_GC); + //return (Map<String,MemoryUsage>) + return cast(memoryUsageMapType.toJavaTypeData(td)); + } catch (InvalidObjectException | OpenDataException e) { + // Should never reach here + throw new AssertionError(e); + } + } + + /** + * Returns true if the input CompositeData has the expected + * CompositeType (i.e. contain all attributes with expected + * names and types). Otherwise, return false. + */ + public static void validateCompositeData(CompositeData cd) { + if (cd == null) { + throw new NullPointerException("Null CompositeData"); + } + + if (!isTypeMatched(getBaseGcInfoCompositeType(), + cd.getCompositeType())) { + throw new IllegalArgumentException( + "Unexpected composite type for GcInfo"); + } + } + + // This is only used for validation. + private static CompositeType baseGcInfoCompositeType = null; + static synchronized CompositeType getBaseGcInfoCompositeType() { + if (baseGcInfoCompositeType == null) { + try { + baseGcInfoCompositeType = + new CompositeType("sun.management.BaseGcInfoCompositeType", + "CompositeType for Base GcInfo", + getBaseGcInfoItemNames(), + getBaseGcInfoItemNames(), + getBaseGcInfoItemTypes()); + } catch (OpenDataException e) { + // shouldn't reach here + throw new RuntimeException(e); + } + } + return baseGcInfoCompositeType; + } + + private static final long serialVersionUID = -5716428894085882742L; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/HotSpotDiagnostic.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import javax.management.ObjectName; + +import com.sun.management.HotSpotDiagnosticMXBean; +import com.sun.management.VMOption; +import sun.management.Util; + +/** + * Implementation of the diagnostic MBean for Hotspot VM. + */ +public class HotSpotDiagnostic implements HotSpotDiagnosticMXBean { + public HotSpotDiagnostic() { + } + + @Override + public void dumpHeap(String outputFile, boolean live) throws IOException { + SecurityManager security = System.getSecurityManager(); + if (security != null) { + security.checkWrite(outputFile); + Util.checkControlAccess(); + } + + dumpHeap0(outputFile, live); + } + + private native void dumpHeap0(String outputFile, boolean live) throws IOException; + + @Override + public List<VMOption> getDiagnosticOptions() { + List<Flag> allFlags = Flag.getAllFlags(); + List<VMOption> result = new ArrayList<>(); + for (Flag flag : allFlags) { + if (flag.isWriteable() && flag.isExternal()) { + result.add(flag.getVMOption()); + } + } + return result; + } + + @Override + public VMOption getVMOption(String name) { + if (name == null) { + throw new NullPointerException("name cannot be null"); + } + + Flag f = Flag.getFlag(name); + if (f == null) { + throw new IllegalArgumentException("VM option \"" + + name + "\" does not exist"); + } + return f.getVMOption(); + } + + @Override + public void setVMOption(String name, String value) { + if (name == null) { + throw new NullPointerException("name cannot be null"); + } + if (value == null) { + throw new NullPointerException("value cannot be null"); + } + + Util.checkControlAccess(); + Flag flag = Flag.getFlag(name); + if (flag == null) { + throw new IllegalArgumentException("VM option \"" + + name + "\" does not exist"); + } + if (!flag.isWriteable()){ + throw new IllegalArgumentException("VM Option \"" + + name + "\" is not writeable"); + } + + // Check the type of the value + Object v = flag.getValue(); + if (v instanceof Long) { + try { + long l = Long.parseLong(value); + Flag.setLongValue(name, l); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid value:" + + " VM Option \"" + name + "\"" + + " expects numeric value", e); + } + } else if (v instanceof Double) { + try { + double d = Double.parseDouble(value); + Flag.setDoubleValue(name, d); + } catch (NumberFormatException e) { + throw new IllegalArgumentException("Invalid value:" + + " VM Option \"" + name + "\"" + + " expects numeric value", e); + } + } else if (v instanceof Boolean) { + if (!value.equalsIgnoreCase("true") && + !value.equalsIgnoreCase("false")) { + throw new IllegalArgumentException("Invalid value:" + + " VM Option \"" + name + "\"" + + " expects \"true\" or \"false\"."); + } + Flag.setBooleanValue(name, Boolean.parseBoolean(value)); + } else if (v instanceof String) { + Flag.setStringValue(name, value); + } else { + throw new IllegalArgumentException("VM Option \"" + + name + "\" is of an unsupported type: " + + v.getClass().getName()); + } + } + + @Override + public ObjectName getObjectName() { + return Util.newObjectName("com.sun.management:type=HotSpotDiagnostic"); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/HotSpotThreadImpl.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.management.internal; + +import com.sun.management.ThreadMXBean; +import sun.management.ManagementFactoryHelper; +import sun.management.ThreadImpl; +import sun.management.VMManagement; + +/** + * + */ +public class HotSpotThreadImpl extends ThreadImpl implements ThreadMXBean { + public HotSpotThreadImpl(VMManagement vm) { + super(ManagementFactoryHelper.getVMManagement()); + } + + @Override + public boolean isThreadAllocatedMemorySupported() { + return super.isThreadAllocatedMemorySupported(); + } + + @Override + public boolean isThreadAllocatedMemoryEnabled() { + return super.isThreadAllocatedMemoryEnabled(); + } + + @Override + public long[] getThreadCpuTime(long[] ids) { + return super.getThreadCpuTime(ids); + } + + @Override + public long[] getThreadUserTime(long[] ids) { + return super.getThreadUserTime(ids); + } + + @Override + public long getThreadAllocatedBytes(long id) { + return super.getThreadAllocatedBytes(id); + } + + @Override + public long[] getThreadAllocatedBytes(long[] ids) { + return super.getThreadAllocatedBytes(ids); + } + + @Override + public void setThreadAllocatedMemoryEnabled(boolean enable) { + super.setThreadAllocatedMemoryEnabled(enable); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,285 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.sun.management.internal; + +import com.sun.management.DiagnosticCommandMBean; +import com.sun.management.HotSpotDiagnosticMXBean; +import com.sun.management.ThreadMXBean; +import java.lang.management.ManagementFactory; +import java.lang.management.MemoryManagerMXBean; +import java.lang.management.OperatingSystemMXBean; +import java.security.AccessController; +import java.security.PrivilegedAction; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; +import javax.management.DynamicMBean; +import sun.management.ManagementFactoryHelper; +import sun.management.spi.PlatformMBeanProvider; + +public final class PlatformMBeanProviderImpl extends PlatformMBeanProvider { + final static String DIAGNOSTIC_COMMAND_MBEAN_NAME = + "com.sun.management:type=DiagnosticCommand"; + + private final List<PlatformComponent<?>> mxbeanList; + private static HotSpotDiagnostic hsDiagMBean = null; + private static OperatingSystemMXBean osMBean = null; + + static { + AccessController.doPrivileged((PrivilegedAction<Void>) () -> { + System.loadLibrary("management_ext"); + return null; + }); + } + + public PlatformMBeanProviderImpl() { + mxbeanList = Collections.unmodifiableList(init()); + } + + @Override + public List<PlatformComponent<?>> getPlatformComponentList() { + return mxbeanList; + } + + private List<PlatformComponent<?>> init() { + ArrayList<PlatformComponent<?>> initMBeanList = new ArrayList<>(); + /** + * Garbage Collector in the Java virtual machine. + */ + initMBeanList.add(new PlatformComponent<MemoryManagerMXBean>() { + private final Set<String> garbageCollectorMXBeanInterfaceNames + = Collections.unmodifiableSet( + Stream.of("java.lang.management.MemoryManagerMXBean", + "java.lang.management.GarbageCollectorMXBean", + "com.sun.management.GarbageCollectorMXBean") + .collect(Collectors.toSet())); + + @Override + public Set<Class<? extends MemoryManagerMXBean>> mbeanInterfaces() { + return Stream.of(MemoryManagerMXBean.class, + java.lang.management.GarbageCollectorMXBean.class, + com.sun.management.GarbageCollectorMXBean.class) + .collect(Collectors.toSet()); + } + + @Override + public Set<String> mbeanInterfaceNames() { + return garbageCollectorMXBeanInterfaceNames; + } + + @Override + public String getObjectNamePattern() { + return ManagementFactory.GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE + ",name=*"; + } + + @Override + public boolean isSingleton() { + return false; // zero or more instances + } + + @Override + public Map<String, MemoryManagerMXBean> nameToMBeanMap() { + List<java.lang.management.GarbageCollectorMXBean> list + = ManagementFactoryHelper.getGarbageCollectorMXBeans(); + Map<String, MemoryManagerMXBean> map; + if (list.isEmpty()) { + map = Collections.emptyMap(); + } else { + map = new HashMap<>(list.size()); + for (MemoryManagerMXBean gcm : list) { + map.put(gcm.getObjectName().getCanonicalName(), + gcm); + } + } + + return map; + } + }); + + /** + * Threading system of the Java virtual machine. + */ + initMBeanList.add(new PlatformComponent<java.lang.management.ThreadMXBean>() { + private final Set<String> threadMXBeanInterfaceNames + = Collections.unmodifiableSet( + Stream.of("java.lang.management.ThreadMXBean", + "com.sun.management.ThreadMXBean") + .collect(Collectors.toSet())); + private ThreadMXBean threadMBean = null; + + @Override + public Set<Class<? extends java.lang.management.ThreadMXBean>> mbeanInterfaces() { + return Stream.of(java.lang.management.ThreadMXBean.class, + com.sun.management.ThreadMXBean.class) + .collect(Collectors.toSet()); + } + + @Override + public Set<String> mbeanInterfaceNames() { + return threadMXBeanInterfaceNames; + } + + @Override + public String getObjectNamePattern() { + return ManagementFactory.THREAD_MXBEAN_NAME; + } + + @Override + public synchronized Map<String, java.lang.management.ThreadMXBean> nameToMBeanMap() { + if (threadMBean == null) { + threadMBean = new HotSpotThreadImpl(ManagementFactoryHelper.getVMManagement()); + } + return Collections.singletonMap( + ManagementFactory.THREAD_MXBEAN_NAME, + threadMBean); + } + }); + + /** + * OperatingSystemMXBean + */ + initMBeanList.add(new PlatformComponent<OperatingSystemMXBean>() { + private final Set<String> operatingSystemMXBeanInterfaceNames + = Collections.unmodifiableSet( + Stream.of("java.lang.management.OperatingSystemMXBean", + "com.sun.management.OperatingSystemMXBean", + "com.sun.management.UnixOperatingSystemMXBean") + .collect(Collectors.toSet())); + + @Override + public Set<Class<? extends OperatingSystemMXBean>> mbeanInterfaces() { + return Stream.of(java.lang.management.OperatingSystemMXBean.class, + com.sun.management.OperatingSystemMXBean.class, + com.sun.management.UnixOperatingSystemMXBean.class) + .collect(Collectors.toSet()); + } + + @Override + public Set<String> mbeanInterfaceNames() { + return operatingSystemMXBeanInterfaceNames; + } + + @Override + public String getObjectNamePattern() { + return ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME; + } + + @Override + public Map<String, java.lang.management.OperatingSystemMXBean> nameToMBeanMap() { + return Collections.<String, java.lang.management.OperatingSystemMXBean>singletonMap( + ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, + getOperatingSystemMXBean()); + } + }); + + /** + * Diagnostic support for the HotSpot Virtual Machine. + */ + initMBeanList.add(new PlatformComponent<com.sun.management.HotSpotDiagnosticMXBean>() { + private final Set<String> hotSpotDiagnosticMXBeanInterfaceNames = + Collections.unmodifiableSet(Collections.<String>singleton( + "com.sun.management.HotSpotDiagnosticMXBean")); + + @Override + public Set<Class<? extends com.sun.management.HotSpotDiagnosticMXBean>> mbeanInterfaces() { + return Collections.singleton(com.sun.management.HotSpotDiagnosticMXBean.class); + } + + @Override + public Set<String> mbeanInterfaceNames() { + return hotSpotDiagnosticMXBeanInterfaceNames; + } + + @Override + public String getObjectNamePattern() { + return "com.sun.management:type=HotSpotDiagnostic"; + } + + @Override + public Map<String, com.sun.management.HotSpotDiagnosticMXBean> nameToMBeanMap() { + return Collections.<String, com.sun.management.HotSpotDiagnosticMXBean>singletonMap( + "com.sun.management:type=HotSpotDiagnostic", + getDiagnosticMXBean()); + } + }); + + /** + * Diagnostic command MBean + */ + DiagnosticCommandMBean diagMBean = DiagnosticCommandImpl.getDiagnosticCommandMBean(); + if (diagMBean != null) { + initMBeanList.add(new PlatformComponent<DynamicMBean>() { + final Set<String> dynamicMBeanInterfaceNames + = Collections.unmodifiableSet(Collections.<String>singleton( + "javax.management.DynamicMBean")); + + @Override + public Set<String> mbeanInterfaceNames() { + return dynamicMBeanInterfaceNames; + } + + @Override + public Set<Class<? extends DynamicMBean>> mbeanInterfaces() { + // DynamicMBean cannot be used to find an MBean by ManagementFactory + return Collections.emptySet(); + } + + @Override + public String getObjectNamePattern() { + return DIAGNOSTIC_COMMAND_MBEAN_NAME; + } + + @Override + public Map<String, DynamicMBean> nameToMBeanMap() { + return Collections.<String, DynamicMBean>singletonMap( + DIAGNOSTIC_COMMAND_MBEAN_NAME, + diagMBean); + } + }); + } + + initMBeanList.trimToSize(); + return initMBeanList; + } + + private static synchronized HotSpotDiagnosticMXBean getDiagnosticMXBean() { + if (hsDiagMBean == null) { + hsDiagMBean = new HotSpotDiagnostic(); + } + return hsDiagMBean; + } + + private static synchronized OperatingSystemMXBean getOperatingSystemMXBean() { + if (osMBean == null) { + osMBean = new OperatingSystemImpl(ManagementFactoryHelper.getVMManagement()); + } + return osMBean; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/internal/VMOptionCompositeData.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +import com.sun.management.VMOption; +import com.sun.management.VMOption.Origin; +import javax.management.openmbean.CompositeType; +import javax.management.openmbean.CompositeData; +import javax.management.openmbean.CompositeDataSupport; +import javax.management.openmbean.OpenDataException; +import sun.management.LazyCompositeData; +import sun.management.MappedMXBeanType; + +/** + * A CompositeData for VMOption for the local management support. + * This class avoids the performance penalty paid to the + * construction of a CompositeData use in the local case. + */ +public class VMOptionCompositeData extends LazyCompositeData { + private final VMOption option; + + private VMOptionCompositeData(VMOption option) { + this.option = option; + } + + public VMOption getVMOption() { + return option; + } + + public static CompositeData toCompositeData(VMOption option) { + VMOptionCompositeData vcd = new VMOptionCompositeData(option); + return vcd.getCompositeData(); + } + + protected CompositeData getCompositeData() { + // CONTENTS OF THIS ARRAY MUST BE SYNCHRONIZED WITH + // vmOptionItemNames! + final Object[] vmOptionItemValues = { + option.getName(), + option.getValue(), + option.isWriteable(), + option.getOrigin().toString(), + }; + + try { + return new CompositeDataSupport(vmOptionCompositeType, + vmOptionItemNames, + vmOptionItemValues); + } catch (OpenDataException e) { + // Should never reach here + throw new AssertionError(e); + } + } + + private static final CompositeType vmOptionCompositeType; + static { + try { + vmOptionCompositeType = (CompositeType) + MappedMXBeanType.toOpenType(VMOption.class); + } catch (OpenDataException e) { + // Should never reach here + throw new AssertionError(e); + } + } + + static CompositeType getVMOptionCompositeType() { + return vmOptionCompositeType; + } + + private static final String NAME = "name"; + private static final String VALUE = "value"; + private static final String WRITEABLE = "writeable"; + private static final String ORIGIN = "origin"; + + private static final String[] vmOptionItemNames = { + NAME, + VALUE, + WRITEABLE, + ORIGIN, + }; + + public static String getName(CompositeData cd) { + return getString(cd, NAME); + } + public static String getValue(CompositeData cd) { + return getString(cd, VALUE); + } + public static Origin getOrigin(CompositeData cd) { + String o = getString(cd, ORIGIN); + return Enum.valueOf(Origin.class, o); + } + public static boolean isWriteable(CompositeData cd) { + return getBoolean(cd, WRITEABLE); + } + + /** Validate if the input CompositeData has the expected + * CompositeType (i.e. contain all attributes with expected + * names and types). + */ + public static void validateCompositeData(CompositeData cd) { + if (cd == null) { + throw new NullPointerException("Null CompositeData"); + } + + if (!isTypeMatched(vmOptionCompositeType, cd.getCompositeType())) { + throw new IllegalArgumentException( + "Unexpected composite type for VMOption"); + } + } + + private static final long serialVersionUID = -2395573975093578470L; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/classes/com/sun/management/package-info.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/** + * This package contains Oracle Corporation's platform extension to + * the implementation of the + * <a href="{@docRoot}/../../../../api/java/lang/management/package-summary.html"> + * java.lang.management</a> API and also defines the management + * interface for some other components for the platform. + * + * <p> + * All platform MBeans are registered in the <em>platform MBeanServer</em> + * which can be obtained via the + * <a href="{@docRoot}/../../../../api/java/lang/management/ManagementFactory.html#getPlatformMBeanServer()"> + * java.lang.management.ManagementFactory.getPlatformMBeanServer</a> + * + * @author Mandy Chung + * @since 1.5 + */ + +@jdk.Exported +package com.sun.management;
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/native/libmanagement_ext/DiagnosticCommandImpl.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <stdlib.h> +#include <jni.h> +#include "management_ext.h" +#include "com_sun_management_internal_DiagnosticCommandImpl.h" + +JNIEXPORT void JNICALL Java_com_sun_management_internal_DiagnosticCommandImpl_setNotificationEnabled +(JNIEnv *env, jobject dummy, jboolean enabled) { + if (jmm_version <= JMM_VERSION_1_2_2) { + JNU_ThrowByName(env, "java/lang/UnsupportedOperationException", + "JMX interface to diagnostic framework notifications is not supported by this VM"); + return; + } + jmm_interface->SetDiagnosticFrameworkNotificationEnabled(env, enabled); +} + +JNIEXPORT jobjectArray JNICALL +Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommands + (JNIEnv *env, jobject dummy) +{ + return jmm_interface->GetDiagnosticCommands(env); +} + +jobject getDiagnosticCommandArgumentInfoArray(JNIEnv *env, jstring command, + int num_arg) { + int i; + jobject obj; + jobjectArray result; + dcmdArgInfo* dcmd_arg_info_array; + jclass dcmdArgInfoCls; + jclass arraysCls; + jmethodID mid; + jobject resultList; + + dcmd_arg_info_array = (dcmdArgInfo*) malloc(num_arg * sizeof(dcmdArgInfo)); + /* According to ISO C it is perfectly legal for malloc to return zero if called with a zero argument */ + if (dcmd_arg_info_array == NULL && num_arg != 0) { + return NULL; + } + jmm_interface->GetDiagnosticCommandArgumentsInfo(env, command, + dcmd_arg_info_array); + dcmdArgInfoCls = (*env)->FindClass(env, + "com/sun/management/internal/DiagnosticCommandArgumentInfo"); + if ((*env)->ExceptionCheck(env)) { + free(dcmd_arg_info_array); + return NULL; + } + + result = (*env)->NewObjectArray(env, num_arg, dcmdArgInfoCls, NULL); + if (result == NULL) { + free(dcmd_arg_info_array); + return NULL; + } + for (i=0; i<num_arg; i++) { + obj = JNU_NewObjectByName(env, + "com/sun/management/internal/DiagnosticCommandArgumentInfo", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZZI)V", + (*env)->NewStringUTF(env,dcmd_arg_info_array[i].name), + (*env)->NewStringUTF(env,dcmd_arg_info_array[i].description), + (*env)->NewStringUTF(env,dcmd_arg_info_array[i].type), + dcmd_arg_info_array[i].default_string == NULL ? NULL: + (*env)->NewStringUTF(env, dcmd_arg_info_array[i].default_string), + dcmd_arg_info_array[i].mandatory, + dcmd_arg_info_array[i].option, + dcmd_arg_info_array[i].multiple, + dcmd_arg_info_array[i].position); + if (obj == NULL) { + free(dcmd_arg_info_array); + return NULL; + } + (*env)->SetObjectArrayElement(env, result, i, obj); + } + free(dcmd_arg_info_array); + arraysCls = (*env)->FindClass(env, "java/util/Arrays"); + if ((*env)->ExceptionCheck(env)) { + return NULL; + } + mid = (*env)->GetStaticMethodID(env, arraysCls, + "asList", "([Ljava/lang/Object;)Ljava/util/List;"); + resultList = (*env)->CallStaticObjectMethod(env, arraysCls, mid, result); + if ((*env)->ExceptionCheck(env)) { + // Make sure we return NULL in case of OOM inside Java + return NULL; + } + return resultList; +} + +/* Throws IllegalArgumentException if at least one of the diagnostic command + * passed in argument is not supported by the JVM + */ +JNIEXPORT jobjectArray JNICALL +Java_com_sun_management_internal_DiagnosticCommandImpl_getDiagnosticCommandInfo +(JNIEnv *env, jobject dummy, jobjectArray commands) +{ + int i; + jclass dcmdInfoCls; + jobject result; + jobjectArray args; + jobject obj; + jmmOptionalSupport mos; + jint ret = jmm_interface->GetOptionalSupport(env, &mos); + jsize num_commands; + dcmdInfo* dcmd_info_array; + + if (commands == NULL) { + JNU_ThrowNullPointerException(env, "Invalid String Array"); + return NULL; + } + num_commands = (*env)->GetArrayLength(env, commands); + dcmdInfoCls = (*env)->FindClass(env, + "com/sun/management/internal/DiagnosticCommandInfo"); + if ((*env)->ExceptionCheck(env)) { + return NULL; + } + + result = (*env)->NewObjectArray(env, num_commands, dcmdInfoCls, NULL); + if (result == NULL) { + JNU_ThrowOutOfMemoryError(env, 0); + return NULL; + } + if (num_commands == 0) { + /* Handle the 'zero commands' case specially to avoid calling 'malloc()' */ + /* with a zero argument because that may legally return a NULL pointer. */ + return result; + } + dcmd_info_array = (dcmdInfo*) malloc(num_commands * sizeof(dcmdInfo)); + if (dcmd_info_array == NULL) { + JNU_ThrowOutOfMemoryError(env, NULL); + return NULL; + } + jmm_interface->GetDiagnosticCommandInfo(env, commands, dcmd_info_array); + for (i=0; i<num_commands; i++) { + args = getDiagnosticCommandArgumentInfoArray(env, + (*env)->GetObjectArrayElement(env,commands,i), + dcmd_info_array[i].num_arguments); + if (args == NULL) { + free(dcmd_info_array); + JNU_ThrowOutOfMemoryError(env, 0); + return NULL; + } + obj = JNU_NewObjectByName(env, + "com/sun/management/internal/DiagnosticCommandInfo", + "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZLjava/util/List;)V", + (*env)->NewStringUTF(env,dcmd_info_array[i].name), + (*env)->NewStringUTF(env,dcmd_info_array[i].description), + (*env)->NewStringUTF(env,dcmd_info_array[i].impact), + dcmd_info_array[i].permission_class==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_class), + dcmd_info_array[i].permission_name==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_name), + dcmd_info_array[i].permission_action==NULL?NULL:(*env)->NewStringUTF(env,dcmd_info_array[i].permission_action), + dcmd_info_array[i].enabled, + args); + if (obj == NULL) { + free(dcmd_info_array); + JNU_ThrowOutOfMemoryError(env, 0); + return NULL; + } + (*env)->SetObjectArrayElement(env, result, i, obj); + } + free(dcmd_info_array); + return result; +} + +/* Throws IllegalArgumentException if the diagnostic command + * passed in argument is not supported by the JVM + */ +JNIEXPORT jstring JNICALL +Java_com_sun_management_internal_DiagnosticCommandImpl_executeDiagnosticCommand +(JNIEnv *env, jobject dummy, jstring command) { + return jmm_interface->ExecuteDiagnosticCommand(env, command); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/native/libmanagement_ext/Flag.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <jni.h> +#include "management_ext.h" +#include "com_sun_management_internal_Flag.h" + +static jobject default_origin = NULL; +static jobject vm_creation_origin = NULL; +static jobject mgmt_origin = NULL; +static jobject envvar_origin = NULL; +static jobject config_file_origin = NULL; +static jobject ergo_origin = NULL; +static jobject attach_origin = NULL; +static jobject other_origin = NULL; + +JNIEXPORT jint JNICALL +Java_com_sun_management_internal_Flag_getInternalFlagCount + (JNIEnv *env, jclass cls) +{ + jlong count = jmm_interface->GetLongAttribute(env, NULL, + JMM_VM_GLOBAL_COUNT); + return (jint) count; +} + +JNIEXPORT jobjectArray JNICALL + Java_com_sun_management_internal_Flag_getAllFlagNames +(JNIEnv *env, jclass cls) +{ + return jmm_interface->GetVMGlobalNames(env); +} + +static jobject find_origin_constant(JNIEnv* env, const char* enum_name) { + jvalue field; + field = JNU_GetStaticFieldByName(env, + NULL, + "com/sun/management/VMOption$Origin", + enum_name, + "Lcom/sun/management/VMOption$Origin;"); + return (*env)->NewGlobalRef(env, field.l); +} + +JNIEXPORT void JNICALL +Java_com_sun_management_internal_Flag_initialize + (JNIEnv *env, jclass cls) +{ + default_origin = find_origin_constant(env, "DEFAULT"); + vm_creation_origin = find_origin_constant(env, "VM_CREATION"); + mgmt_origin = find_origin_constant(env, "MANAGEMENT"); + envvar_origin = find_origin_constant(env, "ENVIRON_VAR"); + config_file_origin = find_origin_constant(env, "CONFIG_FILE"); + ergo_origin = find_origin_constant(env, "ERGONOMIC"); + attach_origin = find_origin_constant(env, "ATTACH_ON_DEMAND"); + other_origin = find_origin_constant(env, "OTHER"); +} + +JNIEXPORT jint JNICALL +Java_com_sun_management_internal_Flag_getFlags + (JNIEnv *env, jclass cls, jobjectArray names, jobjectArray flags, jint count) +{ + jint num_flags, i, index; + jmmVMGlobal* globals; + size_t gsize; + const char* class_name = "com/sun/management/internal/Flag"; + const char* signature = "(Ljava/lang/String;Ljava/lang/Object;ZZLcom/sun/management/VMOption$Origin;)V"; + jobject origin; + jobject valueObj; + jobject flag; + + if (flags == NULL) { + JNU_ThrowNullPointerException(env, 0); + return 0; + } + + if (count <= 0) { + JNU_ThrowIllegalArgumentException(env, 0); + return 0; + } + + gsize = (size_t)count * sizeof(jmmVMGlobal); + globals = (jmmVMGlobal*) malloc(gsize); + if (globals == NULL) { + JNU_ThrowOutOfMemoryError(env, 0); + return 0; + } + + memset(globals, 0, gsize); + num_flags = jmm_interface->GetVMGlobals(env, names, globals, count); + if (num_flags == 0) { + free(globals); + return 0; + } + + index = 0; + for (i = 0; i < count; i++) { + if (globals[i].name == NULL) { + continue; + } + switch (globals[i].type) { + case JMM_VMGLOBAL_TYPE_JBOOLEAN: + valueObj = JNU_NewObjectByName(env, "java/lang/Boolean", "(Z)V", + globals[i].value.z); + break; + case JMM_VMGLOBAL_TYPE_JSTRING: + valueObj = globals[i].value.l; + break; + case JMM_VMGLOBAL_TYPE_JLONG: + valueObj = JNU_NewObjectByName(env, "java/lang/Long", "(J)V", + globals[i].value.j); + break; + case JMM_VMGLOBAL_TYPE_JDOUBLE: + valueObj = JNU_NewObjectByName(env, "java/lang/Double", "(D)V", + globals[i].value.d); + break; + default: + // ignore unsupported type + continue; + } + switch (globals[i].origin) { + case JMM_VMGLOBAL_ORIGIN_DEFAULT: + origin = default_origin; + break; + case JMM_VMGLOBAL_ORIGIN_COMMAND_LINE: + origin = vm_creation_origin; + break; + case JMM_VMGLOBAL_ORIGIN_MANAGEMENT: + origin = mgmt_origin; + break; + case JMM_VMGLOBAL_ORIGIN_ENVIRON_VAR: + origin = envvar_origin; + break; + case JMM_VMGLOBAL_ORIGIN_CONFIG_FILE: + origin = config_file_origin; + break; + case JMM_VMGLOBAL_ORIGIN_ERGONOMIC: + origin = ergo_origin; + break; + case JMM_VMGLOBAL_ORIGIN_ATTACH_ON_DEMAND: + origin = attach_origin; + break; + case JMM_VMGLOBAL_ORIGIN_OTHER: + origin = other_origin; + break; + default: + // unknown origin + origin = other_origin; + break; + } + flag = JNU_NewObjectByName(env, class_name, signature, globals[i].name, + valueObj, globals[i].writeable, + globals[i].external, origin); + if (flag == NULL) { + free(globals); + JNU_ThrowOutOfMemoryError(env, 0); + return 0; + } + (*env)->SetObjectArrayElement(env, flags, index, flag); + index++; + } + + if (index != num_flags) { + JNU_ThrowInternalError(env, "Number of Flag objects created unmatched"); + free(globals); + return 0; + } + + free(globals); + + /* return the number of Flag objects created */ + return num_flags; +} + +JNIEXPORT void JNICALL +Java_com_sun_management_internal_Flag_setLongValue + (JNIEnv *env, jclass cls, jstring name, jlong value) +{ + jvalue v; + v.j = value; + + jmm_interface->SetVMGlobal(env, name, v); +} + +JNIEXPORT void JNICALL +Java_com_sun_management_internal_Flag_setDoubleValue + (JNIEnv *env, jclass cls, jstring name, jdouble value) +{ + jvalue v; + v.d = value; + + jmm_interface->SetVMGlobal(env, name, v); +} + +JNIEXPORT void JNICALL +Java_com_sun_management_internal_Flag_setBooleanValue + (JNIEnv *env, jclass cls, jstring name, jboolean value) +{ + jvalue v; + v.z = value; + + jmm_interface->SetVMGlobal(env, name, v); +} + +JNIEXPORT void JNICALL +Java_com_sun_management_internal_Flag_setStringValue + (JNIEnv *env, jclass cls, jstring name, jstring value) +{ + jvalue v; + v.l = value; + + jmm_interface->SetVMGlobal(env, name, v); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/native/libmanagement_ext/GarbageCollectorExtImpl.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <jni.h> +#include "management_ext.h" +#include "com_sun_management_internal_GarbageCollectorExtImpl.h" + +JNIEXPORT void JNICALL Java_com_sun_management_internal_GarbageCollectorExtImpl_setNotificationEnabled +(JNIEnv *env, jobject dummy, jobject gc,jboolean enabled) { + + if (gc == NULL) { + JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); + return; + } + if((jmm_version > JMM_VERSION_1_2) + || (jmm_version == JMM_VERSION_1_2 && ((jmm_version&0xFF)>=1))) { + jmm_interface->SetGCNotificationEnabled(env, gc, enabled); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/native/libmanagement_ext/GcInfoBuilder.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <stdlib.h> +#include <stdio.h> +#include <jni.h> +#include "management_ext.h" +#include "com_sun_management_internal_GcInfoBuilder.h" + +JNIEXPORT jint JNICALL Java_com_sun_management_internal_GcInfoBuilder_getNumGcExtAttributes + (JNIEnv *env, jobject dummy, jobject gc) { + jlong value; + + if (gc == NULL) { + JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); + return 0; + } + value = jmm_interface->GetLongAttribute(env, gc, + JMM_GC_EXT_ATTRIBUTE_INFO_SIZE); + return (jint) value; +} + +JNIEXPORT void JNICALL Java_com_sun_management_internal_GcInfoBuilder_fillGcAttributeInfo + (JNIEnv *env, jobject dummy, jobject gc, + jint num_attributes, jobjectArray attributeNames, + jcharArray types, jobjectArray descriptions) { + + jmmExtAttributeInfo* ext_att_info; + jchar* nativeTypes; + jstring attName = NULL; + jstring desc = NULL; + jint ret = 0; + jint i; + + if (gc == NULL) { + JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); + return; + } + + if (num_attributes <= 0) { + JNU_ThrowIllegalArgumentException(env, "Invalid num_attributes"); + return; + } + + ext_att_info = (jmmExtAttributeInfo*) malloc((size_t)num_attributes * + sizeof(jmmExtAttributeInfo)); + if (ext_att_info == NULL) { + JNU_ThrowOutOfMemoryError(env, 0); + return; + } + ret = jmm_interface->GetGCExtAttributeInfo(env, gc, + ext_att_info, num_attributes); + if (ret != num_attributes) { + JNU_ThrowInternalError(env, "Unexpected num_attributes"); + free(ext_att_info); + return; + } + + nativeTypes = (jchar*) malloc((size_t)num_attributes * sizeof(jchar)); + if (nativeTypes == NULL) { + free(ext_att_info); + JNU_ThrowOutOfMemoryError(env, 0); + return; + } + for (i = 0; i < num_attributes; i++) { + nativeTypes[i] = ext_att_info[i].type; + attName = (*env)->NewStringUTF(env, ext_att_info[i].name); + desc = (*env)->NewStringUTF(env, ext_att_info[i].description); + (*env)->SetObjectArrayElement(env, attributeNames, i, attName); + (*env)->SetObjectArrayElement(env, descriptions, i, desc); + } + (*env)->SetCharArrayRegion(env, types, 0, num_attributes, nativeTypes); + + if (ext_att_info != NULL) { + free(ext_att_info); + } + if (nativeTypes != NULL) { + free(nativeTypes); + } +} + +static void setLongValueAtObjectArray(JNIEnv *env, jobjectArray array, + jsize index, jlong value) { + static const char* class_name = "java/lang/Long"; + static const char* signature = "(J)V"; + jobject obj = JNU_NewObjectByName(env, class_name, signature, value); + + (*env)->SetObjectArrayElement(env, array, index, obj); +} + +static void setBooleanValueAtObjectArray(JNIEnv *env, jobjectArray array, + jsize index, jboolean value) { + static const char* class_name = "java/lang/Boolean"; + static const char* signature = "(Z)V"; + jobject obj = JNU_NewObjectByName(env, class_name, signature, value); + + (*env)->SetObjectArrayElement(env, array, index, obj); +} + +static void setByteValueAtObjectArray(JNIEnv *env, jobjectArray array, + jsize index, jbyte value) { + static const char* class_name = "java/lang/Byte"; + static const char* signature = "(B)V"; + jobject obj = JNU_NewObjectByName(env, class_name, signature, value); + + (*env)->SetObjectArrayElement(env, array, index, obj); +} + +static void setIntValueAtObjectArray(JNIEnv *env, jobjectArray array, + jsize index, jint value) { + static const char* class_name = "java/lang/Integer"; + static const char* signature = "(I)V"; + jobject obj = JNU_NewObjectByName(env, class_name, signature, value); + + (*env)->SetObjectArrayElement(env, array, index, obj); +} + +static void setShortValueAtObjectArray(JNIEnv *env, jobjectArray array, + jsize index, jshort value) { + static const char* class_name = "java/lang/Short"; + static const char* signature = "(S)V"; + jobject obj = JNU_NewObjectByName(env, class_name, signature, value); + + (*env)->SetObjectArrayElement(env, array, index, obj); +} + +static void setDoubleValueAtObjectArray(JNIEnv *env, jobjectArray array, + jsize index, jdouble value) { + static const char* class_name = "java/lang/Double"; + static const char* signature = "(D)V"; + jobject obj = JNU_NewObjectByName(env, class_name, signature, value); + + (*env)->SetObjectArrayElement(env, array, index, obj); +} + +static void setFloatValueAtObjectArray(JNIEnv *env, jobjectArray array, + jsize index, jfloat value) { + static const char* class_name = "java/lang/Float"; + static const char* signature = "(D)V"; + jobject obj = JNU_NewObjectByName(env, class_name, signature, value); + + (*env)->SetObjectArrayElement(env, array, index, obj); +} + +static void setCharValueAtObjectArray(JNIEnv *env, jobjectArray array, + jsize index, jchar value) { + static const char* class_name = "java/lang/Character"; + static const char* signature = "(C)V"; + jobject obj = JNU_NewObjectByName(env, class_name, signature, value); + + (*env)->SetObjectArrayElement(env, array, index, obj); +} + +JNIEXPORT jobject JNICALL Java_com_sun_management_internal_GcInfoBuilder_getLastGcInfo0 + (JNIEnv *env, jobject builder, jobject gc, + jint ext_att_count, jobjectArray ext_att_values, jcharArray ext_att_types, + jobjectArray usageBeforeGC, jobjectArray usageAfterGC) { + + jmmGCStat gc_stat; + jchar* nativeTypes; + jsize i; + jvalue v; + + if (gc == NULL) { + JNU_ThrowNullPointerException(env, "Invalid GarbageCollectorMBean"); + return 0; + } + + if (ext_att_count <= 0) { + JNU_ThrowIllegalArgumentException(env, "Invalid ext_att_count"); + return 0; + } + + gc_stat.usage_before_gc = usageBeforeGC; + gc_stat.usage_after_gc = usageAfterGC; + gc_stat.gc_ext_attribute_values_size = ext_att_count; + if (ext_att_count > 0) { + gc_stat.gc_ext_attribute_values = (jvalue*) malloc((size_t)ext_att_count * + sizeof(jvalue)); + if (gc_stat.gc_ext_attribute_values == NULL) { + JNU_ThrowOutOfMemoryError(env, 0); + return 0; + } + } else { + gc_stat.gc_ext_attribute_values = NULL; + } + + + jmm_interface->GetLastGCStat(env, gc, &gc_stat); + if (gc_stat.gc_index == 0) { + if (gc_stat.gc_ext_attribute_values != NULL) { + free(gc_stat.gc_ext_attribute_values); + } + return 0; + } + + // convert the ext_att_types to native types + nativeTypes = (jchar*) malloc((size_t)ext_att_count * sizeof(jchar)); + if (nativeTypes == NULL) { + if (gc_stat.gc_ext_attribute_values != NULL) { + free(gc_stat.gc_ext_attribute_values); + } + JNU_ThrowOutOfMemoryError(env, 0); + return 0; + } + (*env)->GetCharArrayRegion(env, ext_att_types, 0, ext_att_count, nativeTypes); + for (i = 0; i < ext_att_count; i++) { + v = gc_stat.gc_ext_attribute_values[i]; + switch (nativeTypes[i]) { + case 'Z': + setBooleanValueAtObjectArray(env, ext_att_values, i, v.z); + break; + case 'B': + setByteValueAtObjectArray(env, ext_att_values, i, v.b); + break; + case 'C': + setCharValueAtObjectArray(env, ext_att_values, i, v.c); + break; + case 'S': + setShortValueAtObjectArray(env, ext_att_values, i, v.s); + break; + case 'I': + setIntValueAtObjectArray(env, ext_att_values, i, v.i); + break; + case 'J': + setLongValueAtObjectArray(env, ext_att_values, i, v.j); + break; + case 'F': + setFloatValueAtObjectArray(env, ext_att_values, i, v.f); + break; + case 'D': + setDoubleValueAtObjectArray(env, ext_att_values, i, v.d); + break; + default: + if (gc_stat.gc_ext_attribute_values != NULL) { + free(gc_stat.gc_ext_attribute_values); + } + if (nativeTypes != NULL) { + free(nativeTypes); + } + JNU_ThrowInternalError(env, "Unsupported attribute type"); + return 0; + } + } + if (gc_stat.gc_ext_attribute_values != NULL) { + free(gc_stat.gc_ext_attribute_values); + } + if (nativeTypes != NULL) { + free(nativeTypes); + } + + return JNU_NewObjectByName(env, + "com/sun/management/GcInfo", + "(Lcom/sun/management/internal/GcInfoBuilder;JJJ[Ljava/lang/management/MemoryUsage;[Ljava/lang/management/MemoryUsage;[Ljava/lang/Object;)V", + builder, + gc_stat.gc_index, + gc_stat.start_time, + gc_stat.end_time, + usageBeforeGC, + usageAfterGC, + ext_att_values); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/native/libmanagement_ext/HotSpotDiagnostic.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <jni.h> +#include "jvm.h" +#include "management_ext.h" +#include "com_sun_management_internal_HotSpotDiagnostic.h" + +JNIEXPORT void JNICALL +Java_com_sun_management_internal_HotSpotDiagnostic_dumpHeap0 + (JNIEnv *env, jobject dummy, jstring outputfile, jboolean live) +{ + jmm_interface->DumpHeap0(env, outputfile, live); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/native/libmanagement_ext/management_ext.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <stdio.h> +#include <jni.h> +#include "jvm.h" +#include "management_ext.h" + +#define ERR_MSG_SIZE 128 + +const JmmInterface* jmm_interface = NULL; +JavaVM* jvm = NULL; +jint jmm_version = 0; + +JNIEXPORT jint JNICALL + JNI_OnLoad(JavaVM *vm, void *reserved) { + JNIEnv* env; + + jvm = vm; + if ((*vm)->GetEnv(vm, (void**) &env, JNI_VERSION_1_2) != JNI_OK) { + return JNI_ERR; + } + + jmm_interface = (JmmInterface*) JVM_GetManagement(JMM_VERSION_1_0); + if (jmm_interface == NULL) { + JNU_ThrowInternalError(env, "Unsupported Management version"); + return JNI_ERR; + } + + jmm_version = jmm_interface->GetVersion(env); + return (*env)->GetVersion(env); +} + +void throw_internal_error(JNIEnv* env, const char* msg) { + char errmsg[128]; + + sprintf(errmsg, "errno: %d error: %s\n", errno, msg); + JNU_ThrowInternalError(env, errmsg); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/share/native/libmanagement_ext/management_ext.h Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <jni.h> + +#include "jni_util.h" +#include "jmm.h" + +#ifndef _MANAGEMENT_EXT_H_ +#define _MANAGEMENT_EXT_H_ + +extern const JmmInterface* jmm_interface; +extern jint jmm_version; +extern void throw_internal_error(JNIEnv* env, const char* msg); + +#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include <fcntl.h> +#include <kstat.h> +#include <procfs.h> +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include <sys/sysinfo.h> +#include <sys/lwp.h> +#include <pthread.h> +#include <utmpx.h> +#include <dlfcn.h> +#include <sys/loadavg.h> +#include <jni.h> +#include "jvm.h" +#include "com_sun_management_internal_OperatingSystemImpl.h" + +typedef struct { + kstat_t *kstat; + uint64_t last_idle; + uint64_t last_total; + double last_ratio; +} cpuload_t; + +static cpuload_t *cpu_loads = NULL; +static unsigned int num_cpus; +static kstat_ctl_t *kstat_ctrl = NULL; + +static void map_cpu_kstat_counters() { + kstat_t *kstat; + int i; + + // Get number of CPU(s) + if ((num_cpus = sysconf(_SC_NPROCESSORS_ONLN)) == -1) { + num_cpus = 1; + } + + // Data structure for saving CPU load + if ((cpu_loads = calloc(num_cpus,sizeof(cpuload_t))) == NULL) { + return; + } + + // Get kstat cpu_stat counters for every CPU + // (loop over kstat to find our cpu_stat(s) + i = 0; + for (kstat = kstat_ctrl->kc_chain; kstat != NULL; kstat = kstat->ks_next) { + if (strncmp(kstat->ks_module, "cpu_stat", 8) == 0) { + + if (kstat_read(kstat_ctrl, kstat, NULL) == -1) { + // Failed to initialize kstat for this CPU so ignore it + continue; + } + + if (i == num_cpus) { + // Found more cpu_stats than reported CPUs + break; + } + + cpu_loads[i++].kstat = kstat; + } + } +} + +static int init_cpu_kstat_counters() { + static int initialized = 0; + + // Concurrence in this method is prevented by the lock in + // the calling method get_cpu_load(); + if(!initialized) { + if ((kstat_ctrl = kstat_open()) != NULL) { + map_cpu_kstat_counters(); + initialized = 1; + } + } + return initialized ? 0 : -1; +} + +static void update_cpu_kstat_counters() { + if(kstat_chain_update(kstat_ctrl) != 0) { + free(cpu_loads); + map_cpu_kstat_counters(); + } +} + +int read_cpustat(cpuload_t *load, cpu_stat_t *cpu_stat) { + if (load->kstat == NULL) { + // no handle. + return -1; + } + if (kstat_read(kstat_ctrl, load->kstat, cpu_stat) == -1) { + // disabling for now, a kstat chain update is likely to happen next time + load->kstat = NULL; + return -1; + } + return 0; +} + +double get_single_cpu_load(unsigned int n) { + cpuload_t *load; + cpu_stat_t cpu_stat; + uint_t *usage; + uint64_t c_idle; + uint64_t c_total; + uint64_t d_idle; + uint64_t d_total; + int i; + + if (n >= num_cpus) { + return -1.0; + } + + load = &cpu_loads[n]; + if (read_cpustat(load, &cpu_stat) < 0) { + return -1.0; + } + + usage = cpu_stat.cpu_sysinfo.cpu; + c_idle = usage[CPU_IDLE]; + + for (c_total = 0, i = 0; i < CPU_STATES; i++) { + c_total += usage[i]; + } + + // Calculate diff against previous snapshot + d_idle = c_idle - load->last_idle; + d_total = c_total - load->last_total; + + /** update if weve moved */ + if (d_total > 0) { + // Save current values for next time around + load->last_idle = c_idle; + load->last_total = c_total; + load->last_ratio = (double) (d_total - d_idle) / d_total; + } + + return load->last_ratio; +} + +int get_info(const char *path, void *info, size_t s, off_t o) { + int fd; + int ret = 0; + if ((fd = open(path, O_RDONLY)) < 0) { + return -1; + } + if (pread(fd, info, s, o) != s) { + ret = -1; + } + close(fd); + return ret; +} + +#define MIN(a, b) ((a < b) ? a : b) + +static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; + +/** + * Return the cpu load (0-1) for proc number 'which' (or average all if which == -1) + */ +double get_cpu_load(int which) { + double load =.0; + + pthread_mutex_lock(&lock); + if(init_cpu_kstat_counters()==0) { + + update_cpu_kstat_counters(); + + if (which == -1) { + unsigned int i; + double t; + + for (t = .0, i = 0; i < num_cpus; i++) { + t += get_single_cpu_load(i); + } + + // Cap total systemload to 1.0 + load = MIN((t / num_cpus), 1.0); + } else { + load = MIN(get_single_cpu_load(which), 1.0); + } + } else { + load = -1.0; + } + pthread_mutex_unlock(&lock); + + return load; +} + +/** + * Return the cpu load (0-1) for the current process (i.e the JVM) + * or -1.0 if the get_info() call failed + */ +double get_process_load(void) { + psinfo_t info; + + // Get the percentage of "recent cpu usage" from all the lwp:s in the JVM:s + // process. This is returned as a value between 0.0 and 1.0 multiplied by 0x8000. + if (get_info("/proc/self/psinfo",&info.pr_pctcpu, sizeof(info.pr_pctcpu), offsetof(psinfo_t, pr_pctcpu)) == 0) { + return (double) info.pr_pctcpu / 0x8000; + } + return -1.0; +} + +JNIEXPORT jdouble JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0 +(JNIEnv *env, jobject dummy) +{ + return get_cpu_load(-1); +} + +JNIEXPORT jdouble JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0 +(JNIEnv *env, jobject dummy) +{ + return get_process_load(); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/unix/classes/com/sun/management/internal/OperatingSystemImpl.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +import sun.management.BaseOperatingSystemImpl; +import sun.management.VMManagement; +/** + * Implementation class for the operating system. + * Standard and committed hotspot-specific metrics if any. + * + * ManagementFactory.getOperatingSystemMXBean() returns an instance + * of this class. + */ +class OperatingSystemImpl extends BaseOperatingSystemImpl + implements com.sun.management.UnixOperatingSystemMXBean { + + OperatingSystemImpl(VMManagement vm) { + super(vm); + } + + public long getCommittedVirtualMemorySize() { + return getCommittedVirtualMemorySize0(); + } + + public long getTotalSwapSpaceSize() { + return getTotalSwapSpaceSize0(); + } + + public long getFreeSwapSpaceSize() { + return getFreeSwapSpaceSize0(); + } + + public long getProcessCpuTime() { + return getProcessCpuTime0(); + } + + public long getFreePhysicalMemorySize() { + return getFreePhysicalMemorySize0(); + } + + public long getTotalPhysicalMemorySize() { + return getTotalPhysicalMemorySize0(); + } + + public long getOpenFileDescriptorCount() { + return getOpenFileDescriptorCount0(); + } + + public long getMaxFileDescriptorCount() { + return getMaxFileDescriptorCount0(); + } + + public double getSystemCpuLoad() { + return getSystemCpuLoad0(); + } + + public double getProcessCpuLoad() { + return getProcessCpuLoad0(); + } + + /* native methods */ + private native long getCommittedVirtualMemorySize0(); + private native long getFreePhysicalMemorySize0(); + private native long getFreeSwapSpaceSize0(); + private native long getMaxFileDescriptorCount0(); + private native long getOpenFileDescriptorCount0(); + private native long getProcessCpuTime0(); + private native double getProcessCpuLoad0(); + private native double getSystemCpuLoad0(); + private native long getTotalPhysicalMemorySize0(); + private native long getTotalSwapSpaceSize0(); + + static { + initialize0(); + } + + private static native void initialize0(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,479 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" +#include "jvm.h" +#include "management_ext.h" +#include "com_sun_management_internal_OperatingSystemImpl.h" + +#include <sys/types.h> +#include <sys/stat.h> +#if defined(_ALLBSD_SOURCE) +#include <sys/sysctl.h> +#ifdef __APPLE__ +#include <sys/param.h> +#include <sys/mount.h> +#include <mach/mach.h> +#include <sys/proc_info.h> +#include <libproc.h> +#endif +#elif !defined(_AIX) +#include <sys/swap.h> +#endif +#include <sys/resource.h> +#include <sys/times.h> +#ifndef _ALLBSD_SOURCE +#include <sys/sysinfo.h> +#endif +#include <ctype.h> +#include <dirent.h> +#include <errno.h> +#include <fcntl.h> +#include <limits.h> +#include <stdlib.h> +#include <unistd.h> + +#if defined(_AIX) +#include <libperfstat.h> +#endif + +static jlong page_size = 0; + +#if defined(_ALLBSD_SOURCE) || defined(_AIX) +#define MB (1024UL * 1024UL) +#else + +/* This gets us the new structured proc interfaces of 5.6 & later */ +/* - see comment in <sys/procfs.h> */ +#define _STRUCTURED_PROC 1 +#include <sys/procfs.h> + +#endif /* _ALLBSD_SOURCE */ + +static struct dirent* read_dir(DIR* dirp, struct dirent* entry) { +#ifdef __solaris__ + struct dirent* dbuf = readdir(dirp); + return dbuf; +#else /* __linux__ || _ALLBSD_SOURCE */ + struct dirent* p; + if (readdir_r(dirp, entry, &p) == 0) { + return p; + } else { + return NULL; + } +#endif +} + +// true = get available swap in bytes +// false = get total swap in bytes +static jlong get_total_or_available_swap_space_size(JNIEnv* env, jboolean available) { +#ifdef __solaris__ + long total, avail; + int nswap, i, count; + swaptbl_t *stbl; + char *strtab; + + // First get the number of swap resource entries + if ((nswap = swapctl(SC_GETNSWP, NULL)) == -1) { + throw_internal_error(env, "swapctl failed to get nswap"); + return -1; + } + if (nswap == 0) { + return 0; + } + + // Allocate storage for resource entries + stbl = (swaptbl_t*) malloc(nswap * sizeof(swapent_t) + + sizeof(struct swaptable)); + if (stbl == NULL) { + JNU_ThrowOutOfMemoryError(env, 0); + return -1; + } + + // Allocate storage for the table + strtab = (char*) malloc((nswap + 1) * MAXPATHLEN); + if (strtab == NULL) { + free(stbl); + JNU_ThrowOutOfMemoryError(env, 0); + return -1; + } + + for (i = 0; i < (nswap + 1); i++) { + stbl->swt_ent[i].ste_path = strtab + (i * MAXPATHLEN); + } + stbl->swt_n = nswap + 1; + + // Get the entries + if ((count = swapctl(SC_LIST, stbl)) < 0) { + free(stbl); + free(strtab); + throw_internal_error(env, "swapctl failed to get swap list"); + return -1; + } + + // Sum the entries to get total and free swap + total = 0; + avail = 0; + for (i = 0; i < count; i++) { + total += stbl->swt_ent[i].ste_pages; + avail += stbl->swt_ent[i].ste_free; + } + + free(stbl); + free(strtab); + return available ? ((jlong)avail * page_size) : + ((jlong)total * page_size); +#elif defined(__linux__) + int ret; + FILE *fp; + jlong total = 0, avail = 0; + + struct sysinfo si; + ret = sysinfo(&si); + if (ret != 0) { + throw_internal_error(env, "sysinfo failed to get swap size"); + } + total = (jlong)si.totalswap * si.mem_unit; + avail = (jlong)si.freeswap * si.mem_unit; + + return available ? avail : total; +#elif defined(__APPLE__) + struct xsw_usage vmusage; + size_t size = sizeof(vmusage); + if (sysctlbyname("vm.swapusage", &vmusage, &size, NULL, 0) != 0) { + throw_internal_error(env, "sysctlbyname failed"); + } + return available ? (jlong)vmusage.xsu_avail : (jlong)vmusage.xsu_total; +#else /* _ALLBSD_SOURCE */ + /* + * XXXBSD: there's no way available to get swap info in + * FreeBSD. Usage of libkvm is not an option here + */ + // throw_internal_error(env, "Unimplemented in FreeBSD"); + return (0); +#endif +} + +JNIEXPORT void JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_initialize0 + (JNIEnv *env, jclass cls) +{ + page_size = sysconf(_SC_PAGESIZE); +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getCommittedVirtualMemorySize0 + (JNIEnv *env, jobject mbean) +{ +#ifdef __solaris__ + psinfo_t psinfo; + ssize_t result; + size_t remaining; + char* addr; + int fd; + + fd = open64("/proc/self/psinfo", O_RDONLY, 0); + if (fd < 0) { + throw_internal_error(env, "Unable to open /proc/self/psinfo"); + return -1; + } + + addr = (char *)&psinfo; + for (remaining = sizeof(psinfo_t); remaining > 0;) { + result = read(fd, addr, remaining); + if (result < 0) { + if (errno != EINTR) { + close(fd); + throw_internal_error(env, "Unable to read /proc/self/psinfo"); + return -1; + } + } else { + remaining -= result; + addr += result; + } + } + + close(fd); + return (jlong) psinfo.pr_size * 1024; +#elif defined(__linux__) + FILE *fp; + unsigned long vsize = 0; + + if ((fp = fopen("/proc/self/stat", "r")) == NULL) { + throw_internal_error(env, "Unable to open /proc/self/stat"); + return -1; + } + + // Ignore everything except the vsize entry + if (fscanf(fp, "%*d %*s %*c %*d %*d %*d %*d %*d %*u %*u %*u %*u %*u %*d %*d %*d %*d %*d %*d %*u %*u %*d %lu %*[^\n]\n", &vsize) == EOF) { + throw_internal_error(env, "Unable to get virtual memory usage"); + fclose(fp); + return -1; + } + + fclose(fp); + return (jlong)vsize; +#elif defined(__APPLE__) + struct task_basic_info t_info; + mach_msg_type_number_t t_info_count = TASK_BASIC_INFO_COUNT; + + kern_return_t res = task_info(mach_task_self(), TASK_BASIC_INFO, (task_info_t)&t_info, &t_info_count); + if (res != KERN_SUCCESS) { + throw_internal_error(env, "task_info failed"); + } + return t_info.virtual_size; +#else /* _ALLBSD_SOURCE */ + /* + * XXXBSD: there's no way available to do it in FreeBSD, AFAIK. + */ + // throw_internal_error(env, "Unimplemented in FreeBSD"); + return (64 * MB); +#endif +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getTotalSwapSpaceSize0 + (JNIEnv *env, jobject mbean) +{ + return get_total_or_available_swap_space_size(env, JNI_FALSE); +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getFreeSwapSpaceSize0 + (JNIEnv *env, jobject mbean) +{ + return get_total_or_available_swap_space_size(env, JNI_TRUE); +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuTime0 + (JNIEnv *env, jobject mbean) +{ +#ifdef __APPLE__ + struct rusage usage; + if (getrusage(RUSAGE_SELF, &usage) != 0) { + throw_internal_error(env, "getrusage failed"); + return -1; + } + jlong microsecs = + usage.ru_utime.tv_sec * 1000 * 1000 + usage.ru_utime.tv_usec + + usage.ru_stime.tv_sec * 1000 * 1000 + usage.ru_stime.tv_usec; + return microsecs * 1000; +#else + jlong clk_tck, ns_per_clock_tick; + jlong cpu_time_ns; + struct tms time; + + /* + * BSDNOTE: FreeBSD implements _SC_CLK_TCK since FreeBSD 5, so + * add a magic to handle it + */ +#if defined(__solaris__) || defined(_SC_CLK_TCK) + clk_tck = (jlong) sysconf(_SC_CLK_TCK); +#elif defined(__linux__) || defined(_ALLBSD_SOURCE) + clk_tck = 100; +#endif + if (clk_tck == -1) { + throw_internal_error(env, + "sysconf failed - not able to get clock tick"); + return -1; + } + + times(&time); + ns_per_clock_tick = (jlong) 1000 * 1000 * 1000 / (jlong) clk_tck; + cpu_time_ns = ((jlong)time.tms_utime + (jlong) time.tms_stime) * + ns_per_clock_tick; + return cpu_time_ns; +#endif +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getFreePhysicalMemorySize0 + (JNIEnv *env, jobject mbean) +{ +#ifdef __APPLE__ + mach_msg_type_number_t count; + vm_statistics_data_t vm_stats; + kern_return_t res; + + count = HOST_VM_INFO_COUNT; + res = host_statistics(mach_host_self(), HOST_VM_INFO, (host_info_t)&vm_stats, &count); + if (res != KERN_SUCCESS) { + throw_internal_error(env, "host_statistics failed"); + return -1; + } + return (jlong)vm_stats.free_count * page_size; +#elif defined(_ALLBSD_SOURCE) + /* + * XXBSDL no way to do it in FreeBSD + */ + // throw_internal_error(env, "unimplemented in FreeBSD") + return (128 * MB); +#elif defined(_AIX) + perfstat_memory_total_t memory_info; + if (-1 != perfstat_memory_total(NULL, &memory_info, sizeof(perfstat_memory_total_t), 1)) { + return (jlong)(memory_info.real_free * 4L * 1024L); + } + return -1; +#else // solaris / linux + jlong num_avail_physical_pages = sysconf(_SC_AVPHYS_PAGES); + return (num_avail_physical_pages * page_size); +#endif +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getTotalPhysicalMemorySize0 + (JNIEnv *env, jobject mbean) +{ +#ifdef _ALLBSD_SOURCE + jlong result = 0; + int mib[2]; + size_t rlen; + + mib[0] = CTL_HW; + mib[1] = HW_MEMSIZE; + rlen = sizeof(result); + if (sysctl(mib, 2, &result, &rlen, NULL, 0) != 0) { + throw_internal_error(env, "sysctl failed"); + return -1; + } + return result; +#elif defined(_AIX) + perfstat_memory_total_t memory_info; + if (-1 != perfstat_memory_total(NULL, &memory_info, sizeof(perfstat_memory_total_t), 1)) { + return (jlong)(memory_info.real_total * 4L * 1024L); + } + return -1; +#else // solaris / linux + jlong num_physical_pages = sysconf(_SC_PHYS_PAGES); + return (num_physical_pages * page_size); +#endif +} + + + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getOpenFileDescriptorCount0 + (JNIEnv *env, jobject mbean) +{ +#ifdef __APPLE__ + // This code is influenced by the darwin lsof source + pid_t my_pid; + struct proc_bsdinfo bsdinfo; + struct proc_fdinfo *fds; + int nfiles; + kern_return_t kres; + int res; + size_t fds_size; + + kres = pid_for_task(mach_task_self(), &my_pid); + if (kres != KERN_SUCCESS) { + throw_internal_error(env, "pid_for_task failed"); + return -1; + } + + // get the maximum number of file descriptors + res = proc_pidinfo(my_pid, PROC_PIDTBSDINFO, 0, &bsdinfo, PROC_PIDTBSDINFO_SIZE); + if (res <= 0) { + throw_internal_error(env, "proc_pidinfo with PROC_PIDTBSDINFO failed"); + return -1; + } + + // allocate memory to hold the fd information (we don't acutally use this information + // but need it to get the number of open files) + fds_size = bsdinfo.pbi_nfiles * sizeof(struct proc_fdinfo); + fds = malloc(fds_size); + if (fds == NULL) { + JNU_ThrowOutOfMemoryError(env, "could not allocate space for file descriptors"); + return -1; + } + + // get the list of open files - the return value is the number of bytes + // proc_pidinfo filled in + res = proc_pidinfo(my_pid, PROC_PIDLISTFDS, 0, fds, fds_size); + if (res <= 0) { + free(fds); + throw_internal_error(env, "proc_pidinfo failed for PROC_PIDLISTFDS"); + return -1; + } + nfiles = res / sizeof(struct proc_fdinfo); + free(fds); + + return nfiles; +#elif defined(_ALLBSD_SOURCE) + /* + * XXXBSD: there's no way available to do it in FreeBSD, AFAIK. + */ + // throw_internal_error(env, "Unimplemented in FreeBSD"); + return (100); +#else /* solaris/linux */ + DIR *dirp; + struct dirent dbuf; + struct dirent* dentp; + jlong fds = 0; + +#if defined(_AIX) +/* AIX does not understand '/proc/self' - it requires the real process ID */ +#define FD_DIR aix_fd_dir + char aix_fd_dir[32]; /* the pid has at most 19 digits */ + snprintf(aix_fd_dir, 32, "/proc/%d/fd", getpid()); +#else +#define FD_DIR "/proc/self/fd" +#endif + + dirp = opendir(FD_DIR); + if (dirp == NULL) { + throw_internal_error(env, "Unable to open directory /proc/self/fd"); + return -1; + } + + // iterate through directory entries, skipping '.' and '..' + // each entry represents an open file descriptor. + while ((dentp = read_dir(dirp, &dbuf)) != NULL) { + if (isdigit(dentp->d_name[0])) { + fds++; + } + } + + closedir(dirp); + // subtract by 1 which was the fd open for this implementation + return (fds - 1); +#endif +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getMaxFileDescriptorCount0 + (JNIEnv *env, jobject mbean) +{ + struct rlimit rlp; + + if (getrlimit(RLIMIT_NOFILE, &rlp) == -1) { + throw_internal_error(env, "getrlimit failed"); + return -1; + } + return (jlong) rlp.rlim_cur; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/windows/classes/com/sun/management/internal/OperatingSystemImpl.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +package com.sun.management.internal; + +import com.sun.management.OperatingSystemMXBean; +import sun.management.BaseOperatingSystemImpl; +import sun.management.VMManagement; + +/** + * Implementation class for the operating system. + * Standard and committed hotspot-specific metrics if any. + * + * ManagementFactory.getOperatingSystemMXBean() returns an instance + * of this class. + */ +class OperatingSystemImpl extends BaseOperatingSystemImpl + implements OperatingSystemMXBean { + + // psapiLock is a lock to make sure only one thread loading + // PSAPI DLL. + private static Object psapiLock = new Object(); + + OperatingSystemImpl(VMManagement vm) { + super(vm); + } + + @Override + public long getCommittedVirtualMemorySize() { + synchronized (psapiLock) { + return getCommittedVirtualMemorySize0(); + } + } + + @Override + public long getTotalSwapSpaceSize() { + return getTotalSwapSpaceSize0(); + } + + @Override + public long getFreeSwapSpaceSize() { + return getFreeSwapSpaceSize0(); + } + + @Override + public long getProcessCpuTime() { + return getProcessCpuTime0(); + } + + @Override + public long getFreePhysicalMemorySize() { + return getFreePhysicalMemorySize0(); + } + + @Override + public long getTotalPhysicalMemorySize() { + return getTotalPhysicalMemorySize0(); + } + + @Override + public double getSystemCpuLoad() { + return getSystemCpuLoad0(); + } + + @Override + public double getProcessCpuLoad() { + return getProcessCpuLoad0(); + } + + /* native methods */ + private native long getCommittedVirtualMemorySize0(); + private native long getFreePhysicalMemorySize0(); + private native long getFreeSwapSpaceSize0(); + private native double getProcessCpuLoad0(); + private native long getProcessCpuTime0(); + private native double getSystemCpuLoad0(); + private native long getTotalPhysicalMemorySize0(); + private native long getTotalSwapSpaceSize0(); + + static { + initialize0(); + } + + private static native void initialize0(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/src/jdk.management/windows/native/libmanagement_ext/OperatingSystemImpl.c Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,1363 @@ +/* + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +#include "jni.h" +#include "jni_util.h" +#include "jlong.h" +#include "jvm.h" +#include "management_ext.h" +#include "com_sun_management_internal_OperatingSystemImpl.h" + +#include <psapi.h> +#include <errno.h> +#include <stdlib.h> + +#include <malloc.h> +#pragma warning (push,0) +#include <windows.h> +#pragma warning (pop) +#include <stdio.h> +#include <time.h> +#include <stdint.h> +#include <assert.h> + +/* Disable warnings due to broken header files from Microsoft... */ +#pragma warning(push, 3) +#include <pdh.h> +#include <pdhmsg.h> +#include <process.h> +#pragma warning(pop) + +typedef unsigned __int32 juint; +typedef unsigned __int64 julong; + +static void set_low(jlong* value, jint low) { + *value &= (jlong)0xffffffff << 32; + *value |= (jlong)(julong)(juint)low; +} + +static void set_high(jlong* value, jint high) { + *value &= (jlong)(julong)(juint)0xffffffff; + *value |= (jlong)high << 32; +} + +static jlong jlong_from(jint h, jint l) { + jlong result = 0; // initialization to avoid warning + set_high(&result, h); + set_low(&result, l); + return result; +} + +static HANDLE main_process; + +static void perfInit(void); + +JNIEXPORT void JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_initialize0 + (JNIEnv *env, jclass cls) +{ + main_process = GetCurrentProcess(); + perfInit(); +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getCommittedVirtualMemorySize0 + (JNIEnv *env, jobject mbean) +{ + PROCESS_MEMORY_COUNTERS pmc; + if (GetProcessMemoryInfo(main_process, &pmc, sizeof(PROCESS_MEMORY_COUNTERS)) == 0) { + return (jlong)-1L; + } else { + return (jlong) pmc.PagefileUsage; + } +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getTotalSwapSpaceSize0 + (JNIEnv *env, jobject mbean) +{ + MEMORYSTATUSEX ms; + ms.dwLength = sizeof(ms); + GlobalMemoryStatusEx(&ms); + return (jlong) ms.ullTotalPageFile; +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getFreeSwapSpaceSize0 + (JNIEnv *env, jobject mbean) +{ + MEMORYSTATUSEX ms; + ms.dwLength = sizeof(ms); + GlobalMemoryStatusEx(&ms); + return (jlong) ms.ullAvailPageFile; +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuTime0 + (JNIEnv *env, jobject mbean) +{ + + FILETIME process_creation_time, process_exit_time, + process_user_time, process_kernel_time; + + // Using static variables declared above + // Units are 100-ns intervals. Convert to ns. + GetProcessTimes(main_process, &process_creation_time, + &process_exit_time, + &process_kernel_time, &process_user_time); + return (jlong_from(process_user_time.dwHighDateTime, + process_user_time.dwLowDateTime) + + jlong_from(process_kernel_time.dwHighDateTime, + process_kernel_time.dwLowDateTime)) * 100; +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getFreePhysicalMemorySize0 + (JNIEnv *env, jobject mbean) +{ + MEMORYSTATUSEX ms; + ms.dwLength = sizeof(ms); + GlobalMemoryStatusEx(&ms); + return (jlong) ms.ullAvailPhys; +} + +JNIEXPORT jlong JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getTotalPhysicalMemorySize0 + (JNIEnv *env, jobject mbean) +{ + MEMORYSTATUSEX ms; + ms.dwLength = sizeof(ms); + GlobalMemoryStatusEx(&ms); + return (jlong) ms.ullTotalPhys; +} + +/* Performance Data Helper API (PDH) support */ + +typedef PDH_STATUS (WINAPI *PdhAddCounterFunc)( + HQUERY hQuery, + LPCSTR szFullCounterPath, + DWORD dwUserData, + HCOUNTER *phCounter + ); +typedef PDH_STATUS (WINAPI *PdhOpenQueryFunc)( + LPCWSTR szDataSource, + DWORD dwUserData, + HQUERY *phQuery + ); +typedef PDH_STATUS (WINAPI *PdhCollectQueryDataFunc)( + HQUERY hQuery + ); + +typedef PDH_STATUS (WINAPI *PdhEnumObjectItemsFunc)( + LPCTSTR szDataSource, + LPCTSTR szMachineName, + LPCTSTR szObjectName, + LPTSTR mszCounterList, + LPDWORD pcchCounterListLength, + LPTSTR mszInstanceList, + LPDWORD pcchInstanceListLength, + DWORD dwDetailLevel, + DWORD dwFlags + ); +typedef PDH_STATUS (WINAPI *PdhRemoveCounterFunc)( + HCOUNTER hCounter + ); +typedef PDH_STATUS (WINAPI *PdhLookupPerfNameByIndexFunc)( + LPCSTR szMachineName, + DWORD dwNameIndex, + LPSTR szNameBuffer, + LPDWORD pcchNameBufferSize + ); +typedef DWORD (WINAPI *PdhCloseQueryFunc)( + HQUERY hQuery + ); + +typedef DWORD (WINAPI *PdhGetFormattedCounterValueFunc)( + HCOUNTER hCounter, + DWORD dwFormat, + LPDWORD lpdwType, + PPDH_FMT_COUNTERVALUE pValue + ); + +static PdhAddCounterFunc PdhAddCounter_i; +static PdhOpenQueryFunc PdhOpenQuery_i; +static PdhCloseQueryFunc PdhCloseQuery_i; +static PdhCollectQueryDataFunc PdhCollectQueryData_i; +static PdhGetFormattedCounterValueFunc PdhGetFormattedCounterValue_i; +static PdhEnumObjectItemsFunc PdhEnumObjectItems_i; +static PdhRemoveCounterFunc PdhRemoveCounter_i; +static PdhLookupPerfNameByIndexFunc PdhLookupPerfNameByIndex_i; + +/* + * Struct for PDH queries. + */ +typedef struct { + HQUERY query; + uint64_t lastUpdate; // Last time query was updated (ticks) +} UpdateQueryS, *UpdateQueryP; + +// Min time between query updates (ticks) +static const int MIN_UPDATE_INTERVAL = 500; + +/* + * Struct for a PDH query with multiple counters. + */ +typedef struct { + UpdateQueryS query; + HCOUNTER* counters; + int noOfCounters; +} MultipleCounterQueryS, *MultipleCounterQueryP; + +/* + * Struct for a PDH query with a single counter. + */ +typedef struct { + UpdateQueryS query; + HCOUNTER counter; +} SingleCounterQueryS, *SingleCounterQueryP; + + +typedef struct { + CRITICAL_SECTION cs; + DWORD owningThread; + DWORD recursionCount; +} PdhCriticalSectionS, *PdhCriticalSectionP; + +static PdhCriticalSectionS initializationLock; + +static void InitializePdhCriticalSection(PdhCriticalSectionP criticalSection) { + assert(criticalSection); + + InitializeCriticalSection(&criticalSection->cs); + criticalSection->owningThread = 0; + criticalSection->recursionCount = 0; +} + +static void EnterPdhCriticalSection(PdhCriticalSectionP criticalSection) { + assert(criticalSection); + + EnterCriticalSection(&criticalSection->cs); + criticalSection->recursionCount++; + if (!criticalSection->owningThread) { + criticalSection->owningThread = GetCurrentThreadId(); + } +} + +static void LeavePdhCriticalSection(PdhCriticalSectionP criticalSection) { + assert(criticalSection); + assert(GetCurrentThreadId() == criticalSection->owningThread); + assert(criticalSection->recursionCount >= 1); + + criticalSection->recursionCount--; + if (!criticalSection->recursionCount) { + criticalSection->owningThread = 0; + } + LeaveCriticalSection(&criticalSection->cs); +} + +/* + * INFO: Using PDH APIs Correctly in a Localized Language (Q287159) + * http://support.microsoft.com/default.aspx?scid=kb;EN-US;q287159 + * The index value for the base system counters and objects like processor, + * process, thread, memory, and so forth are always the same irrespective + * of the localized version of the operating system or service pack installed. + * To find the correct index for an object or counter, inspect the registry key/value: + * [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Perflib\009\Counter] + */ +static const DWORD PDH_PROCESSOR_IDX = 238; +static const DWORD PDH_PROCESSOR_TIME_IDX = 6; +static const DWORD PDH_PROCESS_IDX = 230; +static const DWORD PDH_ID_PROCESS_IDX = 784; + +/* useful pdh fmt's */ +static const char* const OBJECT_COUNTER_FMT = "\\%s\\%s"; +static const size_t OBJECT_COUNTER_FMT_LEN = 2; +static const char* const OBJECT_WITH_INSTANCES_COUNTER_FMT = "\\%s(%s)\\%s"; +static const size_t OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN = 4; +static const char* const PROCESS_OBJECT_INSTANCE_COUNTER_FMT = "\\%s(%s#%s)\\%s"; +static const size_t PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN = 5; + +static const char* pdhProcessImageName = NULL; /* "java" */ +static char* pdhIDProcessCounterFmt = NULL; /* "\Process(java#%d)\ID Process" */ + +static int numberOfJavaProcessesAtInitialization = 0; + +/* + * Currently used CPU queries/counters and variables + */ +static SingleCounterQueryP processTotalCPULoad = NULL; +static MultipleCounterQueryP multiCounterCPULoad = NULL; +static double cpuFactor = .0; +static DWORD numCpus = 0; + +/* + * Seems WinXP PDH returns PDH_MORE_DATA whenever we send in a NULL buffer. + * Let's just ignore it, since we make sure we have enough buffer anyway. + */ +static int +pdhFail(PDH_STATUS pdhStat) { + return pdhStat != ERROR_SUCCESS && pdhStat != PDH_MORE_DATA; +} + +static const char* +allocateAndCopy(const char* const originalString) { + size_t len; + char* allocatedString; + + assert(originalString); + + len = strlen(originalString); + + allocatedString = malloc(len + 1); + + if (!allocatedString) { + return NULL; + } + + strncpy(allocatedString, originalString, len); + allocatedString[len] = '\0'; + + return allocatedString; +} + +/* + * Allocates memory into the supplied pointer and + * fills it with the localized PDH artifact description, if indexed correctly. + * Caller owns the memory from the point of returning from this function. + * + * @param index the PDH counter index as specified in the registry + * @param ppBuffer pointer to a char*. + * @return 0 if successful, negative on failure. + */ +static int +lookupNameByIndex(DWORD index, char** ppBuffer) { + DWORD size; + + assert(ppBuffer); + + /* determine size needed */ + if (PdhLookupPerfNameByIndex_i(NULL, index, NULL, &size) != PDH_MORE_DATA) { + /* invalid index? */ + return -1; + } + + *ppBuffer = malloc((size_t)size); + + if (!*ppBuffer) { + return -1; + } + + if (PdhLookupPerfNameByIndex_i(NULL, index, *ppBuffer, &size) != ERROR_SUCCESS) { + free(*ppBuffer); + *ppBuffer = NULL; + return -1; + } + + /* windows vista does not null-terminate the string + * (although the docs says it will) */ + (*ppBuffer)[size - 1] = '\0'; + + return 0; +} + +/* +* Construct a fully qualified PDH path +* +* @param objectName a PDH Object string representation (required) +* @param counterName a PDH Counter string representation (required) +* @param imageName a process image name string, ex. "java" (opt) +* @param instance an instance string, ex. "0", "1", ... (opt) +* @return the fully qualified PDH path. +* +* Caller will own the returned malloc:ed string +*/ +static const char* +makeFullCounterPath(const char* const objectName, + const char* const counterName, + const char* const imageName, + const char* const instance) { + + size_t fullCounterPathLen; + char* fullCounterPath; + + assert(objectName); + assert(counterName); + + fullCounterPathLen = strlen(objectName); + fullCounterPathLen += strlen(counterName); + + if (imageName) { + /* + * For paths using the "Process" Object. + * + * Examples: + * abstract: "\Process(imageName#instance)\Counter" + * actual: "\Process(java#2)\ID Process" + */ + fullCounterPathLen += PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN; + fullCounterPathLen += strlen(imageName); + + /* + * imageName must be passed together with an associated + * instance "number" ("0", "1", "2", ...). + * This is required in order to create valid "Process" Object paths. + * + * Examples: "\Process(java#0)", \Process(java#1"), ... + */ + assert(instance); + + fullCounterPathLen += strlen(instance); + + fullCounterPath = malloc(fullCounterPathLen + 1); + + if (!fullCounterPath) { + return NULL; + } + + _snprintf(fullCounterPath, + fullCounterPathLen, + PROCESS_OBJECT_INSTANCE_COUNTER_FMT, + objectName, + imageName, + instance, + counterName); + } else { + if (instance) { + /* + * For paths where the Object has multiple instances. + * + * Examples: + * abstract: "\Object(instance)\Counter" + * actual: "\Processor(0)\% Privileged Time" + */ + fullCounterPathLen += strlen(instance); + fullCounterPathLen += OBJECT_WITH_INSTANCES_COUNTER_FMT_LEN; + } else { + /* + * For "normal" paths. + * + * Examples: + * abstract: "\Object\Counter" + * actual: "\Memory\Available Mbytes" + */ + fullCounterPathLen += OBJECT_COUNTER_FMT_LEN; + } + + fullCounterPath = malloc(fullCounterPathLen + 1); + + if (!fullCounterPath) { + return NULL; + } + + if (instance) { + _snprintf(fullCounterPath, + fullCounterPathLen, + OBJECT_WITH_INSTANCES_COUNTER_FMT, + objectName, + instance, + counterName); + } else { + _snprintf(fullCounterPath, + fullCounterPathLen, + OBJECT_COUNTER_FMT, + objectName, + counterName); + } + } + + fullCounterPath[fullCounterPathLen] = '\0'; + + return fullCounterPath; +} + +/* + * Resolves an index for a PDH artifact to + * a localized, malloc:ed string representation. + * Caller will own the returned malloc:ed string. + * + * @param pdhArtifactIndex PDH index + * @return malloc:ed string representation + * of the requested pdh artifact (localized). + * NULL on failure. + */ +static const char* +getPdhLocalizedArtifact(DWORD pdhArtifactIndex) { + char* pdhLocalizedArtifactString; + + if (lookupNameByIndex(pdhArtifactIndex, + &pdhLocalizedArtifactString) != 0) { + return NULL; + } + + return pdhLocalizedArtifactString; +} + +static void +pdhCleanup(HQUERY* const query, HCOUNTER* const counter) { + if (counter && *counter) { + PdhRemoveCounter_i(*counter); + *counter = NULL; + } + if (query && *query) { + PdhCloseQuery_i(*query); + *query = NULL; + } +} + +static void +destroySingleCounter(SingleCounterQueryP counterQuery) { + if (counterQuery) { + pdhCleanup(&counterQuery->query.query, &counterQuery->counter); + } +} + +static void +destroyMultiCounter(MultipleCounterQueryP multiCounterQuery) { + int i; + if (multiCounterQuery) { + if (multiCounterQuery->counters) { + for (i = 0; i < multiCounterQuery->noOfCounters; i++) { + pdhCleanup(NULL, &multiCounterQuery->counters[i]); + } + free(multiCounterQuery->counters); + multiCounterQuery->counters = NULL; + } + pdhCleanup(&multiCounterQuery->query.query, NULL); + } +} + +static int +openQuery(HQUERY* const query) { + assert(query); + + if (PdhOpenQuery_i(NULL, 0, query) != ERROR_SUCCESS) { + return -1; + } + + return 0; +} + +static int +addCounter(HQUERY query, + const char* const fullCounterPath, + HCOUNTER* const counter) { + + assert(fullCounterPath); + assert(counter); + + if (PdhAddCounter_i(query, + fullCounterPath, + 0, + counter) != ERROR_SUCCESS) { + return -1; + } + + return 0; +} + +/* + * Sets up the supplied SingleCounterQuery to listen for the specified counter. + * + * @param counterQuery the counter query to set up. + * @param fullCounterPath the string specifying the full path to the counter. + * @returns 0 if successful, negative on failure. + */ +static int +initializeSingleCounterQuery(SingleCounterQueryP counterQuery, + const char* const fullCounterPath) { + assert(counterQuery); + assert(fullCounterPath); + + if (openQuery(&counterQuery->query.query) == 0) { + if (addCounter(counterQuery->query.query, + fullCounterPath, + &counterQuery->counter) == 0) { + return 0; + } + } + + return -1; +} + +/* + * Sets up a SingleCounterQuery + * + * param counter the counter query to set up. + * param localizedObject string representing the PDH object to query + * param localizedCounter string representing the PDH counter to query + * param processImageName if the counter query needs the process image name ("java") + * param instance if the counter has instances, this is the instance ("\Processor(0)\") + where 0 is the instance + * param firstSampleOnInit for counters that need two queries to yield their values, + the first query can be issued just after initialization + * + * @returns 0 if successful, negative on failure. + */ +static int +initializeSingleCounter(SingleCounterQueryP const counter, + const char* const localizedObject, + const char* const localizedCounter, + const char* const processImageName, + const char* const instance, + BOOL firstSampleOnInit) { + int retValue = -1; + + const char* fullCounterPath = makeFullCounterPath(localizedObject, + localizedCounter, + processImageName, + instance); + + if (fullCounterPath) { + + assert(counter); + + if (initializeSingleCounterQuery(counter, fullCounterPath) == 0) { + /* + * According to the MSDN documentation, rate counters must be read twice: + * + * "Obtaining the value of rate counters such as Page faults/sec requires that + * PdhCollectQueryData be called twice, with a specific time interval between + * the two calls, before calling PdhGetFormattedCounterValue. Call Sleep to + * implement the waiting period between the two calls to PdhCollectQueryData." + * + * Take the first sample here already to allow for the next (first) "real" sample + * to succeed. + */ + if (firstSampleOnInit) { + PdhCollectQueryData_i(counter->query.query); + } + + retValue = 0; + } + free((char*)fullCounterPath); + } + + return retValue; +} + +static void +perfInit(void) { + InitializePdhCriticalSection(&initializationLock); +} + +static int +getProcessID() { + static int myPid = 0; + if (0 == myPid) { + myPid = _getpid(); + } + return myPid; +} + +/* + * Working against the Process object and it's related counters is inherently problematic + * when using the PDH API: + * + * For PDH, a process is not primarily identified by it's process id, + * but with a sequential number, for example \Process(java#0), \Process(java#1), .... + * The really bad part is that this list is reset as soon as one process exits: + * If \Process(java#1) exits, \Process(java#3) now becomes \Process(java#2) etc. + * + * The PDH query api requires a process identifier to be submitted when registering + * a query, but as soon as the list resets, the query is invalidated (since the name + * changed). + * + * Solution: + * The #number identifier for a Process query can only decrease after process creation. + * + * Therefore we create an array of counter queries for all process object instances + * up to and including ourselves: + * + * Ex. we come in as third process instance (java#2), we then create and register + * queries for the following Process object instances: + * java#0, java#1, java#2 + * + * currentQueryIndexForProcess() keeps track of the current "correct" query + * (in order to keep this index valid when the list resets from underneath, + * ensure to call getCurrentQueryIndexForProcess() before every query involving + * Process object instance data). + */ +static int +currentQueryIndexForProcess(void) { + HQUERY tmpQuery = NULL; + HCOUNTER handleCounter = NULL; + int retValue = -1; + + assert(pdhProcessImageName); + assert(pdhIDProcessCounterFmt); + + if (openQuery(&tmpQuery) == 0) { + int index; + + /* iterate over all instance indexes and try to find our own pid */ + for (index = 0; index < INT_MAX; ++index) { + char fullIDProcessCounterPath[MAX_PATH]; + PDH_FMT_COUNTERVALUE counterValue; + PDH_STATUS res; + + _snprintf(fullIDProcessCounterPath, + MAX_PATH, + pdhIDProcessCounterFmt, + index); + + if (addCounter(tmpQuery, fullIDProcessCounterPath, &handleCounter) != 0) { + break; + } + + res = PdhCollectQueryData_i(tmpQuery); + + if (PDH_INVALID_HANDLE == res || PDH_NO_DATA == res) { + break; + } + + PdhGetFormattedCounterValue_i(handleCounter, + PDH_FMT_LONG, + NULL, + &counterValue); + /* + * This check seems to be needed for Win2k SMP boxes, since + * they for some reason don't return PDH_NO_DATA for non existing + * counters. + */ + if (counterValue.CStatus != PDH_CSTATUS_VALID_DATA) { + break; + } + + if ((LONG)getProcessID() == counterValue.longValue) { + retValue = index; + break; + } + } + } + + pdhCleanup(&tmpQuery, &handleCounter); + + return retValue; +} + +/* + * If successful, returns the #index corresponding to our PID + * as resolved by the pdh query: + * "\Process(java#index)\ID Process" (or localized equivalent) + * + * This function should be called before attempting to read + * from any Process related counter(s), and the return value + * is the index to be used for indexing an array of Process object query's: + * + * Example: + * processTotalCPULoad[currentQueryIndex].query + * + * Returns -1 on failure. + */ +static int +getCurrentQueryIndexForProcess() { + int currentQueryIndex = currentQueryIndexForProcess(); + + assert(currentQueryIndex >= 0 && + currentQueryIndex < numberOfJavaProcessesAtInitialization); + + return currentQueryIndex; +} + +/* + * Returns the PDH string identifying the current process image name. + * Use this name as a qualifier when getting counters from the PDH Process Object + * representing your process. + + * Example: + * "\Process(java#0)\Virtual Bytes" - where "java" is the PDH process + * image name. + * + * Please note that the process image name is not necessarily "java", + * hence the use of GetModuleFileName() to detect the process image name. + * + * @return the process image name to be used when retrieving + * PDH counters from the current process. The caller will + own the returned malloc:ed string. NULL if failure. + */ +static const char* +getPdhProcessImageName() { + char moduleName[MAX_PATH]; + char* processImageName; + char* dotPos; + + // Find our module name and use it to extract the image name used by PDH + DWORD getmfnReturn = GetModuleFileName(NULL, moduleName, sizeof(moduleName)); + + if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + return NULL; + } + + if (getmfnReturn >= MAX_PATH || 0 == getmfnReturn) { + return NULL; + } + + processImageName = strrchr(moduleName, '\\'); //drop path + processImageName++; //skip slash + dotPos = strrchr(processImageName, '.'); //drop .exe + dotPos[0] = '\0'; + + return allocateAndCopy(processImageName); +} + +/* + * Sets up the supplied MultipleCounterQuery to check on the processors via PDH CPU counters. + * TODO: Refactor and prettify as with the the SingleCounter queries + * if more MultipleCounterQueries are discovered/needed. + * + * @param multiCounterCPULoad a pointer to a MultipleCounterQueryS, will be filled in with + * the necessary info to check the PDH processor counters. + * @return 0 if successful, negative on failure. + */ +static int +initializeMultipleCounterForCPUs(MultipleCounterQueryP multiCounterCPULoad) { + DWORD cSize = 0; + DWORD iSize = 0; + DWORD pCount; + DWORD index; + char* processor = NULL; //'Processor' == PDH_PROCESSOR_IDX + char* time = NULL; //'Time' == PDH_PROCESSOR_TIME_IDX + char* instances = NULL; + char* tmp; + int retValue = -1; + PDH_STATUS pdhStat; + + if (lookupNameByIndex(PDH_PROCESSOR_IDX, &processor) != 0) { + goto end; + } + + if (lookupNameByIndex(PDH_PROCESSOR_TIME_IDX, &time) != 0) { + goto end; + } + + //ok, now we have enough to enumerate all processors. + pdhStat = PdhEnumObjectItems_i( + NULL, // reserved + NULL, // local machine + processor, // object to enumerate + NULL, // pass in NULL buffers + &cSize, // and 0 length to get + NULL, // required size + &iSize, // of the buffers in chars + PERF_DETAIL_WIZARD, // counter detail level + 0); + + if (pdhFail(pdhStat)) { + goto end; + } + + instances = calloc(iSize, 1); + + if (!instances) { + goto end; + } + + cSize = 0; + + pdhStat = PdhEnumObjectItems_i( + NULL, // reserved + NULL, // local machine + processor, // object to enumerate + NULL, // pass in NULL buffers + &cSize, + instances, // now allocated to be filled in + &iSize, // and size is known + PERF_DETAIL_WIZARD, // counter detail level + 0); + + if (pdhFail(pdhStat)) { + goto end; + } + + // enumerate the Processor instances ("\Processor(0)", "\Processor(1)", ..., "\Processor(_Total)") + for (pCount = 0, tmp = instances; *tmp != '\0'; tmp = &tmp[strlen(tmp)+1], pCount++); + + assert(pCount == numCpus+1); + + //ok, we now have the number of Processor instances - allocate an HCOUNTER for each + multiCounterCPULoad->counters = (HCOUNTER*)malloc(pCount * sizeof(HCOUNTER)); + + if (!multiCounterCPULoad->counters) { + goto end; + } + + multiCounterCPULoad->noOfCounters = pCount; + + if (openQuery(&multiCounterCPULoad->query.query) != 0) { + goto end; + } + + // fetch instance and register its corresponding HCOUNTER with the query + for (index = 0, tmp = instances; *tmp != '\0'; tmp = &tmp[strlen(tmp)+1], ++index) { + const char* const fullCounterPath = makeFullCounterPath(processor, time, NULL, tmp); + + if (!fullCounterPath) { + goto end; + } + + retValue = addCounter(multiCounterCPULoad->query.query, + fullCounterPath, + &multiCounterCPULoad->counters[index]); + + free((char*)fullCounterPath); + + if (retValue != 0) { + goto end; + } + } + + // Query once to initialize the counters which require at least two samples + // (like the % CPU usage) to calculate correctly. + PdhCollectQueryData_i(multiCounterCPULoad->query.query); + + end: + if (processor) { + free(processor); + } + + if (time) { + free(time); + } + + if (instances) { + free(instances); + } + + return retValue; +} + +/* + * Dynamically sets up function pointers to the PDH library. + * + * @param h HMODULE for the PDH library + * @return 0 on success, negative on failure. + */ +static int +bindPdhFunctionPointers(HMODULE h) { + assert(h); + assert(GetCurrentThreadId() == initializationLock.owningThread); + + /* The 'A' at the end means the ANSI (not the UNICODE) vesions of the methods */ + PdhAddCounter_i = (PdhAddCounterFunc)GetProcAddress(h, "PdhAddCounterA"); + PdhOpenQuery_i = (PdhOpenQueryFunc)GetProcAddress(h, "PdhOpenQueryA"); + PdhCloseQuery_i = (PdhCloseQueryFunc)GetProcAddress(h, "PdhCloseQuery"); + PdhCollectQueryData_i = (PdhCollectQueryDataFunc)GetProcAddress(h, "PdhCollectQueryData"); + PdhGetFormattedCounterValue_i = (PdhGetFormattedCounterValueFunc)GetProcAddress(h, "PdhGetFormattedCounterValue"); + PdhEnumObjectItems_i = (PdhEnumObjectItemsFunc)GetProcAddress(h, "PdhEnumObjectItemsA"); + PdhRemoveCounter_i = (PdhRemoveCounterFunc)GetProcAddress(h, "PdhRemoveCounter"); + PdhLookupPerfNameByIndex_i = (PdhLookupPerfNameByIndexFunc)GetProcAddress(h, "PdhLookupPerfNameByIndexA"); + + if (!PdhAddCounter_i || !PdhOpenQuery_i || + !PdhCloseQuery_i || !PdhCollectQueryData_i || + !PdhGetFormattedCounterValue_i || !PdhEnumObjectItems_i || + !PdhRemoveCounter_i || !PdhLookupPerfNameByIndex_i) + { + return -1; + } + return 0; +} + +/* + * Returns the counter value as a double for the specified query. + * Will collect the query data and update the counter values as necessary. + * + * @param query the query to update (if needed). + * @param c the counter to read. + * @param value where to store the formatted value. + * @param format the format to use (i.e. PDH_FMT_DOUBLE, PDH_FMT_LONG etc) + * @return 0 if no error + * -1 if PdhCollectQueryData fails + * -2 if PdhGetFormattedCounterValue fails + */ +static int +getPerformanceData(UpdateQueryP query, HCOUNTER c, PDH_FMT_COUNTERVALUE* value, DWORD format) { + clock_t now = clock(); + + /* + * Need to limit how often we update the query + * to minimize the Heisenberg effect. + * (PDH behaves erratically if the counters are + * queried too often, especially counters that + * store and use values from two consecutive updates, + * like cpu load.) + */ + if (now - query->lastUpdate > MIN_UPDATE_INTERVAL) { + if (PdhCollectQueryData_i(query->query) != ERROR_SUCCESS) { + return -1; + } + query->lastUpdate = now; + } + + if (PdhGetFormattedCounterValue_i(c, format, NULL, value) != ERROR_SUCCESS) { + return -2; + } + + return 0; +} + +static int +allocateAndInitializePdhConstants() { + const char* pdhLocalizedProcessObject = NULL; + const char* pdhLocalizedIDProcessCounter = NULL; + size_t pdhIDProcessCounterFmtLen; + int currentQueryIndex; + int retValue = -1; + + assert(GetCurrentThreadId() == initializationLock.owningThread); + + assert(!pdhProcessImageName); + pdhProcessImageName = getPdhProcessImageName(); + if (!pdhProcessImageName) { + goto end; + } + + pdhLocalizedProcessObject = getPdhLocalizedArtifact(PDH_PROCESS_IDX); + if (!pdhLocalizedProcessObject) { + goto end; + } + + pdhLocalizedIDProcessCounter = getPdhLocalizedArtifact(PDH_ID_PROCESS_IDX); + if (!pdhLocalizedIDProcessCounter) { + goto end; + } + + assert(!pdhIDProcessCounterFmt); + + pdhIDProcessCounterFmtLen = strlen(pdhProcessImageName); + pdhIDProcessCounterFmtLen += strlen(pdhLocalizedProcessObject); + pdhIDProcessCounterFmtLen += strlen(pdhLocalizedIDProcessCounter); + pdhIDProcessCounterFmtLen += PROCESS_OBJECT_INSTANCE_COUNTER_FMT_LEN; + pdhIDProcessCounterFmtLen += 2; // "%d" + + assert(pdhIDProcessCounterFmtLen < MAX_PATH); + pdhIDProcessCounterFmt = malloc(pdhIDProcessCounterFmtLen + 1); + if (!pdhIDProcessCounterFmt) { + goto end; + } + + /* "\Process(java#%d)\ID Process" */ + _snprintf(pdhIDProcessCounterFmt, + pdhIDProcessCounterFmtLen, + PROCESS_OBJECT_INSTANCE_COUNTER_FMT, + pdhLocalizedProcessObject, + pdhProcessImageName, + "%d", + pdhLocalizedIDProcessCounter); + + pdhIDProcessCounterFmt[pdhIDProcessCounterFmtLen] = '\0'; + + assert(0 == numberOfJavaProcessesAtInitialization); + currentQueryIndex = currentQueryIndexForProcess(); + if (-1 == currentQueryIndex) { + goto end; + } + + numberOfJavaProcessesAtInitialization = currentQueryIndex + 1; + assert(numberOfJavaProcessesAtInitialization >= 1); + + retValue = 0; + + end: + + if (pdhLocalizedProcessObject) { + free((char*)pdhLocalizedProcessObject); + } + + if (pdhLocalizedIDProcessCounter) { + free((char*)pdhLocalizedIDProcessCounter); + } + + return retValue; +} + +static void +deallocatePdhConstants() { + assert(GetCurrentThreadId() == initializationLock.owningThread); + + if (pdhProcessImageName) { + free((char*)pdhProcessImageName); + pdhProcessImageName = NULL; + } + + if (pdhIDProcessCounterFmt) { + free(pdhIDProcessCounterFmt); + pdhIDProcessCounterFmt = NULL; + } + + numberOfJavaProcessesAtInitialization = 0; +} + +static int +initializeCPUCounters() { + SYSTEM_INFO si; + char* localizedProcessObject; + char* localizedProcessorTimeCounter; + int i; + int retValue = -1; + + assert(GetCurrentThreadId() == initializationLock.owningThread); + + assert(0 == numCpus); + GetSystemInfo(&si); + numCpus = si.dwNumberOfProcessors; + assert(numCpus >= 1); + + /* Initialize the denominator for the jvm load calculations */ + assert(.0 == cpuFactor); + cpuFactor = numCpus * 100; + + if (lookupNameByIndex(PDH_PROCESS_IDX, + &localizedProcessObject) == 0) { + + if (lookupNameByIndex(PDH_PROCESSOR_TIME_IDX, + &localizedProcessorTimeCounter) == 0) { + + assert(processTotalCPULoad); + assert(pdhProcessImageName); + + for (i = 0; i < numberOfJavaProcessesAtInitialization; ++i) { + char instanceIndexBuffer[32]; + retValue = initializeSingleCounter(&processTotalCPULoad[i], + localizedProcessObject, + localizedProcessorTimeCounter, + pdhProcessImageName, + itoa(i, instanceIndexBuffer, 10), + TRUE); + if (retValue != 0) { + break; + } + } + free(localizedProcessorTimeCounter); + } + free(localizedProcessObject); + } + + if (retValue != 0) { + return -1; + } + + assert(multiCounterCPULoad); + return initializeMultipleCounterForCPUs(multiCounterCPULoad); +} + +static void +deallocateCPUCounters() { + int i; + + assert(GetCurrentThreadId() == initializationLock.owningThread); + + if (processTotalCPULoad) { + for (i = 0; i < numberOfJavaProcessesAtInitialization; ++i) { + destroySingleCounter(&processTotalCPULoad[i]); + } + free(processTotalCPULoad); + processTotalCPULoad = NULL; + } + + if (multiCounterCPULoad) { + destroyMultiCounter(multiCounterCPULoad); + free(multiCounterCPULoad); + multiCounterCPULoad = NULL; + } + + cpuFactor = .0; + numCpus = 0; +} + +static void +pdhInitErrorHandler(HMODULE h) { + assert(GetCurrentThreadId() == initializationLock.owningThread); + + deallocatePdhConstants(); + + if (h) { + FreeLibrary(h); + } +} + +/* + * Helper to initialize the PDH library, function pointers and constants. + * + * @return 0 if successful, negative on failure. + */ +static int +pdhInit() { + static BOOL initialized = FALSE; + int retValue; + + if (initialized) { + return 0; + } + + retValue = 0; + + EnterPdhCriticalSection(&initializationLock); { + if (!initialized) { + HMODULE h = NULL; + if ((h = LoadLibrary("pdh.dll")) == NULL) { + retValue = -1; + } else if (bindPdhFunctionPointers(h) < 0) { + retValue = -1; + } else if (allocateAndInitializePdhConstants() < 0) { + retValue = -1; + } + + if (0 == retValue) { + initialized = TRUE; + } else { + pdhInitErrorHandler(h); + } + } + } LeavePdhCriticalSection(&initializationLock); + + return retValue; +} + +static int +allocateCPUCounters() { + assert(GetCurrentThreadId() == initializationLock.owningThread); + assert(numberOfJavaProcessesAtInitialization >= 1); + assert(!processTotalCPULoad); + assert(!multiCounterCPULoad); + + /* + * Create an array of Process object queries, for each instance + * up to and including our own (java#0, java#1, java#2, ...). + */ + processTotalCPULoad = calloc(numberOfJavaProcessesAtInitialization, + sizeof(SingleCounterQueryS)); + + if (!processTotalCPULoad) { + return -1; + } + + multiCounterCPULoad = calloc(1, sizeof(MultipleCounterQueryS)); + + if (!multiCounterCPULoad) { + return -1; + } + + return 0; +} + +static int +initializePdhCPUCounters() { + static BOOL initialized = FALSE; + int retValue; + + if (initialized) { + return 0; + } + + retValue = 0; + + EnterPdhCriticalSection(&initializationLock); { + if (!initialized) { + if (pdhInit() < 0) { + retValue = -1; + } else if (allocateCPUCounters() < 0) { + retValue = -1; + } else if (initializeCPUCounters() < 0) { + retValue = -1; + } + + if (0 == retValue) { + initialized = TRUE; + } else { + deallocateCPUCounters(); + } + } + } LeavePdhCriticalSection(&initializationLock); + + return retValue; +} + +static int +perfCPUInit() { + return initializePdhCPUCounters(); +} + +static double +perfGetProcessCPULoad() { + PDH_FMT_COUNTERVALUE cv; + int currentQueryIndex; + + if (perfCPUInit() < 0) { + // warn? + return -1.0; + } + + currentQueryIndex = getCurrentQueryIndexForProcess(); + + if (getPerformanceData(&processTotalCPULoad[currentQueryIndex].query, + processTotalCPULoad[currentQueryIndex].counter, + &cv, + PDH_FMT_DOUBLE | PDH_FMT_NOCAP100) == 0) { + double d = cv.doubleValue / cpuFactor; + d = min(1, d); + d = max(0, d); + return d; + } + return -1.0; +} + +static double +perfGetCPULoad(int which) { + PDH_FMT_COUNTERVALUE cv; + HCOUNTER c; + + if (perfCPUInit() < 0) { + // warn? + return -1.0; + } + + if (-1 == which) { + c = multiCounterCPULoad->counters[multiCounterCPULoad->noOfCounters - 1]; + } else { + if (which < multiCounterCPULoad->noOfCounters) { + c = multiCounterCPULoad->counters[which]; + } else { + return -1.0; + } + } + if (getPerformanceData(&multiCounterCPULoad->query, c, &cv, PDH_FMT_DOUBLE ) == 0) { + return cv.doubleValue / 100; + } + return -1.0; +} + +JNIEXPORT jdouble JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getSystemCpuLoad0 +(JNIEnv *env, jobject dummy) +{ + return perfGetCPULoad(-1); +} + +JNIEXPORT jdouble JNICALL +Java_com_sun_management_internal_OperatingSystemImpl_getProcessCpuLoad0 +(JNIEnv *env, jobject dummy) +{ + return perfGetProcessCPULoad(); +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/management/CheckSomeMXBeanImplPackage.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.lang.management.ManagementFactory; +import java.lang.management.PlatformManagedObject; + +/* + * @test + * @bug 8042901 + * @summary If jdk.management is present, GarbageCollectorMXBean and ThreadMXBean + * must be from com.sun.management.internal + * @author Shanliang Jiang + */ +public class CheckSomeMXBeanImplPackage { + private static String implPackageName = "com.sun.management.internal"; + + public static void main(String[] args) throws Exception { + boolean present = false; + try { + Class.forName("com.sun.management.GarbageCollectorMXBean"); + present = true; + } catch (ClassNotFoundException cnfe) {} + + if (present) { + Class <? extends PlatformManagedObject> klazz = + java.lang.management.GarbageCollectorMXBean.class; + for (Object obj : + ManagementFactory.getPlatformMXBeans(klazz)) { + check(klazz.getName(), obj); + } + + klazz = com.sun.management.GarbageCollectorMXBean.class; + for (Object obj : + ManagementFactory.getPlatformMXBeans(klazz)) { + check(klazz.getName(), obj); + } + + klazz = java.lang.management.ThreadMXBean.class; + check(klazz.getName(), + ManagementFactory.getPlatformMXBean(klazz)); + + klazz = com.sun.management.ThreadMXBean.class; + check(klazz.getName(), + ManagementFactory.getPlatformMXBean(klazz)); + + System.out.println("--- PASSED!"); + } else { + System.out.println("--- Skip the test, jdk.management module is not present!"); + } + } + + private static void check(String mbeanName, Object impl) { + if (!impl.getClass().getName().startsWith(implPackageName)) { + throw new RuntimeException(mbeanName+" implementation package " + + "should be: " + implPackageName + + ", but got: " + impl.getClass()); + } else { + System.out.println("--- Good, "+mbeanName+" got right implementation: " + impl); + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/com/sun/management/VMOptionOpenDataTest.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import com.sun.management.VMOption; +import java.io.InvalidObjectException; +import java.util.Objects; +import javax.management.openmbean.OpenDataException; +import sun.management.MappedMXBeanType; + +/* + * @test + * @bug 8042901 + * @summary Check that MappedMXBeanType.toOpenTypeData supports VMOption + * @author Shanliang Jiang + */ +public class VMOptionOpenDataTest { + public static void main(String[] args) throws Exception { + System.out.println("--- VMOptionOpenDataTest-main: Checking that " + + "MappedMXBeanType.toOpenTypeData supports VMOption"); + Exception failed = null; + try { + VMOption vo = new VMOption("toto", "titi", true, VMOption.Origin.OTHER); + System.out.println("--- Construct a VMOption object: \"" + vo + "\""); + + Object open = MappedMXBeanType.toOpenTypeData(vo, VMOption.class); + System.out.println("--- Map it to an open type: \"" + open +" \""); + + Object back = MappedMXBeanType.toJavaTypeData(open, VMOption.class); + System.out.println("--- Map it back to java type: \"" + back +" \""); + + if (back == null) { + failed = new RuntimeException("Failed, mapping back got null."); + } else if (!(back instanceof VMOption)) { + failed = new RuntimeException("Failed, not mapped back to a VMOption: " + +back.getClass()); + } else { + VMOption mapBack = (VMOption)back; + if (!Objects.equals(vo.getName(), mapBack.getName()) || + !Objects.equals(vo.getOrigin(), mapBack.getOrigin()) || + !Objects.equals(vo.getValue(), mapBack.getValue()) || + vo.isWriteable() != mapBack.isWriteable()) { + failed = new RuntimeException( + "Failed, failed to map back the original VMOtion."); + } + } + } catch (OpenDataException | InvalidObjectException ode) { + failed = ode; + } + if (failed == null) { + System.out.println("--- PASSED!"); + } else { + System.out.println("--- Failed: "+failed.getMessage()); + throw failed; + } + } +}
--- a/jdk/test/java/lang/instrument/NMTHelper.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/test/java/lang/instrument/NMTHelper.java Fri Apr 17 09:40:02 2015 +0200 @@ -27,8 +27,9 @@ import java.util.regex.Pattern; import java.util.Arrays; import java.util.stream.Collectors; -import sun.management.ManagementFactoryHelper; -import com.sun.management.DiagnosticCommandMBean; +import java.lang.management.ManagementFactory; +import javax.management.MalformedObjectNameException; +import javax.management.ObjectName; public class NMTHelper { @@ -53,7 +54,12 @@ } private static String executeDcmd(String cmd, String ... args) { - DiagnosticCommandMBean dcmd = ManagementFactoryHelper.getDiagnosticCommandMBean(); + ObjectName oname = null; + try { + oname = ObjectName.getInstance("com.sun.management:type=DiagnosticCommand"); + } catch (MalformedObjectNameException mone) { + throw new RuntimeException(mone); + } Object[] dcmdArgs = {args}; String[] signature = {String[].class.getName()}; @@ -63,7 +69,8 @@ System.out.println("Output from Dcmd '" + cmdString + "' is being written to file " + f); try (FileWriter fw = new FileWriter(f)) { fw.write("> " + cmdString + ":"); - String result = (String) dcmd.invoke(cmd, dcmdArgs, signature); + String result = (String)ManagementFactory.getPlatformMBeanServer(). + invoke(oname, cmd, dcmdArgs, signature); fw.write(result); return result; } catch(Exception ex) {
--- a/jdk/test/java/lang/instrument/RedefineMethodInBacktraceApp.java Wed Apr 15 13:27:39 2015 +0200 +++ b/jdk/test/java/lang/instrument/RedefineMethodInBacktraceApp.java Fri Apr 17 09:40:02 2015 +0200 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -31,7 +31,8 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.concurrent.CountDownLatch; -import sun.management.ManagementFactoryHelper; +import javax.management.JMX; +import javax.management.ObjectName; /** * When an exception is thrown, the JVM collects just enough information @@ -103,8 +104,11 @@ String[] threadPrintArgs = {}; Object[] dcmdArgs = {threadPrintArgs}; String[] signature = {String[].class.getName()}; - DiagnosticCommandMBean dcmd = ManagementFactoryHelper.getDiagnosticCommandMBean(); - System.out.println(dcmd.invoke("threadPrint", dcmdArgs, signature)); + System.out.println(ManagementFactory.getPlatformMBeanServer().invoke( + ObjectName.getInstance("com.sun.management:type=DiagnosticCommand"), + "threadPrint", + dcmdArgs, + signature)); // release the thread stop.countDown();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/sun/management/PlatformMBeanProviderConstructorCheck.java Fri Apr 17 09:40:02 2015 +0200 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +import java.security.AccessControlException; +import java.security.Permission; +import java.security.Policy; +import java.security.ProtectionDomain; +import java.util.List; + +/* + * @test + * @bug 8042901 + * @summary Check permission for PlatformMBeanProvider Constructor + * @author Shanliang Jiang + */ +public class PlatformMBeanProviderConstructorCheck { + public static void main(String[] args) throws Exception { + Policy origPolicy = Policy.getPolicy(); + SecurityManager origSM = System.getSecurityManager(); + try { + System.out.println("---PlatformMBeanProviderConstructorCheck starting..."); + + Policy.setPolicy(new MyPolicy()); + System.setSecurityManager(new SecurityManager()); + + System.out.println("---PlatformMBeanProviderConstructorCheck Testing without permission..."); + try { + new MyProvider(); + throw new RuntimeException("Does not get expected AccessControlException!"); + } catch (AccessControlException ace) { + System.out.println("---PlatformMBeanProviderConstructorCheck got the expected exception: " + + ace); + } + + System.out.println("---PlatformMBeanProviderConstructorCheck Testing with permission..."); + MyPolicy.allowed = true; + new MyProvider(); + + System.out.println("---PlatformMBeanProviderConstructorCheck PASSED!"); + } finally { + System.setSecurityManager(origSM); + Policy.setPolicy(origPolicy); + } + } + + private static class MyPolicy extends Policy { + private static String permName = "sun.management.spi.PlatformMBeanProvider.subclass"; + private static boolean allowed = false; + + @Override + public boolean implies(ProtectionDomain domain, Permission permission) { + if (permName.equals(permission.getName())) { + System.out.println("---MyPolicy-implies checks permission for " + +permName+" and returns "+allowed); + + return allowed; + } else { + return true; + } + } + } + + private static class MyProvider extends sun.management.spi.PlatformMBeanProvider { + @Override + public List<PlatformComponent<?>> getPlatformComponentList() { + return null; + } + } +}