# HG changeset patch # User sjiang # Date 1429256402 -7200 # Node ID e37c7eba132fb18518fd779d6b09c30c7c9205a2 # Parent ca83b4cae3636571af16833cf0d16f1bd08f33cf 8042901: Allow com.sun.management to be in a different module to java.lang.management Reviewed-by: mchung, dfuchs, erikj, jbachorik diff -r ca83b4cae363 -r e37c7eba132f jdk/make/lib/Lib-java.management.gmk --- 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, \ diff -r ca83b4cae363 -r e37c7eba132f jdk/make/lib/Lib-jdk.management.gmk --- /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) + +################################################################################ diff -r ca83b4cae363 -r e37c7eba132f jdk/make/mapfiles/libmanagement/mapfile-vers --- 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; diff -r ca83b4cae363 -r e37c7eba132f jdk/make/mapfiles/libmanagement_ext/mapfile-vers --- /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: + *; +}; diff -r ca83b4cae363 -r e37c7eba132f jdk/make/src/classes/build/tools/module/boot.modules --- 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 diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/META-INF/services/sun.management.spi.PlatformMBeanProvider --- 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 diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/DiagnosticCommandMBean.java --- 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. - * - *

The {@code DiagnosticCommandMBean} is registered to the - * {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer - * platform MBeanServer} as are other platform MBeans. - * - *

The {@link javax.management.ObjectName ObjectName} for uniquely identifying - * the diagnostic MBean within an MBeanServer is: - *

- * {@code com.sun.management:type=DiagnosticCommand} - *
- * - *

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 diagnostic command is represented as an operation of - * the {@code DiagnosticCommandMBean} interface. Each diagnostic command has: - *

- * - * The recommended way to transform a diagnostic command name into a MBean - * operation name is as follows: - * - * - *

The diagnostic command name is always provided with the meta-data on the - * operation in a field named {@code dcmd.name} (see below). - * - *

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. - * - *

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. - * - *

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: - *

- * - *

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: - *

- * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameTypeDescription
dcmd.nameStringThe original diagnostic command name (not the operation name)
dcmd.descriptionStringThe diagnostic command description
dcmd.helpStringThe full help message for this diagnostic command (same output as - * the one produced by the 'help' command)
dcmd.vmImpactStringThe 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
dcmd.enabledbooleanTrue if the diagnostic command is enabled, false otherwise
dcmd.permissionClassStringSome 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 - *
dcmd.permissionNameStringThe fist argument of the permission required to execute this - * diagnostic command or null if no permission is required
dcmd.permissionActionStringThe 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
dcmd.argumentsDescriptorA Descriptor instance containing the descriptions of options and - * arguments supported by the diagnostic command (see below)
- *

- * - *

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: - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
NameTypeDescription
dcmd.arg.nameStringThe name of the parameter
dcmd.arg.typeStringThe 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. - *
dcmd.arg.descriptionStringThe parameter description
dcmd.arg.isMandatorybooleanTrue if the parameter is mandatory, false otherwise
dcmd.arg.isOptionbooleanTrue if the parameter is an option, false if it is an argument
dcmd.arg.isMultiplebooleanTrue if the parameter can be specified several times, false - * otherwise
- * - *

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 - * - * {@code "jmx.mbean.info.changed"} and a - * {@linkplain javax.management.Notification#getUserData() userData} that - * is the new {@code MBeanInfo}. - * - * @since 1.8 - */ -public interface DiagnosticCommandMBean extends DynamicMBean -{ - -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/GarbageCollectionNotificationInfo.java --- 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 - * - *

- * 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: - * - *

  • The name of the garbage collector used to perform the collection.
  • - *
  • The action performed by the garbage collector.
  • - *
  • The cause of the garbage collection action.
  • - *
  • 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.
  • - * - * - *

    - * 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: - * - *

    - *      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);
    - *          ....
    - *      }
    - * 
    - * - *

    - * The type of the notification emitted by a {@code GarbageCollectorMXBean} is: - *

    - **/ - -@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: - *
    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Attribute NameType
    gcName{@code java.lang.String}
    gcAction{@code java.lang.String}
    gcCause{@code java.lang.String}
    gcInfo{@code javax.management.openmbean.CompositeData}
    - *
    - * - * @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; - } - -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/GarbageCollectorMXBean.java --- 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. - * - *

    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, null is returned. - * The collector-specific attributes, if any, can be obtained - * via the {@link CompositeData CompositeData} interface. - *

    - * MBeanServer access: - * The mapped type of GcInfo is CompositeData - * with attributes specified in {@link GcInfo#from GcInfo}. - * - * @return a GcInfo object representing - * the most GC information; or null if no GC - * information available. - */ - public GcInfo getLastGcInfo(); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/GcInfo.java --- 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: - *

    - * - *
    - * - *

    - * GcInfo 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. - * - *

    MXBean Mapping

    - * GcInfo 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 usageBeforeGc; - private final Map 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(poolNames.length); - this.usageAfterGc = new HashMap(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 Map of the name of a memory pool - * to the memory usage of the corresponding - * memory pool before GC starts. - * - * @return a Map of memory pool names to the memory - * usage of a memory pool before GC starts. - */ - public Map getMemoryUsageBeforeGc() { - return Collections.unmodifiableMap(usageBeforeGc); - } - - /** - * Returns the memory usage of all memory pools - * at the end of this GC. - * This method returns - * a Map of the name of a memory pool - * to the memory usage of the corresponding - * memory pool when GC finishes. - * - * @return a Map of memory pool names to the memory - * usage of a memory pool when GC finishes. - */ - public Map getMemoryUsageAfterGc() { - return Collections.unmodifiableMap(usageAfterGc); - } - - /** - * Returns a GcInfo object represented by the - * given CompositeData. The given - * CompositeData must contain - * all the following attributes: - * - *

    - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Attribute NameType
    indexjava.lang.Long
    startTimejava.lang.Long
    endTimejava.lang.Long
    memoryUsageBeforeGcjavax.management.openmbean.TabularData
    memoryUsageAfterGcjavax.management.openmbean.TabularData
    - *
    - * - * @throws IllegalArgumentException if cd does not - * represent a GcInfo object with the attributes - * described above. - * - * @return a GcInfo object represented by cd - * if cd is not null; null 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(); - } - - /** - *

    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; - } -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java --- 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. - * - *

    The diagnostic MBean is registered to the platform MBeanServer - * as are other platform MBeans. - * - *

    The ObjectName for uniquely identifying the diagnostic - * MXBean within an MBeanServer is: - *

    - * com.sun.management:type=HotSpotDiagnostic - *
    -.* - * 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 outputFile file in the same - * format as the hprof heap dump. - *

    - * If this method is called remotely from another process, - * the heap dump output is written to a file named outputFile - * 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 true dump only live objects - * i.e. objects that are reachable from others - * @throws IOException if the outputFile - * cannot be created, opened, or written to. - * @throws UnsupportedOperationException if this operation is not supported. - * @throws NullPointerException if outputFile is null. - * @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 VMOption 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 VMOption objects for all diagnostic options. - */ - public java.util.List getDiagnosticOptions(); - - /** - * Returns a VMOption object for a VM option of the given - * name. - * - * @return a VMOption object for a VM option of the given name. - * @throws NullPointerException if name is null. - * @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 VMOption - * object returned by the {@link #getVMOption} method or - * the {@link #getDiagnosticOptions} method. This method does - * not change the value of this VMOption 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 null. - * - * @throws java.lang.SecurityException - * if a security manager exists and the caller does not have - * ManagementPermission("control"). - */ - public void setVMOption(String name, String value); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/OperatingSystemMXBean.java --- 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. - * - *

    - * The OperatingSystemMXBean 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 -1 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 -1 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 -1 if the - * the platform does not support this operation. - * - * @return the CPU time used by the process in nanoseconds, - * or -1 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(); - -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/ThreadMXBean.java --- 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. - *

    - * 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. - *

    - * 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. - *

    - * 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. - *

    - * 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. - *

    - * 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. - *

    - * 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); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/UnixOperatingSystemMXBean.java --- 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(); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/VMOption.java --- 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 origin}. - *

    - * 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 VMOption contains the value of a VM option - * and the origin of that value at the time this VMOption - * object was constructed. The value of the VM option - * may be changed after the VMOption object was constructed, - * - * @see - * Java Virtual Machine - * @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 VMOption. - * - * @param name Name of a VM option. - * @param value Value of a VM option. - * @param writeable true if a VM option can be set dynamically, - * or false otherwise. - * @param origin where the value of a VM option came from. - * - * @throws NullPointerException if the name or value is null - */ - public VMOption(String name, String value, boolean writeable, Origin origin) { - this.name = name; - this.value = value; - this.writeable = writeable; - this.origin = origin; - } - - /** - * Constructs a VMOption 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 VMOption was created. The value could have been changed. - * - * @return the value of the VM option at the time when - * this VMOption 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 true if this VM option is writeable; false - * otherwise. - */ - public boolean isWriteable() { - return writeable; - } - - public String toString() { - return "VM option: " + getName() + - " value: " + value + " " + - " origin: " + origin + " " + - (writeable ? "(read-write)" : "(read-only)"); - } - - /** - * Returns a VMOption object represented by the - * given CompositeData. The given CompositeData - * must contain the following attributes: - *

    - *

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Attribute NameType
    namejava.lang.String
    valuejava.lang.String
    originjava.lang.String
    writeablejava.lang.Boolean
    - *
    - * - * @param cd CompositeData representing a VMOption - * - * @throws IllegalArgumentException if cd does not - * represent a VMOption with the attributes described - * above. - * - * @return a VMOption object represented by cd - * if cd is not null; - * null 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); - } - - } - - -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java --- 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> mxbeanList; - - public PlatformMBeanProviderImpl() { - mxbeanList = Collections.unmodifiableList(init()); - } - - @Override - public List> getPlatformComponentList() { - return mxbeanList; - } - - private List> init() { - ArrayList> initMBeanList = new ArrayList<>(); - /** - * Garbage Collector in the Java virtual machine. - */ - initMBeanList.add(new PlatformComponent() { - private final Set garbageCollectorMXBeanInterfaceNames - = Collections.unmodifiableSet( - Stream.of("java.lang.management.MemoryManagerMXBean", - "java.lang.management.GarbageCollectorMXBean", - "com.sun.management.GarbageCollectorMXBean") - .collect(Collectors.toSet())); - - @Override - public Set> 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 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 nameToMBeanMap() { - List list - = ManagementFactoryHelper.getGarbageCollectorMXBeans();; - Map map; - if (list.isEmpty()) { - map = Collections.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() { - private final Set operatingSystemMXBeanInterfaceNames - = Collections.unmodifiableSet( - Stream.of("java.lang.management.OperatingSystemMXBean", - "com.sun.management.OperatingSystemMXBean", - "com.sun.management.UnixOperatingSystemMXBean") - .collect(Collectors.toSet())); - - @Override - public Set> 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 mbeanInterfaceNames() { - return operatingSystemMXBeanInterfaceNames; - } - - @Override - public String getObjectNamePattern() { - return ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME; - } - - @Override - public Map nameToMBeanMap() { - return Collections.singletonMap( - ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, - ManagementFactoryHelper.getOperatingSystemMXBean()); - } - }); - - /** - * Diagnostic support for the HotSpot Virtual Machine. - */ - initMBeanList.add(new PlatformComponent() { - private final Set hotSpotDiagnosticMXBeanInterfaceNames = - Collections.unmodifiableSet(Collections.singleton("com.sun.management.HotSpotDiagnosticMXBean")); - - @Override - public Set> mbeanInterfaces() { - return Collections.singleton(com.sun.management.HotSpotDiagnosticMXBean.class); - } - - @Override - public Set mbeanInterfaceNames() { - return hotSpotDiagnosticMXBeanInterfaceNames; - } - - @Override - public String getObjectNamePattern() { - return "com.sun.management:type=HotSpotDiagnostic"; - } - - @Override - public Map nameToMBeanMap() { - return Collections.singletonMap( - "com.sun.management:type=HotSpotDiagnostic", - ManagementFactoryHelper.getDiagnosticMXBean()); - } - }); - - /** - * DynamicMBean - */ - HashMap dynmbeans - = ManagementFactoryHelper.getPlatformDynamicMBeans(); - final Set dynamicMBeanInterfaceNames = - Collections.unmodifiableSet(Collections.singleton("javax.management.DynamicMBean")); - for (Map.Entry e : dynmbeans.entrySet()) { - initMBeanList.add(new PlatformComponent() { - @Override - public Set mbeanInterfaceNames() { - return dynamicMBeanInterfaceNames; - } - - @Override - public Set> 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 nameToMBeanMap() { - return Collections.singletonMap( - e.getKey().getCanonicalName(), - e.getValue()); - } - }); - } - initMBeanList.trimToSize(); - return initMBeanList; - } -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/com/sun/management/package-info.java --- 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 - * - * java.lang.management API and also defines the management - * interface for some other components for the platform. - * - *

    - * All platform MBeans are registered in the platform MBeanServer - * which can be obtained via the - * - * java.lang.management.ManagementFactory.getPlatformMBeanServer - * - * @author Mandy Chung - * @since 1.5 - */ - -@jdk.Exported -package com.sun.management; diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/java/lang/management/DefaultPlatformMBeanProvider.java --- 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> 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 dynmbeans - = ManagementFactoryHelper.getPlatformDynamicMBeans(); - final Set dynamicMBeanInterfaceNames = - Collections.unmodifiableSet(Collections.singleton("javax.management.DynamicMBean")); - for (Map.Entry e : dynmbeans.entrySet()) { - initMBeanList.add(new PlatformComponent() { - @Override - public Set> mbeanInterfaces() { - return Collections.emptySet(); - } - - @Override - public Set mbeanInterfaceNames() { - return dynamicMBeanInterfaceNames; - } - - @Override - public String getObjectNamePattern() { - return e.getKey().getCanonicalName(); - } - - @Override - public Map nameToMBeanMap() { - return Collections.singletonMap( - e.getKey().getCanonicalName(), - e.getValue()); - } - }); - } - initMBeanList.trimToSize(); return initMBeanList; } diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/java/lang/management/ManagementFactory.java --- 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) () -> cls.getClassLoader()); + (PrivilegedAction) () -> 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("<>", "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) () -> { + System.loadLibrary("management"); + return null; + }); + } } diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/DiagnosticCommandArgumentInfo.java --- 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: - *

    - * <command name> [<option>=<value>] [<argument_value>] - *
    - * Example: - *
    - * command_name option1=value1 option2=value argumentA argumentB argumentC - *
    - * 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; - } -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/DiagnosticCommandImpl.java --- 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 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 { - @Override - public int compare(MBeanOperationInfo o1, MBeanOperationInfo o2) { - return o1.getName().compareTo(o2.getName()); - } - } - - @Override - public MBeanInfo getMBeanInfo() { - SortedSet operations = new TreeSet<>(new OperationInfoComparator()); - Map 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 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 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 allargmap = new HashMap<>(); - for (DiagnosticCommandArgumentInfo arginfo : w.info.getArgumentsInfo()) { - HashMap 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); - -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/DiagnosticCommandInfo.java --- 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 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 getArgumentsInfo() { - return arguments; - } - - DiagnosticCommandInfo(String name, String description, - String impact, String permissionClass, - String permissionName, String permissionAction, - boolean enabled, - List 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; - } -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/Flag.java --- 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 flags = getFlags(names, 1); - if (flags.isEmpty()) { - return null; - } else { - // flags should have only one element - return flags.get(0); - } - } - - static List getAllFlags() { - int numFlags = getInternalFlagCount(); - - // Get all internal flags with names = null - return getFlags(null, numFlags); - } - - private static List getFlags(String[] names, int numFlags) { - Flag[] flags = new Flag[numFlags]; - int count = getFlags(names, flags, numFlags); - - List 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() { - public Void run() { - System.loadLibrary("management"); - return null; - } - }); - initialize(); - } - private static native void initialize(); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/GarbageCollectionNotifInfoCompositeData.java --- 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() { - 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 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; -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/GarbageCollectorImpl.java --- 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 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); - } diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/GcInfoBuilder.java --- 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); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/GcInfoCompositeData.java --- 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() { - 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() { - 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 - 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 cast(Object x) { - return (Map) x; - } - public static Map - getMemoryUsageAfterGc(CompositeData cd) { - try { - TabularData td = (TabularData) cd.get(MEMORY_USAGE_AFTER_GC); - //return (Map) - 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; -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/HotSpotDiagnostic.java --- 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 getDiagnosticOptions() { - List allFlags = Flag.getAllFlags(); - List 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"); - } -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/LazyCompositeData.java --- 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"); diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/ManagementFactory.java --- 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); - } -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/ManagementFactoryHelper.java --- 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 getGarbageCollectorMXBeans() { + public static List getGarbageCollectorMXBeans() { MemoryManagerMXBean[] mgrs = MemoryImpl.getMemoryManagers(); List 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 getPlatformDynamicMBeans() { - HashMap 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() { - 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); + } } diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/MappedMXBeanType.java --- 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 list = (List) 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 map = (Map) 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() { + 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() { - public Method[] run() { - return javaClass.getMethods(); - } - }); + public Method[] run() { + return javaClass.getMethods(); + } + }); final List names = new ArrayList<>(); final List> 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) { diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/NotificationEmitterSupport.java --- 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(); } diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/ThreadImpl.java --- 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); } diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/Util.java --- 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); } } diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/VMOptionCompositeData.java --- 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; -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/classes/sun/management/spi/PlatformMBeanProvider.java --- 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; } diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/native/libmanagement/DiagnosticCommandImpl.c --- 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 -#include -#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; iNewStringUTF(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; iGetObjectArrayElement(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); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/native/libmanagement/Flag.c --- 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 -#include -#include -#include -#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); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/native/libmanagement/GarbageCollectorImpl.c --- 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); - } -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/native/libmanagement/GcInfoBuilder.c --- 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 -#include -#include -#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); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/share/native/libmanagement/HotSpotDiagnostic.c --- 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 -#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); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/unix/classes/sun/management/OperatingSystemImpl.java --- 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(); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/unix/native/libmanagement/LinuxOperatingSystem.c --- 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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) (ausedKernel < 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; - } -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/unix/native/libmanagement/MacosxOperatingSystem.c --- 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 -#include -#include - -#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; - } diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/unix/native/libmanagement/OperatingSystemImpl.c --- 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 -#include -#if defined(_ALLBSD_SOURCE) -#include -#ifdef __APPLE__ -#include -#include -#include -#include -#include -#endif -#elif !defined(_AIX) -#include -#endif -#include -#include -#ifndef _ALLBSD_SOURCE -#include -#endif -#include -#include -#include -#include -#include -#include -#include - -#if defined(_AIX) -#include -#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 */ -#define _STRUCTURED_PROC 1 -#include - -#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; -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/unix/native/libmanagement/SolarisOperatingSystem.c --- 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 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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(); -} - diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/windows/classes/sun/management/OperatingSystemImpl.java --- 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(); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/java.management/windows/native/libmanagement/OperatingSystemImpl.c --- 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 -#include -#include - -#include -#pragma warning (push,0) -#include -#pragma warning (pop) -#include -#include -#include -#include - -/* Disable warnings due to broken header files from Microsoft... */ -#pragma warning(push, 3) -#include -#include -#include -#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(); -} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/linux/native/libmanagement_ext/UnixOperatingSystem.c --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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) (ausedKernel < 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; + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/macosx/native/libmanagement_ext/UnixOperatingSystem.c --- /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 +#include +#include + +#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; + } diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/META-INF/services/sun.management.spi.PlatformMBeanProvider --- /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 diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/DiagnosticCommandMBean.java --- /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. + * + *

    The {@code DiagnosticCommandMBean} is registered to the + * {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer + * platform MBeanServer} as are other platform MBeans. + * + *

    The {@link javax.management.ObjectName ObjectName} for uniquely identifying + * the diagnostic MBean within an MBeanServer is: + *

    + * {@code com.sun.management:type=DiagnosticCommand} + *
    + * + *

    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 diagnostic command is represented as an operation of + * the {@code DiagnosticCommandMBean} interface. Each diagnostic command has: + *

      + *
    • the diagnostic command name which is the name being referenced in + * the HotSpot Virtual Machine
    • + *
    • 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
    • + *
    + * + * The recommended way to transform a diagnostic command name into a MBean + * operation name is as follows: + *
      + *
    • All characters from the first one to the first dot are set to be + * lower-case characters
    • + *
    • Every dot or underline character is removed and the following + * character is set to be an upper-case character
    • + *
    • All other characters are copied without modification
    • + *
    + * + *

    The diagnostic command name is always provided with the meta-data on the + * operation in a field named {@code dcmd.name} (see below). + * + *

    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. + * + *

    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. + * + *

    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: + *

      + *
    • {@link javax.management.MBeanOperationInfo#getName() getName()} + * returns the operation name generated from the diagnostic command name
    • + *
    • {@link javax.management.MBeanOperationInfo#getDescription() getDescription()} + * returns the diagnostic command description + * (the same as the one return in the 'help' command)
    • + *
    • {@link javax.management.MBeanOperationInfo#getImpact() getImpact()} + * returns ACTION_INFO
    • + *
    • {@link javax.management.MBeanOperationInfo#getReturnType() getReturnType()} + * returns {@code java.lang.String}
    • + *
    • {@link javax.management.MBeanOperationInfo#getDescriptor() getDescriptor()} + * returns a Descriptor instance (see below)
    • + *
    + * + *

    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: + *

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    NameTypeDescription
    dcmd.nameStringThe original diagnostic command name (not the operation name)
    dcmd.descriptionStringThe diagnostic command description
    dcmd.helpStringThe full help message for this diagnostic command (same output as + * the one produced by the 'help' command)
    dcmd.vmImpactStringThe 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
    dcmd.enabledbooleanTrue if the diagnostic command is enabled, false otherwise
    dcmd.permissionClassStringSome 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 + *
    dcmd.permissionNameStringThe fist argument of the permission required to execute this + * diagnostic command or null if no permission is required
    dcmd.permissionActionStringThe 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
    dcmd.argumentsDescriptorA Descriptor instance containing the descriptions of options and + * arguments supported by the diagnostic command (see below)
    + *

    + * + *

    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: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    NameTypeDescription
    dcmd.arg.nameStringThe name of the parameter
    dcmd.arg.typeStringThe 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. + *
    dcmd.arg.descriptionStringThe parameter description
    dcmd.arg.isMandatorybooleanTrue if the parameter is mandatory, false otherwise
    dcmd.arg.isOptionbooleanTrue if the parameter is an option, false if it is an argument
    dcmd.arg.isMultiplebooleanTrue if the parameter can be specified several times, false + * otherwise
    + * + *

    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 + * + * {@code "jmx.mbean.info.changed"} and a + * {@linkplain javax.management.Notification#getUserData() userData} that + * is the new {@code MBeanInfo}. + * + * @since 1.8 + */ +public interface DiagnosticCommandMBean extends DynamicMBean +{ + +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/GarbageCollectionNotificationInfo.java --- /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 + * + *

    + * 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: + * + *

  • The name of the garbage collector used to perform the collection.
  • + *
  • The action performed by the garbage collector.
  • + *
  • The cause of the garbage collection action.
  • + *
  • 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.
  • + * + * + *

    + * 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: + * + *

    + *      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);
    + *          ....
    + *      }
    + * 
    + * + *

    + * The type of the notification emitted by a {@code GarbageCollectorMXBean} is: + *

      + *
    • A {@linkplain #GARBAGE_COLLECTION_NOTIFICATION garbage collection notification}. + *
      Used by every notification emitted by the garbage collector, the details about + * the notification are provided in the {@linkplain #getGcAction action} String + *

    • + *
    + **/ + +@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: + *
    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Attribute NameType
    gcName{@code java.lang.String}
    gcAction{@code java.lang.String}
    gcCause{@code java.lang.String}
    gcInfo{@code javax.management.openmbean.CompositeData}
    + *
    + * + * @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; + } + +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/GarbageCollectorMXBean.java --- /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. + * + *

    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, null is returned. + * The collector-specific attributes, if any, can be obtained + * via the {@link CompositeData CompositeData} interface. + *

    + * MBeanServer access: + * The mapped type of GcInfo is CompositeData + * with attributes specified in {@link GcInfo#from GcInfo}. + * + * @return a GcInfo object representing + * the most GC information; or null if no GC + * information available. + */ + public GcInfo getLastGcInfo(); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/GcInfo.java --- /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: + *

    + *
      + *
    • Start time
    • + *
    • End time
    • + *
    • Duration
    • + *
    • Memory usage before the collection starts
    • + *
    • Memory usage after the collection ends
    • + *
    + *
    + * + *

    + * GcInfo 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. + * + *

    MXBean Mapping

    + * GcInfo 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 usageBeforeGc; + private final Map 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(poolNames.length); + this.usageAfterGc = new HashMap(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 Map of the name of a memory pool + * to the memory usage of the corresponding + * memory pool before GC starts. + * + * @return a Map of memory pool names to the memory + * usage of a memory pool before GC starts. + */ + public Map getMemoryUsageBeforeGc() { + return Collections.unmodifiableMap(usageBeforeGc); + } + + /** + * Returns the memory usage of all memory pools + * at the end of this GC. + * This method returns + * a Map of the name of a memory pool + * to the memory usage of the corresponding + * memory pool when GC finishes. + * + * @return a Map of memory pool names to the memory + * usage of a memory pool when GC finishes. + */ + public Map getMemoryUsageAfterGc() { + return Collections.unmodifiableMap(usageAfterGc); + } + + /** + * Returns a GcInfo object represented by the + * given CompositeData. The given + * CompositeData must contain + * all the following attributes: + * + *

    + *

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Attribute NameType
    indexjava.lang.Long
    startTimejava.lang.Long
    endTimejava.lang.Long
    memoryUsageBeforeGcjavax.management.openmbean.TabularData
    memoryUsageAfterGcjavax.management.openmbean.TabularData
    + *
    + * + * @throws IllegalArgumentException if cd does not + * represent a GcInfo object with the attributes + * described above. + * + * @return a GcInfo object represented by cd + * if cd is not null; null 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(); + } + + /** + *

    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; + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/HotSpotDiagnosticMXBean.java --- /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. + * + *

    The diagnostic MBean is registered to the platform MBeanServer + * as are other platform MBeans. + * + *

    The ObjectName for uniquely identifying the diagnostic + * MXBean within an MBeanServer is: + *

    + * com.sun.management:type=HotSpotDiagnostic + *
    +.* + * 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 outputFile file in the same + * format as the hprof heap dump. + *

    + * If this method is called remotely from another process, + * the heap dump output is written to a file named outputFile + * 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 true dump only live objects + * i.e. objects that are reachable from others + * @throws IOException if the outputFile + * cannot be created, opened, or written to. + * @throws UnsupportedOperationException if this operation is not supported. + * @throws NullPointerException if outputFile is null. + * @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 VMOption 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 VMOption objects for all diagnostic options. + */ + public java.util.List getDiagnosticOptions(); + + /** + * Returns a VMOption object for a VM option of the given + * name. + * + * @return a VMOption object for a VM option of the given name. + * @throws NullPointerException if name is null. + * @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 VMOption + * object returned by the {@link #getVMOption} method or + * the {@link #getDiagnosticOptions} method. This method does + * not change the value of this VMOption 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 null. + * + * @throws java.lang.SecurityException + * if a security manager exists and the caller does not have + * ManagementPermission("control"). + */ + public void setVMOption(String name, String value); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/OperatingSystemMXBean.java --- /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. + * + *

    + * The OperatingSystemMXBean 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 -1 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 -1 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 -1 if the + * the platform does not support this operation. + * + * @return the CPU time used by the process in nanoseconds, + * or -1 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(); + +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/ThreadMXBean.java --- /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. + *

    + * 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. + *

    + * 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. + *

    + * 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. + *

    + * 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. + *

    + * 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. + *

    + * 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); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/UnixOperatingSystemMXBean.java --- /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(); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/VMOption.java --- /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 origin}. + *

    + * 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 VMOption contains the value of a VM option + * and the origin of that value at the time this VMOption + * object was constructed. The value of the VM option + * may be changed after the VMOption object was constructed, + * + * @see + * Java Virtual Machine + * @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 VMOption. + * + * @param name Name of a VM option. + * @param value Value of a VM option. + * @param writeable true if a VM option can be set dynamically, + * or false otherwise. + * @param origin where the value of a VM option came from. + * + * @throws NullPointerException if the name or value is null + */ + public VMOption(String name, String value, boolean writeable, Origin origin) { + this.name = name; + this.value = value; + this.writeable = writeable; + this.origin = origin; + } + + /** + * Constructs a VMOption 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 VMOption was created. The value could have been changed. + * + * @return the value of the VM option at the time when + * this VMOption 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 true if this VM option is writeable; false + * otherwise. + */ + public boolean isWriteable() { + return writeable; + } + + public String toString() { + return "VM option: " + getName() + + " value: " + value + " " + + " origin: " + origin + " " + + (writeable ? "(read-write)" : "(read-only)"); + } + + /** + * Returns a VMOption object represented by the + * given CompositeData. The given CompositeData + * must contain the following attributes: + *

    + *

    + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
    Attribute NameType
    namejava.lang.String
    valuejava.lang.String
    originjava.lang.String
    writeablejava.lang.Boolean
    + *
    + * + * @param cd CompositeData representing a VMOption + * + * @throws IllegalArgumentException if cd does not + * represent a VMOption with the attributes described + * above. + * + * @return a VMOption object represented by cd + * if cd is not null; + * null 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); + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/DiagnosticCommandArgumentInfo.java --- /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: + *
    + * <command name> [<option>=<value>] [<argument_value>] + *
    + * Example: + *
    + * command_name option1=value1 option2=value argumentA argumentB argumentC + *
    + * 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; + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/DiagnosticCommandImpl.java --- /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 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 { + @Override + public int compare(MBeanOperationInfo o1, MBeanOperationInfo o2) { + return o1.getName().compareTo(o2.getName()); + } + } + + @Override + public MBeanInfo getMBeanInfo() { + SortedSet operations = new TreeSet<>(new OperationInfoComparator()); + Map 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 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 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 allargmap = new HashMap<>(); + for (DiagnosticCommandArgumentInfo arginfo : w.info.getArgumentsInfo()) { + HashMap 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); + +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/DiagnosticCommandInfo.java --- /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 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 getArgumentsInfo() { + return arguments; + } + + DiagnosticCommandInfo(String name, String description, + String impact, String permissionClass, + String permissionName, String permissionAction, + boolean enabled, + List 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; + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/Flag.java --- /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 flags = getFlags(names, 1); + if (flags.isEmpty()) { + return null; + } else { + // flags should have only one element + return flags.get(0); + } + } + + static List getAllFlags() { + int numFlags = getInternalFlagCount(); + + // Get all internal flags with names = null + return getFlags(null, numFlags); + } + + private static List getFlags(String[] names, int numFlags) { + Flag[] flags = new Flag[numFlags]; + int count = getFlags(names, flags, numFlags); + + List 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() { + public Void run() { + System.loadLibrary("management"); + return null; + } + }); + initialize(); + } + private static native void initialize(); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/GarbageCollectionNotifInfoCompositeData.java --- /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() { + 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 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; +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/GarbageCollectorExtImpl.java --- /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 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); + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/GcInfoBuilder.java --- /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); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/GcInfoCompositeData.java --- /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() { + 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() { + 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 + 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 cast(Object x) { + return (Map) x; + } + public static Map + getMemoryUsageAfterGc(CompositeData cd) { + try { + TabularData td = (TabularData) cd.get(MEMORY_USAGE_AFTER_GC); + //return (Map) + 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; +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/HotSpotDiagnostic.java --- /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 getDiagnosticOptions() { + List allFlags = Flag.getAllFlags(); + List 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"); + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/HotSpotThreadImpl.java --- /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); + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/PlatformMBeanProviderImpl.java --- /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> mxbeanList; + private static HotSpotDiagnostic hsDiagMBean = null; + private static OperatingSystemMXBean osMBean = null; + + static { + AccessController.doPrivileged((PrivilegedAction) () -> { + System.loadLibrary("management_ext"); + return null; + }); + } + + public PlatformMBeanProviderImpl() { + mxbeanList = Collections.unmodifiableList(init()); + } + + @Override + public List> getPlatformComponentList() { + return mxbeanList; + } + + private List> init() { + ArrayList> initMBeanList = new ArrayList<>(); + /** + * Garbage Collector in the Java virtual machine. + */ + initMBeanList.add(new PlatformComponent() { + private final Set garbageCollectorMXBeanInterfaceNames + = Collections.unmodifiableSet( + Stream.of("java.lang.management.MemoryManagerMXBean", + "java.lang.management.GarbageCollectorMXBean", + "com.sun.management.GarbageCollectorMXBean") + .collect(Collectors.toSet())); + + @Override + public Set> mbeanInterfaces() { + return Stream.of(MemoryManagerMXBean.class, + java.lang.management.GarbageCollectorMXBean.class, + com.sun.management.GarbageCollectorMXBean.class) + .collect(Collectors.toSet()); + } + + @Override + public Set 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 nameToMBeanMap() { + List list + = ManagementFactoryHelper.getGarbageCollectorMXBeans(); + Map 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() { + private final Set threadMXBeanInterfaceNames + = Collections.unmodifiableSet( + Stream.of("java.lang.management.ThreadMXBean", + "com.sun.management.ThreadMXBean") + .collect(Collectors.toSet())); + private ThreadMXBean threadMBean = null; + + @Override + public Set> mbeanInterfaces() { + return Stream.of(java.lang.management.ThreadMXBean.class, + com.sun.management.ThreadMXBean.class) + .collect(Collectors.toSet()); + } + + @Override + public Set mbeanInterfaceNames() { + return threadMXBeanInterfaceNames; + } + + @Override + public String getObjectNamePattern() { + return ManagementFactory.THREAD_MXBEAN_NAME; + } + + @Override + public synchronized Map nameToMBeanMap() { + if (threadMBean == null) { + threadMBean = new HotSpotThreadImpl(ManagementFactoryHelper.getVMManagement()); + } + return Collections.singletonMap( + ManagementFactory.THREAD_MXBEAN_NAME, + threadMBean); + } + }); + + /** + * OperatingSystemMXBean + */ + initMBeanList.add(new PlatformComponent() { + private final Set operatingSystemMXBeanInterfaceNames + = Collections.unmodifiableSet( + Stream.of("java.lang.management.OperatingSystemMXBean", + "com.sun.management.OperatingSystemMXBean", + "com.sun.management.UnixOperatingSystemMXBean") + .collect(Collectors.toSet())); + + @Override + public Set> 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 mbeanInterfaceNames() { + return operatingSystemMXBeanInterfaceNames; + } + + @Override + public String getObjectNamePattern() { + return ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME; + } + + @Override + public Map nameToMBeanMap() { + return Collections.singletonMap( + ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME, + getOperatingSystemMXBean()); + } + }); + + /** + * Diagnostic support for the HotSpot Virtual Machine. + */ + initMBeanList.add(new PlatformComponent() { + private final Set hotSpotDiagnosticMXBeanInterfaceNames = + Collections.unmodifiableSet(Collections.singleton( + "com.sun.management.HotSpotDiagnosticMXBean")); + + @Override + public Set> mbeanInterfaces() { + return Collections.singleton(com.sun.management.HotSpotDiagnosticMXBean.class); + } + + @Override + public Set mbeanInterfaceNames() { + return hotSpotDiagnosticMXBeanInterfaceNames; + } + + @Override + public String getObjectNamePattern() { + return "com.sun.management:type=HotSpotDiagnostic"; + } + + @Override + public Map nameToMBeanMap() { + return Collections.singletonMap( + "com.sun.management:type=HotSpotDiagnostic", + getDiagnosticMXBean()); + } + }); + + /** + * Diagnostic command MBean + */ + DiagnosticCommandMBean diagMBean = DiagnosticCommandImpl.getDiagnosticCommandMBean(); + if (diagMBean != null) { + initMBeanList.add(new PlatformComponent() { + final Set dynamicMBeanInterfaceNames + = Collections.unmodifiableSet(Collections.singleton( + "javax.management.DynamicMBean")); + + @Override + public Set mbeanInterfaceNames() { + return dynamicMBeanInterfaceNames; + } + + @Override + public Set> 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 nameToMBeanMap() { + return Collections.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; + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/internal/VMOptionCompositeData.java --- /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; +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/classes/com/sun/management/package-info.java --- /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 + * + * java.lang.management API and also defines the management + * interface for some other components for the platform. + * + *

    + * All platform MBeans are registered in the platform MBeanServer + * which can be obtained via the + * + * java.lang.management.ManagementFactory.getPlatformMBeanServer + * + * @author Mandy Chung + * @since 1.5 + */ + +@jdk.Exported +package com.sun.management; diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/native/libmanagement_ext/DiagnosticCommandImpl.c --- /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 +#include +#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; iNewStringUTF(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; iGetObjectArrayElement(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); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/native/libmanagement_ext/Flag.c --- /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 +#include +#include +#include +#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); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/native/libmanagement_ext/GarbageCollectorExtImpl.c --- /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 +#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); + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/native/libmanagement_ext/GcInfoBuilder.c --- /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 +#include +#include +#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); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/native/libmanagement_ext/HotSpotDiagnostic.c --- /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 +#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); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/native/libmanagement_ext/management_ext.c --- /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 +#include +#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); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/share/native/libmanagement_ext/management_ext.h --- /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 + +#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 diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/solaris/native/libmanagement_ext/UnixOperatingSystem.c --- /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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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(); +} + diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/unix/classes/com/sun/management/internal/OperatingSystemImpl.java --- /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(); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/unix/native/libmanagement_ext/OperatingSystemImpl.c --- /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 +#include +#if defined(_ALLBSD_SOURCE) +#include +#ifdef __APPLE__ +#include +#include +#include +#include +#include +#endif +#elif !defined(_AIX) +#include +#endif +#include +#include +#ifndef _ALLBSD_SOURCE +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +#if defined(_AIX) +#include +#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 */ +#define _STRUCTURED_PROC 1 +#include + +#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; +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/windows/classes/com/sun/management/internal/OperatingSystemImpl.java --- /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(); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/src/jdk.management/windows/native/libmanagement_ext/OperatingSystemImpl.c --- /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 +#include +#include + +#include +#pragma warning (push,0) +#include +#pragma warning (pop) +#include +#include +#include +#include + +/* Disable warnings due to broken header files from Microsoft... */ +#pragma warning(push, 3) +#include +#include +#include +#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(); +} diff -r ca83b4cae363 -r e37c7eba132f jdk/test/com/sun/management/CheckSomeMXBeanImplPackage.java --- /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 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); + } + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/test/com/sun/management/VMOptionOpenDataTest.java --- /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; + } + } +} diff -r ca83b4cae363 -r e37c7eba132f jdk/test/java/lang/instrument/NMTHelper.java --- 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) { diff -r ca83b4cae363 -r e37c7eba132f jdk/test/java/lang/instrument/RedefineMethodInBacktraceApp.java --- 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(); diff -r ca83b4cae363 -r e37c7eba132f jdk/test/sun/management/PlatformMBeanProviderConstructorCheck.java --- /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> getPlatformComponentList() { + return null; + } + } +}