This commit is contained in:
Phil Race 2017-04-20 10:00:32 -07:00
commit 7aa3cba238
368 changed files with 1530 additions and 43853 deletions

View File

@ -263,239 +263,13 @@ $(eval $(call SetupBuildDemo, TransparentRuler, \
MAIN_CLASS := transparentruler.Ruler, \
))
$(eval $(call SetupBuildDemo, jconsole-plugin, \
DEMO_SUBDIR := scripting, \
SRC_SUB_DIR := src, \
MAIN_CLASS := NONE, \
))
$(eval $(call SetupBuildDemo, FullThreadDump, \
DEMO_SUBDIR := management, \
))
$(eval $(call SetupBuildDemo, JTop, \
DEMO_SUBDIR := management, \
))
$(eval $(call SetupBuildDemo, MemoryMonitor, \
DEMO_SUBDIR := management, \
))
$(eval $(call SetupBuildDemo, VerboseGC, \
DEMO_SUBDIR := management, \
))
################################################################################
# Build JVMTI demos.
# Setup make rules for building a JVMTI demo.
#
# Parameter 1 is the name of the rule. This name is used as variable prefix,
# and the targets generated are listed in a variable by that name.
#
# Remaining parameters are named arguments. These include:
# EXTRA_SRC_SUBDIR Also include these subdirectories
# TOOLCHAIN Optionally specify toolchain to use
SetupBuildJvmtiDemo = $(NamedParamsMacroTemplate)
define SetupBuildJvmtiDemoBody
$1_SRC := \
$(DEMO_SHARE_SRC)/jvmti/$1 \
$$(wildcard $$(addprefix $(DEMO_SHARE_SRC)/jvmti/, \
agent_util $$($1_EXTRA_SRC_SUBDIR)))
### Build the native lib
$1_CFLAGS_INCLUDE := $$(addprefix -I, $$($1_SRC))
$1_CXXFLAGS := $$($1_CFLAGS_INCLUDE) $(CXXFLAGS_JDKLIB) $(CXXFLAGS_DEBUG_SYMBOLS)
ifeq ($$($1_TOOLCHAIN), TOOLCHAIN_LINK_CXX)
# For C++, we also need some special treatment.
$1_LDFLAGS := $$(LDFLAGS_CXX_JDK)
$1_LIBS := $(LIBCXX)
ifeq ($(OPENJDK_TARGET_CPU_ARCH), sparc)
$1_CXXFLAGS := $$(filter-out -xregs=no%appl, $$($1_CXXFLAGS))
endif
endif
# Remove the -incremental:no setting to get .ilk-files like in the old build.
$$(eval $$(call SetupNativeCompilation, BUILD_DEMO_JVMTI_NATIVE_$1, \
SRC := $$($1_SRC), \
TOOLCHAIN := $$($1_TOOLCHAIN), \
OPTIMIZATION := LOW, \
CFLAGS := $$($1_CFLAGS_INCLUDE) $$(CFLAGS_JDKLIB) $$(CFLAGS_DEBUG_SYMBOLS), \
CXXFLAGS := $$($1_CXXFLAGS), \
LDFLAGS := $(filter-out -incremental:no -opt:ref, $$(LDFLAGS_JDKLIB)) \
$$($1_LDFLAGS), \
LDFLAGS_macosx := $$(call SET_EXECUTABLE_ORIGIN), \
LIBS := $$($1_LIBS), \
LIBS_solaris := -lc, \
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
RC_FLAGS := $$(RC_FLAGS) \
-D "JDK_FNAME=$1.dll" \
-D "JDK_INTERNAL_NAME=$1" \
-D "JDK_FTYPE=0x2L", \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/demos/native/jvmti/$1, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/lib, \
LIBRARY := $1, \
STRIP_SYMBOLS := false, \
))
$1 += $$(BUILD_DEMO_JVMTI_NATIVE_$1)
### Build the jar, if we have java sources
ifneq ($$(wildcard $(DEMO_SHARE_SRC)/jvmti/$1/*.java), )
$$(eval $$(call SetupJavaCompilation, BUILD_DEMO_JVMTI_JAVA_$1, \
SETUP := GENERATE_USINGJDKBYTECODE, \
SRC := $(DEMO_SHARE_SRC)/jvmti/$1, \
BIN := $(SUPPORT_OUTPUTDIR)/demos/classes/jvmti/$1, \
COPY := $(COPY_TO_JAR), \
JAR := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/$1.jar, \
EXTRA_MANIFEST_ATTR := Main-Class: \n, \
MANIFEST := $(DEMO_MANIFEST), \
))
$1 += $$(BUILD_DEMO_JVMTI_JAVA_$1_JAR)
endif
### Build the source zip
$1_EXCLUDE_FILES := \
$$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/README.txt, \
agent_util $$($1_EXTRA_SRC_SUBDIR))) \
$$(wildcard $$(patsubst %, $(DEMO_SHARE_SRC)/jvmti/%/sample.makefile.txt, \
agent_util $$($1_EXTRA_SRC_SUBDIR)))
$$(eval $$(call SetupZipArchive, BUILD_DEMO_JVMTI_SRC_$1, \
SRC := $$($1_SRC), \
EXCLUDE_FILES := $$($1_EXCLUDE_FILES), \
ZIP := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/src.zip, \
))
$1 += $$(BUILD_DEMO_JVMTI_SRC_$1)
# Copy files to image
$(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/README.txt: $(DEMO_SHARE_SRC)/jvmti/$1/README.txt
$$(call install-file)
$(CHMOD) -f ug+w $$@
$1 += $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/README.txt
ifeq ($(OPENJDK_TARGET_OS), windows)
# These lib and exp files normally end up in OBJECT_DIR but for demos they
# are supposed to be included in the distro. Since they are created as
# a side-effect of the library compilation, make does not know about them.
$1_SUPPORT_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/demos/native/jvmti/$1
$1_IMAGE_OUTPUTDIR := $(SUPPORT_OUTPUTDIR)/demos/image/jvmti/$1/lib
$$($1_SUPPORT_OUTPUTDIR)/$1.lib: $$(BUILD_DEMO_JVMTI_NATIVE_$1)
$$($1_SUPPORT_OUTPUTDIR)/$1.exp: $$(BUILD_DEMO_JVMTI_NATIVE_$1)
$$($1_IMAGE_OUTPUTDIR)/$1.lib: $$($1_SUPPORT_OUTPUTDIR)/$1.lib
$$(call install-file)
$$($1_IMAGE_OUTPUTDIR)/$1.exp: $$($1_SUPPORT_OUTPUTDIR)/$1.exp
$$(call install-file)
$1 += $$($1_IMAGE_OUTPUTDIR)/$1.lib $$($1_IMAGE_OUTPUTDIR)/$1.exp
endif
TARGETS += $$($1)
endef
$(eval $(call SetupBuildJvmtiDemo, compiledMethodLoad))
$(eval $(call SetupBuildJvmtiDemo, gctest))
$(eval $(call SetupBuildJvmtiDemo, heapViewer))
$(eval $(call SetupBuildJvmtiDemo, versionCheck))
$(eval $(call SetupBuildJvmtiDemo, heapTracker, \
EXTRA_SRC_SUBDIR := java_crw_demo, \
))
$(eval $(call SetupBuildJvmtiDemo, minst, \
EXTRA_SRC_SUBDIR := java_crw_demo, \
))
$(eval $(call SetupBuildJvmtiDemo, mtrace, \
EXTRA_SRC_SUBDIR := java_crw_demo, \
))
$(eval $(call SetupBuildJvmtiDemo, waiters, \
TOOLCHAIN := TOOLCHAIN_LINK_CXX, \
))
################################################################################
# Build the Poller demo (on Solaris only).
ifeq ($(OPENJDK_TARGET_OS), solaris)
DEMO_SOLARIS_SRC := $(JDK_TOPDIR)/src/demo/solaris
$(eval $(call SetupJavaCompilation, BUILD_DEMO_JAVA_Poller, \
SETUP := GENERATE_USINGJDKBYTECODE, \
SRC := $(DEMO_SOLARIS_SRC)/jni/Poller, \
BIN := $(SUPPORT_OUTPUTDIR)/demos/classes/jni/Poller, \
HEADERS := $(SUPPORT_OUTPUTDIR)/demos/classes/jni/Poller, \
JAR := $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/Poller.jar, \
MANIFEST := $(SUPPORT_OUTPUTDIR)/demos/java-main-manifest.mf, \
SRCZIP := $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/src.zip, \
COPY := README.txt Poller.c, \
JARMAIN := Client, \
))
TARGETS += $(BUILD_DEMO_JAVA_Poller)
$(eval $(call SetupNativeCompilation, BUILD_DEMO_NATIVE_Poller, \
SRC := $(DEMO_SOLARIS_SRC)/jni/Poller, \
OPTIMIZATION := LOW, \
CFLAGS := $(CFLAGS_JDKLIB) \
-I$(SUPPORT_OUTPUTDIR)/demos/classes/jni/Poller, \
LDFLAGS := $(LDFLAGS_JDKLIB), \
LIBS_solaris := -lc, \
OBJECT_DIR := $(SUPPORT_OUTPUTDIR)/demos/native/jni/Poller, \
OUTPUT_DIR := $(SUPPORT_OUTPUTDIR)/demos/native, \
LIBRARY := Poller, \
STRIP_SYMBOLS := false, \
))
TARGETS += $(BUILD_DEMO_NATIVE_Poller)
# We can only compile native code after java has been compiled (since we
# depend on generated .h files)
$(SUPPORT_OUTPUTDIR)/demos/native/jni/Poller/Poller.o: \
$(BUILD_DEMO_JAVA_Poller)
# Copy to image
$(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/README.txt: \
$(DEMO_SOLARIS_SRC)/jni/Poller/README.txt
$(call install-file)
$(CHMOD) -f ug+w $@
TARGETS += $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/README.txt
$(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/lib/libPoller.so: \
$(SUPPORT_OUTPUTDIR)/demos/native/libPoller.so
$(call install-file)
TARGETS += $(SUPPORT_OUTPUTDIR)/demos/image/jni/Poller/lib/libPoller.so
endif
################################################################################
# Copy html and README files.
$(SUPPORT_OUTPUTDIR)/demos/image/management/index.html: $(DEMO_SHARE_SRC)/management/index.html
$(call install-file)
$(CHMOD) -f ug+w $@
$(SUPPORT_OUTPUTDIR)/demos/image/jvmti/index.html: $(DEMO_SHARE_SRC)/jvmti/index.html
$(call install-file)
$(CHMOD) -f ug+w $@
$(SUPPORT_OUTPUTDIR)/demos/image/README: $(DEMO_SHARE_SRC)/README
$(call install-file)
TARGETS += $(SUPPORT_OUTPUTDIR)/demos/image/management/index.html \
$(SUPPORT_OUTPUTDIR)/demos/image/jvmti/index.html \
$(SUPPORT_OUTPUTDIR)/demos/image/README
TARGETS += $(SUPPORT_OUTPUTDIR)/demos/image/README
################################################################################
# Copy netbeans project files.

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2017, 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,11 +30,19 @@ include MakeBase.gmk
include JavaCompilation.gmk
include SetupJavaCompilers.gmk
$(eval $(call IncludeCustomExtension, jdk, CompileTools.gmk))
################################################################################
# Use += to be able to add to this from a custom extension
BUILD_TOOLS_SRC_DIRS += \
$(JDK_TOPDIR)/make/src/classes \
$(BUILDTOOLS_OUTPUTDIR)/interim_cldrconverter_classes \
#
$(eval $(call SetupJavaCompilation,BUILD_TOOLS_JDK, \
SETUP := GENERATE_OLDBYTECODE, \
SRC := $(JDK_TOPDIR)/make/src/classes $(BUILDTOOLS_OUTPUTDIR)/interim_cldrconverter_classes, \
SRC := $(BUILD_TOOLS_SRC_DIRS), \
EXCLUDES := build/tools/deps \
build/tools/jigsaw, \
BIN := $(BUILDTOOLS_OUTPUTDIR)/jdk_tools_classes))

View File

@ -1,65 +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.
#
default: all
include $(SPEC)
include MakeBase.gmk
################################################################################
SAMPLE_TARGET_DIR := $(SUPPORT_OUTPUTDIR)/sample/image
SAMPLE_SOURCE_DIR := $(JDK_TOPDIR)/src/sample/share
SAMPLE_SOLARIS_SOURCE_DIR := $(JDK_TOPDIR)/src/sample/solaris
# Exclude the vm directory
$(eval $(call SetupCopyFiles, COPY_SHARE_SAMPLES, \
SRC := $(SAMPLE_SOURCE_DIR), \
DEST := $(SAMPLE_TARGET_DIR), \
FILES := $(filter-out $(SAMPLE_SOURCE_DIR)/vm/%, \
$(call CacheFind, $(SAMPLE_SOURCE_DIR))), \
))
TARGETS += $(COPY_SHARE_SAMPLES)
ifneq (, $(filter $(OPENJDK_TARGET_OS), solaris macosx))
$(eval $(call SetupCopyFiles, COPY_SOLARIS_SAMPLES, \
SRC := $(SAMPLE_SOLARIS_SOURCE_DIR), \
DEST := $(SAMPLE_TARGET_DIR), \
FILES := $(call CacheFind, $(SAMPLE_SOLARIS_SOURCE_DIR)), \
))
TARGETS += $(COPY_SOLARIS_SAMPLES)
endif
################################################################################
$(eval $(call IncludeCustomExtension, jdk, CopySamples.gmk))
################################################################################
all: $(TARGETS)
.PHONY: all default

View File

@ -1,5 +1,5 @@
#
# Copyright (c) 2011, 2016, Oracle and/or its affiliates. All rights reserved.
# Copyright (c) 2011, 2017, 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
@ -28,6 +28,9 @@ _TOOLS_GMK := 1
include JavaCompilation.gmk
# Hook to include the corresponding custom file, if present.
$(eval $(call IncludeCustomExtension, jdk, Tools.gmk))
################################################################################
# To avoid reevaluating the compilation setup for the tools each time this file
# is included, the actual compilation is handled by CompileTools.gmk. The

View File

@ -24,3 +24,5 @@ JIS_X_0208
JIS_X_0212
JIS_X_0208_Solaris
JIS_X_0212_Solaris
MS932
SJIS # SJIS must go together with MS932 to support sun.nio.cs.map

View File

@ -1,4 +1,4 @@
The source code provided with samples and demos for the JDK is meant
The source code provided with demos for the JDK is meant
to illustrate the usage of a given feature or technique and has been
deliberately simplified. Additional steps required for a
production-quality application, such as security checks, input

View File

@ -1,35 +0,0 @@
#
# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
agent_util sources
Just some shared generic source used by several of the demos.

View File

@ -1,309 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#include <agent_util.h>
/* ------------------------------------------------------------------- */
/* Generic C utility functions */
/* Send message to stdout or whatever the data output location is */
void
stdout_message(const char * format, ...)
{
va_list ap;
va_start(ap, format);
(void)vfprintf(stdout, format, ap);
va_end(ap);
}
/* Send message to stderr or whatever the error output location is and exit */
void
fatal_error(const char * format, ...)
{
va_list ap;
va_start(ap, format);
(void)vfprintf(stderr, format, ap);
(void)fflush(stderr);
va_end(ap);
exit(3);
}
/* Get a token from a string (strtok is not MT-safe)
* str String to scan
* seps Separation characters
* buf Place to put results
* max Size of buf
* Returns NULL if no token available or can't do the scan.
*/
char *
get_token(char *str, char *seps, char *buf, int max)
{
int len;
buf[0] = 0;
if ( str==NULL || str[0]==0 ) {
return NULL;
}
str += strspn(str, seps);
if ( str[0]==0 ) {
return NULL;
}
len = (int)strcspn(str, seps);
if ( len >= max ) {
return NULL;
}
(void)strncpy(buf, str, len);
buf[len] = 0;
return str+len;
}
/* Determines if a class/method is specified by a list item
* item String that represents a pattern to match
* If it starts with a '*', then any class is allowed
* If it ends with a '*', then any method is allowed
* cname Class name, e.g. "java.lang.Object"
* mname Method name, e.g. "<init>"
* Returns 1(true) or 0(false).
*/
static int
covered_by_list_item(char *item, char *cname, char *mname)
{
int len;
len = (int)strlen(item);
if ( item[0]=='*' ) {
if ( strncmp(mname, item+1, len-1)==0 ) {
return 1;
}
} else if ( item[len-1]=='*' ) {
if ( strncmp(cname, item, len-1)==0 ) {
return 1;
}
} else {
int cname_len;
cname_len = (int)strlen(cname);
if ( strncmp(cname, item, (len>cname_len?cname_len:len))==0 ) {
if ( cname_len >= len ) {
/* No method name supplied in item, we must have matched */
return 1;
} else {
int mname_len;
mname_len = (int)strlen(mname);
item += cname_len+1;
len -= cname_len+1;
if ( strncmp(mname, item, (len>mname_len?mname_len:len))==0 ) {
return 1;
}
}
}
}
return 0;
}
/* Determines if a class/method is specified by this list
* list String of comma separated pattern items
* cname Class name, e.g. "java.lang.Object"
* mname Method name, e.g. "<init>"
* Returns 1(true) or 0(false).
*/
static int
covered_by_list(char *list, char *cname, char *mname)
{
char token[1024];
char *next;
if ( list[0] == 0 ) {
return 0;
}
next = get_token(list, ",", token, sizeof(token));
while ( next != NULL ) {
if ( covered_by_list_item(token, cname, mname) ) {
return 1;
}
next = get_token(next, ",", token, sizeof(token));
}
return 0;
}
/* Determines which class and methods we are interested in
* cname Class name, e.g. "java.lang.Object"
* mname Method name, e.g. "<init>"
* include_list Empty or an explicit list for inclusion
* exclude_list Empty or an explicit list for exclusion
* Returns 1(true) or 0(false).
*/
int
interested(char *cname, char *mname, char *include_list, char *exclude_list)
{
if ( exclude_list!=NULL && exclude_list[0]!=0 &&
covered_by_list(exclude_list, cname, mname) ) {
return 0;
}
if ( include_list!=NULL && include_list[0]!=0 &&
!covered_by_list(include_list, cname, mname) ) {
return 0;
}
return 1;
}
/* ------------------------------------------------------------------- */
/* Generic JVMTI utility functions */
/* Every JVMTI interface returns an error code, which should be checked
* to avoid any cascading errors down the line.
* The interface GetErrorName() returns the actual enumeration constant
* name, making the error messages much easier to understand.
*/
void
check_jvmti_error(jvmtiEnv *jvmti, jvmtiError errnum, const char *str)
{
if ( errnum != JVMTI_ERROR_NONE ) {
char *errnum_str;
errnum_str = NULL;
(void)(*jvmti)->GetErrorName(jvmti, errnum, &errnum_str);
fatal_error("ERROR: JVMTI: %d(%s): %s\n", errnum,
(errnum_str==NULL?"Unknown":errnum_str),
(str==NULL?"":str));
}
}
/* All memory allocated by JVMTI must be freed by the JVMTI Deallocate
* interface.
*/
void
deallocate(jvmtiEnv *jvmti, void *ptr)
{
jvmtiError error;
error = (*jvmti)->Deallocate(jvmti, ptr);
check_jvmti_error(jvmti, error, "Cannot deallocate memory");
}
/* Allocation of JVMTI managed memory */
void *
allocate(jvmtiEnv *jvmti, jint len)
{
jvmtiError error;
void *ptr;
error = (*jvmti)->Allocate(jvmti, len, (unsigned char **)&ptr);
check_jvmti_error(jvmti, error, "Cannot allocate memory");
return ptr;
}
/* Add demo jar file to boot class path (the BCI Tracker class must be
* in the boot classpath)
*
* WARNING: This code assumes that the jar file can be found at one of:
* ${JAVA_HOME}/demo/jvmti/${DEMO_NAME}/${DEMO_NAME}.jar
* ${JAVA_HOME}/../demo/jvmti/${DEMO_NAME}/${DEMO_NAME}.jar
* where JAVA_HOME may refer to the jre directory.
* Both these values are added to the boot classpath.
* These locations are only true for these demos, installed
* in the JDK area. Platform specific code could be used to
* find the location of the DLL or .so library, and construct a
* path name to the jar file, relative to the library location.
*/
void
add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name)
{
jvmtiError error;
char *file_sep;
int max_len;
char *java_home;
char jar_path[FILENAME_MAX+1];
java_home = NULL;
error = (*jvmti)->GetSystemProperty(jvmti, "java.home", &java_home);
check_jvmti_error(jvmti, error, "Cannot get java.home property value");
if ( java_home == NULL || java_home[0] == 0 ) {
fatal_error("ERROR: Java home not found\n");
}
#ifdef WIN32
file_sep = "\\";
#else
file_sep = "/";
#endif
max_len = (int)(strlen(java_home) + strlen(demo_name)*2 +
strlen(file_sep)*5 +
16 /* ".." "demo" "jvmti" ".jar" NULL */ );
if ( max_len > (int)sizeof(jar_path) ) {
fatal_error("ERROR: Path to jar file too long\n");
}
(void)strcpy(jar_path, java_home);
(void)strcat(jar_path, file_sep);
(void)strcat(jar_path, "demo");
(void)strcat(jar_path, file_sep);
(void)strcat(jar_path, "jvmti");
(void)strcat(jar_path, file_sep);
(void)strcat(jar_path, demo_name);
(void)strcat(jar_path, file_sep);
(void)strcat(jar_path, demo_name);
(void)strcat(jar_path, ".jar");
error = (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, (const char*)jar_path);
check_jvmti_error(jvmti, error, "Cannot add to boot classpath");
(void)strcpy(jar_path, java_home);
(void)strcat(jar_path, file_sep);
(void)strcat(jar_path, "..");
(void)strcat(jar_path, file_sep);
(void)strcat(jar_path, "demo");
(void)strcat(jar_path, file_sep);
(void)strcat(jar_path, "jvmti");
(void)strcat(jar_path, file_sep);
(void)strcat(jar_path, demo_name);
(void)strcat(jar_path, file_sep);
(void)strcat(jar_path, demo_name);
(void)strcat(jar_path, ".jar");
error = (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, (const char*)jar_path);
check_jvmti_error(jvmti, error, "Cannot add to boot classpath");
}
/* ------------------------------------------------------------------- */

View File

@ -1,117 +0,0 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#ifndef AGENT_UTIL_H
#define AGENT_UTIL_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdarg.h>
#include "jni.h"
#include "jvmti.h"
#ifdef __cplusplus
extern "C" {
#endif
void stdout_message(const char * format, ...);
void fatal_error(const char * format, ...);
char *get_token(char *str, char *seps, char *buf, int max);
int interested(char *cname, char *mname,
char *include_list, char *exclude_list);
void check_jvmti_error(jvmtiEnv *jvmti, jvmtiError errnum, const char *str);
void deallocate(jvmtiEnv *jvmti, void *ptr);
void *allocate(jvmtiEnv *jvmti, jint len);
void add_demo_jar_to_bootclasspath(jvmtiEnv *jvmti, char *demo_name);
#ifdef STATIC_BUILD
/* Macros for handling declaration of static/dynamic
* Agent library Load/Attach/Unload functions
*
* DEF_Agent_OnLoad, DEF_Agent_OnAttach or DEF_Agent_OnUnload
* generate the appropriate entrypoint names based on static
* versus dynamic builds.
*
* STATIC_BUILD must be defined to build static versions of these libraries.
* LIBRARY_NAME must be set to the name of the library for static builds.
*/
#define ADD_LIB_NAME3(name, lib) name ## lib
#define ADD_LIB_NAME2(name, lib) ADD_LIB_NAME3(name, lib)
#define ADD_LIB_NAME(entry) ADD_LIB_NAME2(entry, LIBRARY_NAME)
#define DEF_Agent_OnLoad \
ADD_LIB_NAME(Agent_OnLoad_)(JavaVM *vm, char *options, void *reserved) \
{ \
jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)(JavaVM *vm, char *options, void *reserved); \
return ADD_LIB_NAME(Agent_OnLoad_dynamic_)(vm, options, reserved); \
} \
jint JNICALL ADD_LIB_NAME(Agent_OnLoad_dynamic_)
#define DEF_Agent_OnAttach \
ADD_LIB_NAME(Agent_OnAttach_)(JavaVM *vm, char *options, void *reserved) \
{ \
jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)(JavaVM *vm, char *options, void *reserved); \
return ADD_LIB_NAME(Agent_OnAttach_dynamic_)(vm, options, reserved); \
} \
jint JNICALL ADD_LIB_NAME(Agent_OnAttach_dynamic_)
#define DEF_Agent_OnUnload \
ADD_LIB_NAME(Agent_OnUnload_)(JavaVM *vm) \
{ \
void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)(JavaVM *vm); \
ADD_LIB_NAME(Agent_OnUnload_dynamic_)(vm); \
} \
void JNICALL ADD_LIB_NAME(Agent_OnUnload_dynamic_)
#else
#define DEF_Agent_OnLoad Agent_OnLoad
#define DEF_Agent_OnAttach Agent_OnAttach
#define DEF_Agent_OnUnload Agent_OnUnload
#endif
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif

View File

@ -1,42 +0,0 @@
#
# Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
compiledMethodLoad
This agent library traces CompiledMethodLoad events along
with the HotSpot specific compile_info parameter.
You can use this agent library as follows:
java -agentlib:compiledMethodLoad ...
See ${JAVA_HOME}/demo/jvmti/index.html for help running and building agents.

View File

@ -1,277 +0,0 @@
/*
* Copyright (c) 2010, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jni.h"
#include "jvmti.h"
#include "jvmticmlr.h"
#include "agent_util.h"
/* Global static data */
static char OUTPUT_FILE[] = "compiledMethodLoad.txt";
static FILE *fp;
static jvmtiEnv *jvmti;
static jrawMonitorID lock;
/* print a jvmtiCompiledMethodLoadDummyRecord */
void
print_dummy_record(jvmtiCompiledMethodLoadDummyRecord* record,
jvmtiEnv* jvmti, FILE* fp) {
if (record != NULL) {
fprintf(fp, "Dummy record detected containing message: %s\n",
(char *)record->message);
}
}
/* print the specified stack frames */
void
print_stack_frames(PCStackInfo* record, jvmtiEnv *jvmti, FILE* fp) {
if (record != NULL && record->methods != NULL) {
int i;
for (i = 0; i < record->numstackframes; i++) {
jvmtiError err;
char* method_name = NULL;
char* class_name = NULL;
char* method_signature = NULL;
char* class_signature = NULL;
char* generic_ptr_method = NULL;
char* generic_ptr_class = NULL;
jmethodID id;
jclass declaringclassptr;
id = record->methods[i];
err = (*jvmti)->GetMethodDeclaringClass(jvmti, id,
&declaringclassptr);
check_jvmti_error(jvmti, err, "get method declaring class");
err = (*jvmti)->GetClassSignature(jvmti, declaringclassptr,
&class_signature, &generic_ptr_class);
check_jvmti_error(jvmti, err, "get class signature");
err = (*jvmti)->GetMethodName(jvmti, id, &method_name,
&method_signature, &generic_ptr_method);
check_jvmti_error(jvmti, err, "get method name");
fprintf(fp, "%s::%s %s %s @%d\n", class_signature, method_name,
method_signature,
generic_ptr_method == NULL ? "" : generic_ptr_method,
record->bcis[i]);
if (method_name != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*)method_name);
check_jvmti_error(jvmti, err, "deallocate method_name");
}
if (method_signature != NULL) {
err = (*jvmti)->Deallocate(jvmti,
(unsigned char*)method_signature);
check_jvmti_error(jvmti, err, "deallocate method_signature");
}
if (generic_ptr_method != NULL) {
err = (*jvmti)->Deallocate(jvmti,
(unsigned char*)generic_ptr_method);
check_jvmti_error(jvmti, err, "deallocate generic_ptr_method");
}
if (class_name != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*)class_name);
check_jvmti_error(jvmti, err, "deallocate class_name");
}
if (class_signature != NULL) {
err = (*jvmti)->Deallocate(jvmti,
(unsigned char*)class_signature);
check_jvmti_error(jvmti, err, "deallocate class_signature");
}
if (generic_ptr_class != NULL) {
err = (*jvmti)->Deallocate(jvmti,
(unsigned char*)generic_ptr_class);
check_jvmti_error(jvmti, err, "deallocate generic_ptr_class");
}
}
}
}
/* print a jvmtiCompiledMethodLoadInlineRecord */
void
print_inline_info_record(jvmtiCompiledMethodLoadInlineRecord* record,
jvmtiEnv *jvmti, FILE* fp) {
if (record != NULL && record->pcinfo != NULL) {
int numpcs = record->numpcs;
int i;
for (i = 0; i < numpcs; i++) {
PCStackInfo pcrecord = (record->pcinfo[i]);
fprintf(fp, "PcDescriptor(pc=%p):\n", pcrecord.pc);
print_stack_frames(&pcrecord, jvmti, fp);
}
}
}
/* decode kind of CompiledMethodLoadRecord and print */
void
print_records(jvmtiCompiledMethodLoadRecordHeader* list, jvmtiEnv *jvmti,
FILE* fp)
{
jvmtiCompiledMethodLoadRecordHeader* curr = list;
fprintf(fp, "\nPrinting PC Descriptors\n\n");
while (curr != NULL) {
switch (curr->kind) {
case JVMTI_CMLR_DUMMY:
print_dummy_record((jvmtiCompiledMethodLoadDummyRecord *)curr,
jvmti, fp);
break;
case JVMTI_CMLR_INLINE_INFO:
print_inline_info_record(
(jvmtiCompiledMethodLoadInlineRecord *)curr, jvmti, fp);
break;
default:
fprintf(fp, "Warning: unrecognized record: kind=%d\n", curr->kind);
break;
}
curr = (jvmtiCompiledMethodLoadRecordHeader *)curr->next;
}
}
/* Callback for JVMTI_EVENT_COMPILED_METHOD_LOAD */
void JNICALL
compiled_method_load(jvmtiEnv *jvmti, jmethodID method, jint code_size,
const void* code_addr, jint map_length, const jvmtiAddrLocationMap* map,
const void* compile_info)
{
jvmtiError err;
char* name = NULL;
char* signature = NULL;
char* generic_ptr = NULL;
jvmtiCompiledMethodLoadRecordHeader* pcs;
err = (*jvmti)->RawMonitorEnter(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor enter");
err = (*jvmti)->GetMethodName(jvmti, method, &name, &signature,
&generic_ptr);
check_jvmti_error(jvmti, err, "get method name");
fprintf(fp, "\nCompiled method load event\n");
fprintf(fp, "Method name %s %s %s\n\n", name, signature,
generic_ptr == NULL ? "" : generic_ptr);
pcs = (jvmtiCompiledMethodLoadRecordHeader *)compile_info;
if (pcs != NULL) {
print_records(pcs, jvmti, fp);
}
if (name != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*)name);
check_jvmti_error(jvmti, err, "deallocate name");
}
if (signature != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*)signature);
check_jvmti_error(jvmti, err, "deallocate signature");
}
if (generic_ptr != NULL) {
err = (*jvmti)->Deallocate(jvmti, (unsigned char*)generic_ptr);
check_jvmti_error(jvmti, err, "deallocate generic_ptr");
}
err = (*jvmti)->RawMonitorExit(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor exit");
}
/* Agent_OnLoad() is called first, we prepare for a COMPILED_METHOD_LOAD
* event here.
*/
JNIEXPORT jint JNICALL
DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{
jint rc;
jvmtiError err;
jvmtiCapabilities capabilities;
jvmtiEventCallbacks callbacks;
fp = fopen(OUTPUT_FILE, "w");
if (fp == NULL) {
fatal_error("ERROR: %s: Unable to create output file\n", OUTPUT_FILE);
return -1;
}
/* Get JVMTI environment */
rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION);
if (rc != JNI_OK) {
fatal_error(
"ERROR: Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc);
return -1;
}
/* add JVMTI capabilities */
memset(&capabilities,0, sizeof(capabilities));
capabilities.can_generate_compiled_method_load_events = 1;
err = (*jvmti)->AddCapabilities(jvmti, &capabilities);
check_jvmti_error(jvmti, err, "add capabilities");
/* set JVMTI callbacks for events */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.CompiledMethodLoad = &compiled_method_load;
err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
check_jvmti_error(jvmti, err, "set event callbacks");
/* enable JVMTI events */
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_COMPILED_METHOD_LOAD, NULL);
check_jvmti_error(jvmti, err, "set event notify");
/* create coordination monitor */
err = (*jvmti)->CreateRawMonitor(jvmti, "agent lock", &lock);
check_jvmti_error(jvmti, err, "create raw monitor");
return 0;
}
/* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL
DEF_Agent_OnUnload(JavaVM *vm)
{
}

View File

@ -1,148 +0,0 @@
#
# Copyright (c) 2010, 2016, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
########################################################################
#
# Sample GNU Makefile for building JVMTI Demo compiledMethodLoad
#
# Example uses:
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparc]
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparcv9]
# gnumake JDK=<java_home> OSNAME=linux [OPT=true]
# gnumake JDK=<java_home> OSNAME=win32 [OPT=true]
#
########################################################################
# Source lists
LIBNAME=compiledMethodLoad
SOURCES=compiledMethodLoad.c ../agent_util/agent_util.c
# Solaris Studio C Compiler Version 12.4
ifeq ($(OSNAME), solaris)
# Sun Solaris Compiler options needed
COMMON_FLAGS=-mt -KPIC
# Options that help find errors
COMMON_FLAGS+= -Xa -v -xc99=%none
# Check LIBARCH for any special compiler options
LIBARCH=$(shell uname -p)
ifeq ($(LIBARCH), sparc)
COMMON_FLAGS+=-xarch=v8 -xregs=no%appl
endif
ifeq ($(LIBARCH), sparcv9)
COMMON_FLAGS+=-xarch=v9 -xregs=no%appl
endif
ifeq ($(OPT), true)
CFLAGS=-xO2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-z defs -ztext
# Libraries we are dependent on
LIBRARIES= -lc
# Building a shared library
LINK_SHARED=$(LINK.c) -G -o $@
endif
# Linux GNU C Compiler
ifeq ($(OSNAME), linux)
# GNU Compiler options needed to build it
COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer
# Options that help find errors
COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses
ifeq ($(OPT), true)
CFLAGS=-O2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc
# Libraries we are dependent on
LIBRARIES=-lc
# Building a shared library
LINK_SHARED=$(LINK.c) -shared -o $@
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OSNAME), win32)
CC=cl
# Compiler options needed to build it
COMMON_FLAGS=-Gy -DWIN32
# Options that help find errors
COMMON_FLAGS+=-W0 -WX
ifeq ($(OPT), true)
CFLAGS= -Ox -Op -Zi $(COMMON_FLAGS)
else
CFLAGS= -Od -Zi $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.obj)
# Library name and options needed to build it
LIBRARY=$(LIBNAME).dll
LDFLAGS=
# Libraries we are dependent on
LIBRARIES=
# Building a shared library
LINK_SHARED=link -dll -out:$@
endif
# Common -I options
CFLAGS += -I.
CFLAGS += -I../agent_util
CFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME)
# Default rule
all: $(LIBRARY)
# Build native library
$(LIBRARY): $(OBJECTS)
$(LINK_SHARED) $(OBJECTS) $(LIBRARIES)
# Cleanup the built bits
clean:
rm -f $(LIBRARY) $(OBJECTS)
# Simple tester
test: all
LD_LIBRARY_PATH=`pwd` $(JDK)/bin/java -agentlib:$(LIBNAME) -version
# Compilation rule only needed on Windows
ifeq ($(OSNAME), win32)
%.obj: %.c
$(COMPILE.c) $<
endif

View File

@ -1,54 +0,0 @@
#
# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
gctest
This agent library can be used to track garbage collection events.
You can use this agent library as follows:
java -agentlib:gctest ...
To get help on the available options try:
java -agentlib:gctest=help
See ${JAVA_HOME}/demo/jvmti/index.html for help running and building agents.
The Events JVMTI_EVENT_GARBAGE_COLLECTION_START,
JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, and JVMTI_EVENT_OBJECT_FREE
all have limitations as to what can be called directly inside the
agent callback functions (e.g. no JNI calls are allowed, and limited
interface calls can be made). However, by using raw monitors and a separate
watcher thread, this agent demonstrates how these limitations can be
easily avoided, allowing the watcher thread to do just about anything
after the JVMTI_EVENT_GARBAGE_COLLECTION_FINISH event.

View File

@ -1,198 +0,0 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* Example of using JVMTI_EVENT_GARBAGE_COLLECTION_START and
* JVMTI_EVENT_GARBAGE_COLLECTION_FINISH events.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jni.h"
#include "jvmti.h"
/* For stdout_message(), fatal_error(), and check_jvmti_error() */
#include "agent_util.h"
/* Global static data */
static jvmtiEnv *jvmti;
static int gc_count;
static jrawMonitorID lock;
/* Worker thread that waits for garbage collections */
static void JNICALL
worker(jvmtiEnv* jvmti, JNIEnv* jni, void *p)
{
jvmtiError err;
stdout_message("GC worker started...\n");
for (;;) {
err = (*jvmti)->RawMonitorEnter(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor enter");
while (gc_count == 0) {
err = (*jvmti)->RawMonitorWait(jvmti, lock, 0);
if (err != JVMTI_ERROR_NONE) {
err = (*jvmti)->RawMonitorExit(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor wait");
return;
}
}
gc_count = 0;
err = (*jvmti)->RawMonitorExit(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor exit");
/* Perform arbitrary JVMTI/JNI work here to do post-GC cleanup */
stdout_message("post-GarbageCollectionFinish actions...\n");
}
}
/* Creates a new jthread */
static jthread
alloc_thread(JNIEnv *env)
{
jclass thrClass;
jmethodID cid;
jthread res;
thrClass = (*env)->FindClass(env, "java/lang/Thread");
if ( thrClass == NULL ) {
fatal_error("Cannot find Thread class\n");
}
cid = (*env)->GetMethodID(env, thrClass, "<init>", "()V");
if ( cid == NULL ) {
fatal_error("Cannot find Thread constructor method\n");
}
res = (*env)->NewObject(env, thrClass, cid);
if ( res == NULL ) {
fatal_error("Cannot create new Thread object\n");
}
return res;
}
/* Callback for JVMTI_EVENT_VM_INIT */
static void JNICALL
vm_init(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
jvmtiError err;
stdout_message("VMInit...\n");
err = (*jvmti)->RunAgentThread(jvmti, alloc_thread(env), &worker, NULL,
JVMTI_THREAD_MAX_PRIORITY);
check_jvmti_error(jvmti, err, "running agent thread");
}
/* Callback for JVMTI_EVENT_GARBAGE_COLLECTION_START */
static void JNICALL
gc_start(jvmtiEnv* jvmti_env)
{
stdout_message("GarbageCollectionStart...\n");
}
/* Callback for JVMTI_EVENT_GARBAGE_COLLECTION_FINISH */
static void JNICALL
gc_finish(jvmtiEnv* jvmti_env)
{
jvmtiError err;
stdout_message("GarbageCollectionFinish...\n");
err = (*jvmti)->RawMonitorEnter(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor enter");
gc_count++;
err = (*jvmti)->RawMonitorNotify(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor notify");
err = (*jvmti)->RawMonitorExit(jvmti, lock);
check_jvmti_error(jvmti, err, "raw monitor exit");
}
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
JNIEXPORT jint JNICALL
DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{
jint rc;
jvmtiError err;
jvmtiCapabilities capabilities;
jvmtiEventCallbacks callbacks;
/* Get JVMTI environment */
rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION);
if (rc != JNI_OK) {
fatal_error("ERROR: Unable to create jvmtiEnv, rc=%d\n", rc);
return -1;
}
/* Get/Add JVMTI capabilities */
(void)memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_generate_garbage_collection_events = 1;
err = (*jvmti)->AddCapabilities(jvmti, &capabilities);
check_jvmti_error(jvmti, err, "add capabilities");
/* Set callbacks and enable event notifications */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.VMInit = &vm_init;
callbacks.GarbageCollectionStart = &gc_start;
callbacks.GarbageCollectionFinish = &gc_finish;
err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
check_jvmti_error(jvmti, err, "set event callbacks");
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_VM_INIT, NULL);
check_jvmti_error(jvmti, err, "set event notification");
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_GARBAGE_COLLECTION_START, NULL);
check_jvmti_error(jvmti, err, "set event notification");
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_GARBAGE_COLLECTION_FINISH, NULL);
check_jvmti_error(jvmti, err, "set event notification");
/* Create the necessary raw monitor */
err = (*jvmti)->CreateRawMonitor(jvmti, "lock", &lock);
check_jvmti_error(jvmti, err, "create raw monitor");
return 0;
}
/* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL
DEF_Agent_OnUnload(JavaVM *vm)
{
}

View File

@ -1,148 +0,0 @@
#
# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
########################################################################
#
# Sample GNU Makefile for building JVMTI Demo gctest
#
# Example uses:
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparc]
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparcv9]
# gnumake JDK=<java_home> OSNAME=linux [OPT=true]
# gnumake JDK=<java_home> OSNAME=win32 [OPT=true]
#
########################################################################
# Source lists
LIBNAME=gctest
SOURCES=gctest.c ../agent_util/agent_util.c
# Solaris Studio C Compiler Version 12.4
ifeq ($(OSNAME), solaris)
# Sun Solaris Compiler options needed
COMMON_FLAGS=-mt -KPIC
# Options that help find errors
COMMON_FLAGS+= -Xa -v -xc99=%none
# Check LIBARCH for any special compiler options
LIBARCH=$(shell uname -p)
ifeq ($(LIBARCH), sparc)
COMMON_FLAGS+=-xarch=v8 -xregs=no%appl
endif
ifeq ($(LIBARCH), sparcv9)
COMMON_FLAGS+=-xarch=v9 -xregs=no%appl
endif
ifeq ($(OPT), true)
CFLAGS=-xO2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-z defs -ztext
# Libraries we are dependent on
LIBRARIES= -lc
# Building a shared library
LINK_SHARED=$(LINK.c) -G -o $@
endif
# Linux GNU C Compiler
ifeq ($(OSNAME), linux)
# GNU Compiler options needed to build it
COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer
# Options that help find errors
COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses
ifeq ($(OPT), true)
CFLAGS=-O2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc
# Libraries we are dependent on
LIBRARIES=-lc
# Building a shared library
LINK_SHARED=$(LINK.c) -shared -o $@
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OSNAME), win32)
CC=cl
# Compiler options needed to build it
COMMON_FLAGS=-Gy -DWIN32
# Options that help find errors
COMMON_FLAGS+=-W0 -WX
ifeq ($(OPT), true)
CFLAGS= -Ox -Op -Zi $(COMMON_FLAGS)
else
CFLAGS= -Od -Zi $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.obj)
# Library name and options needed to build it
LIBRARY=$(LIBNAME).dll
LDFLAGS=
# Libraries we are dependent on
LIBRARIES=
# Building a shared library
LINK_SHARED=link -dll -out:$@
endif
# Common -I options
CFLAGS += -I.
CFLAGS += -I../agent_util
CFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME)
# Default rule
all: $(LIBRARY)
# Build native library
$(LIBRARY): $(OBJECTS)
$(LINK_SHARED) $(OBJECTS) $(LIBRARIES)
# Cleanup the built bits
clean:
rm -f $(LIBRARY) $(OBJECTS)
# Simple tester
test: all
LD_LIBRARY_PATH=`pwd` $(JDK)/bin/java -agentlib:$(LIBNAME) -version
# Compilation rule only needed on Windows
ifeq ($(OSNAME), win32)
%.obj: %.c
$(COMPILE.c) $<
endif

View File

@ -1,66 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* Java class to hold static methods which will be called in byte code
* injections of all class files.
*/
public class HeapTracker {
private static int engaged = 0;
private static native void _newobj(Object thread, Object o);
public static void newobj(Object o)
{
if ( engaged != 0 ) {
_newobj(Thread.currentThread(), o);
}
}
private static native void _newarr(Object thread, Object a);
public static void newarr(Object a)
{
if ( engaged != 0 ) {
_newarr(Thread.currentThread(), a);
}
}
}

View File

@ -1,47 +0,0 @@
#
# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
heapTracker
This agent library can be used to track object allocations.
It uses the same java_crw_demo library used by HPROF to do BCI
on all classfiles loaded into the Virtual Machine.
You can use this agent library as follows:
java -agentlib:heapTracker ...
To get help on the available options try:
java -agentlib:heapTracker=help
See ${JAVA_HOME}/demo/jvmti/index.html for help running and building agents.

File diff suppressed because it is too large Load Diff

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* Primary heapTracker #include file, should be included by most if not
* all heapTracker source files. Gives access to the global data structure
* and all global macros.
*/
#ifndef HEAP_TRACKER_H
#define HEAP_TRACKER_H
/* Standard C functions used throughout. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdarg.h>
/* General JVM/Java functions, types and macros. */
#include <sys/types.h>
#include "jni.h"
#include "jvmti.h"
/* Utility functions */
#include "agent_util.h"
#endif

View File

@ -1,163 +0,0 @@
#
# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
########################################################################
#
# Sample GNU Makefile for building JVMTI Demo heapTracker
#
# Example uses:
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparc]
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparcv9]
# gnumake JDK=<java_home> OSNAME=linux [OPT=true]
# gnumake JDK=<java_home> OSNAME=win32 [OPT=true]
#
########################################################################
# Source lists
LIBNAME=heapTracker
SOURCES=heapTracker.c ../agent_util/agent_util.c
JAVA_SOURCES=HeapTracker.java
# Name of jar file that needs to be created
JARFILE=heapTracker.jar
# Solaris Studio C Compiler Version 12.4
ifeq ($(OSNAME), solaris)
# Sun Solaris Compiler options needed
COMMON_FLAGS=-mt -KPIC
# Options that help find errors
COMMON_FLAGS+= -Xa -v -xc99=%none
# Check LIBARCH for any special compiler options
LIBARCH=$(shell uname -p)
ifeq ($(LIBARCH), sparc)
COMMON_FLAGS+=-xarch=v8 -xregs=no%appl
endif
ifeq ($(LIBARCH), sparcv9)
COMMON_FLAGS+=-xarch=v9 -xregs=no%appl
endif
ifeq ($(OPT), true)
CFLAGS=-xO2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-z defs -ztext
# Libraries we are dependent on
LIBRARIES=-L $(JDK)/jre/lib/$(LIBARCH) -ljava_crw_demo -lc
# Building a shared library
LINK_SHARED=$(LINK.c) -G -o $@
endif
# Linux GNU C Compiler
ifeq ($(OSNAME), linux)
# GNU Compiler options needed to build it
COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer
# Options that help find errors
COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses
ifeq ($(OPT), true)
CFLAGS=-O2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc
# Libraries we are dependent on
LIBRARIES=-L $(JDK)/jre/lib/$(LIBARCH) -ljava_crw_demo -lc
# Building a shared library
LINK_SHARED=$(LINK.c) -shared -o $@
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OSNAME), win32)
CC=cl
# Compiler options needed to build it
COMMON_FLAGS=-Gy -DWIN32
# Options that help find errors
COMMON_FLAGS+=-W0 -WX
ifeq ($(OPT), true)
CFLAGS= -Ox -Op -Zi $(COMMON_FLAGS)
else
CFLAGS= -Od -Zi $(COMMON_FLAGS)
endif
# Sources need java_crw_demo
SOURCES += ../java_crw_demo/java_crw_demo.c
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.obj)
# Library name and options needed to build it
LIBRARY=$(LIBNAME).dll
LDFLAGS=
# Libraries we are dependent on
LIBRARIES=$(JDK)/
# Building a shared library
LINK_SHARED=link -dll -out:$@
endif
# Common -I options
CFLAGS += -I.
CFLAGS += -I../agent_util
CFLAGS += -I../java_crw_demo
CFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME)
# Default rule (build both native library and jar file)
all: $(LIBRARY) $(JARFILE)
# Build native library
$(LIBRARY): $(OBJECTS)
$(LINK_SHARED) $(OBJECTS) $(LIBRARIES)
# Build jar file
$(JARFILE): $(JAVA_SOURCES)
rm -f -r classes
mkdir -p classes
$(JDK)/bin/javac -d classes $(JAVA_SOURCES)
(cd classes; $(JDK)/bin/jar cf ../$@ *)
# Cleanup the built bits
clean:
rm -f -r classes
rm -f $(LIBRARY) $(JARFILE) $(OBJECTS)
# Simple tester
test: all
LD_LIBRARY_PATH=. $(JDK)/bin/java -agentlib:$(LIBNAME) -Xbootclasspath/a:./$(JARFILE) -version
# Compilation rule only needed on Windows
ifeq ($(OSNAME), win32)
%.obj: %.c
$(COMPILE.c) $<
endif

View File

@ -1,56 +0,0 @@
#
# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
heapViewer
This agent library demonstrates how to get an easy view of the
heap in terms of total object count and space used.
It uses GetLoadedClasses(), SetTag(), and IterateThroughHeap()
to count up all the objects of all the current loaded classes.
The heap dump will happen at the event JVMTI_EVENT_VM_DEATH, or the
event JVMTI_EVENT_DATA_DUMP_REQUEST.
It also demonstrates some more robust agent error handling using
GetErrorName(),
Using the heap iterate functions, lots of statistics can be generated
without resorting to using Byte Code Instrumentation (BCI).
You can use this agent library as follows:
java -agentlib:heapViewer ...
To get help on the available options try:
java -agentlib:heapViewer=help
See ${JAVA_HOME}/demo/jvmti/index.html for help running and building agents.

View File

@ -1,288 +0,0 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#include <stdio.h>
#include <stddef.h>
#include <stdlib.h>
#include <string.h>
#include "jni.h"
#include "jvmti.h"
#include "agent_util.h"
/* Global static data */
typedef struct {
jboolean vmDeathCalled;
jboolean dumpInProgress;
jrawMonitorID lock;
} GlobalData;
static GlobalData globalData, *gdata = &globalData;
/* Typedef to hold class details */
typedef struct {
char *signature;
int count;
int space;
} ClassDetails;
/* Enter agent monitor protected section */
static void
enterAgentMonitor(jvmtiEnv *jvmti)
{
jvmtiError err;
err = (*jvmti)->RawMonitorEnter(jvmti, gdata->lock);
check_jvmti_error(jvmti, err, "raw monitor enter");
}
/* Exit agent monitor protected section */
static void
exitAgentMonitor(jvmtiEnv *jvmti)
{
jvmtiError err;
err = (*jvmti)->RawMonitorExit(jvmti, gdata->lock);
check_jvmti_error(jvmti, err, "raw monitor exit");
}
/* Heap object callback */
static jint JNICALL
cbHeapObject(jlong class_tag, jlong size, jlong* tag_ptr, jint length,
void* user_data)
{
if ( class_tag != (jlong)0 ) {
ClassDetails *d;
d = (ClassDetails*)(void*)(ptrdiff_t)class_tag;
(*((jint*)(user_data)))++;
d->count++;
d->space += (int)size;
}
return JVMTI_VISIT_OBJECTS;
}
/* Compare two ClassDetails */
static int
compareDetails(const void *p1, const void *p2)
{
return ((ClassDetails*)p2)->space - ((ClassDetails*)p1)->space;
}
/* Callback for JVMTI_EVENT_DATA_DUMP_REQUEST (Ctrl-\ or at exit) */
static void JNICALL
dataDumpRequest(jvmtiEnv *jvmti)
{
enterAgentMonitor(jvmti); {
if ( !gdata->vmDeathCalled && !gdata->dumpInProgress ) {
jvmtiHeapCallbacks heapCallbacks;
ClassDetails *details;
jvmtiError err;
jclass *classes;
jint totalCount;
jint count;
jint i;
gdata->dumpInProgress = JNI_TRUE;
/* Get all the loaded classes */
err = (*jvmti)->GetLoadedClasses(jvmti, &count, &classes);
check_jvmti_error(jvmti, err, "get loaded classes");
/* Setup an area to hold details about these classes */
details = (ClassDetails*)calloc(sizeof(ClassDetails), count);
if ( details == NULL ) {
fatal_error("ERROR: Ran out of malloc space\n");
}
for ( i = 0 ; i < count ; i++ ) {
char *sig;
/* Get and save the class signature */
err = (*jvmti)->GetClassSignature(jvmti, classes[i], &sig, NULL);
check_jvmti_error(jvmti, err, "get class signature");
if ( sig == NULL ) {
fatal_error("ERROR: No class signature found\n");
}
details[i].signature = strdup(sig);
deallocate(jvmti, sig);
/* Tag this jclass */
err = (*jvmti)->SetTag(jvmti, classes[i],
(jlong)(ptrdiff_t)(void*)(&details[i]));
check_jvmti_error(jvmti, err, "set object tag");
}
/* Iterate through the heap and count up uses of jclass */
(void)memset(&heapCallbacks, 0, sizeof(heapCallbacks));
heapCallbacks.heap_iteration_callback = &cbHeapObject;
totalCount = 0;
err = (*jvmti)->IterateThroughHeap(jvmti,
JVMTI_HEAP_FILTER_CLASS_UNTAGGED, NULL,
&heapCallbacks, (const void *)&totalCount);
check_jvmti_error(jvmti, err, "iterate through heap");
/* Remove tags */
for ( i = 0 ; i < count ; i++ ) {
/* Un-Tag this jclass */
err = (*jvmti)->SetTag(jvmti, classes[i], (jlong)0);
check_jvmti_error(jvmti, err, "set object tag");
}
/* Sort details by space used */
qsort(details, count, sizeof(ClassDetails), &compareDetails);
/* Print out sorted table */
stdout_message("Heap View, Total of %d objects found.\n\n",
totalCount);
stdout_message("Space Count Class Signature\n");
stdout_message("---------- ---------- ----------------------\n");
for ( i = 0 ; i < count ; i++ ) {
if ( details[i].space == 0 || i > 20 ) {
break;
}
stdout_message("%10d %10d %s\n",
details[i].space, details[i].count, details[i].signature);
}
stdout_message("---------- ---------- ----------------------\n\n");
/* Free up all allocated space */
deallocate(jvmti, classes);
for ( i = 0 ; i < count ; i++ ) {
if ( details[i].signature != NULL ) {
free(details[i].signature);
}
}
free(details);
gdata->dumpInProgress = JNI_FALSE;
}
} exitAgentMonitor(jvmti);
}
/* Callback for JVMTI_EVENT_VM_INIT */
static void JNICALL
vmInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
enterAgentMonitor(jvmti); {
jvmtiError err;
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_DATA_DUMP_REQUEST, NULL);
check_jvmti_error(jvmti, err, "set event notification");
} exitAgentMonitor(jvmti);
}
/* Callback for JVMTI_EVENT_VM_DEATH */
static void JNICALL
vmDeath(jvmtiEnv *jvmti, JNIEnv *env)
{
jvmtiError err;
/* Make sure everything has been garbage collected */
err = (*jvmti)->ForceGarbageCollection(jvmti);
check_jvmti_error(jvmti, err, "force garbage collection");
/* Disable events and dump the heap information */
enterAgentMonitor(jvmti); {
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_DISABLE,
JVMTI_EVENT_DATA_DUMP_REQUEST, NULL);
check_jvmti_error(jvmti, err, "set event notification");
dataDumpRequest(jvmti);
gdata->vmDeathCalled = JNI_TRUE;
} exitAgentMonitor(jvmti);
}
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
JNIEXPORT jint JNICALL
DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{
jint rc;
jvmtiError err;
jvmtiCapabilities capabilities;
jvmtiEventCallbacks callbacks;
jvmtiEnv *jvmti;
/* Get JVMTI environment */
jvmti = NULL;
rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION);
if (rc != JNI_OK) {
fatal_error("ERROR: Unable to create jvmtiEnv, error=%d\n", rc);
return -1;
}
if ( jvmti == NULL ) {
fatal_error("ERROR: No jvmtiEnv* returned from GetEnv\n");
}
/* Get/Add JVMTI capabilities */
(void)memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_tag_objects = 1;
capabilities.can_generate_garbage_collection_events = 1;
err = (*jvmti)->AddCapabilities(jvmti, &capabilities);
check_jvmti_error(jvmti, err, "add capabilities");
/* Create the raw monitor */
err = (*jvmti)->CreateRawMonitor(jvmti, "agent lock", &(gdata->lock));
check_jvmti_error(jvmti, err, "create raw monitor");
/* Set callbacks and enable event notifications */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.VMInit = &vmInit;
callbacks.VMDeath = &vmDeath;
callbacks.DataDumpRequest = &dataDumpRequest;
err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
check_jvmti_error(jvmti, err, "set event callbacks");
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_VM_INIT, NULL);
check_jvmti_error(jvmti, err, "set event notifications");
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_VM_DEATH, NULL);
check_jvmti_error(jvmti, err, "set event notifications");
return 0;
}
/* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL
DEF_Agent_OnUnload(JavaVM *vm)
{
}

View File

@ -1,147 +0,0 @@
#
# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
########################################################################
#
# Sample GNU Makefile for building JVMTI Demo heapViewer
#
# Example uses:
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparc]
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparcv9]
# gnumake JDK=<java_home> OSNAME=linux [OPT=true]
# gnumake JDK=<java_home> OSNAME=win32 [OPT=true]
#
########################################################################
# Source lists
LIBNAME=heapViewer
SOURCES=heapViewer.c ../agent_util/agent_util.c
# Solaris Studio C Compiler Version 12.4
ifeq ($(OSNAME), solaris)
# Sun Solaris Compiler options needed
COMMON_FLAGS=-mt -KPIC
# Options that help find errors
COMMON_FLAGS+= -Xa -v -xc99=%none
# Check LIBARCH for any special compiler options
LIBARCH=$(shell uname -p)
ifeq ($(LIBARCH), sparc)
COMMON_FLAGS+=-xarch=v8 -xregs=no%appl
endif
ifeq ($(LIBARCH), sparcv9)
COMMON_FLAGS+=-xarch=v9 -xregs=no%appl
endif
ifeq ($(OPT), true)
CFLAGS=-xO2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-z defs -ztext
# Libraries we are dependent on
LIBRARIES= -lc
# Building a shared library
LINK_SHARED=$(LINK.c) -G -o $@
endif
# Linux GNU C Compiler
ifeq ($(OSNAME), linux)
# GNU Compiler options needed to build it
COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer
# Options that help find errors
COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses
ifeq ($(OPT), true)
CFLAGS=-O2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc
# Libraries we are dependent on
LIBRARIES=-lc
# Building a shared library
LINK_SHARED=$(LINK.c) -shared -o $@
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OSNAME), win32)
CC=cl
# Compiler options needed to build it
COMMON_FLAGS=-Gy -DWIN32
# Options that help find errors
COMMON_FLAGS+=-W0 -WX
ifeq ($(OPT), true)
CFLAGS= -Ox -Op -Zi $(COMMON_FLAGS)
else
CFLAGS= -Od -Zi $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.obj)
# Library name and options needed to build it
LIBRARY=$(LIBNAME).dll
LDFLAGS=
# Libraries we are dependent on
LIBRARIES=
# Building a shared library
LINK_SHARED=link -dll -out:$@
endif
# Common -I options
CFLAGS += -I.
CFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME)
# Default rule
all: $(LIBRARY)
# Build native library
$(LIBRARY): $(OBJECTS)
$(LINK_SHARED) $(OBJECTS) $(LIBRARIES)
# Cleanup the built bits
clean:
rm -f $(LIBRARY) $(OBJECTS)
# Simple tester
test: all
LD_LIBRARY_PATH=`pwd` $(JDK)/bin/java -agentlib:$(LIBNAME) -version
# Compilation rule only needed on Windows
ifeq ($(OSNAME), win32)
%.obj: %.c
$(COMPILE.c) $<
endif

View File

@ -1,430 +0,0 @@
<html>
<head> <title>JVM TI Demonstration Code</title> </head>
<h1>JVM TI Demonstration Code</h1>
<p>
The
Java&trade; Virtual Machine Tools Interface (JVM TI)
is a native tool interface provided in JDK 5.0 and newer.
Native libraries that use JVM TI and are loaded into the
Java Virtual Machine
via the -agentlib, -agentpath, or -Xrun (deprecated) interfaces, are
called Agents.
<p>
<A HREF="http://java.sun.com/j2se/latest/docs/guide/jvmti">JVM TI</A>
was designed to work with the
Java Native Interface
(<A HREF="http://java.sun.com/j2se/latest/docs/guide/jni">JNI</A>),
and eventually displace the
Java Virtual Machine Debugging Interface
(<A HREF="http://java.sun.com/j2se/1.5.0/docs/guide/jpda/jvmdi-spec.html">JVMDI</A>)
and the
Java Virtual Machine Profiling Interface
(<A HREF="http://java.sun.com/j2se/1.5.0/docs/guide/jvmpi/index.html">JVMPI</A>).
<p>
We have created a set of demonstration agents that should
help show many of the features and abilities of the
interface. This list of demonstration agents will change over time.
They are provided as educational tools and as starting
points for Java tool development.
<p>
These agents are built with every JDK build and some basic testing is performed
on a regular basis, but no extensive testbases currently
exist for these agents.
Every JDK installation should include all the pre-built binaries and sources for
all these agents, just look in the demo/jvmti directory of your JDK.
<h2>Using or Running These Agents</h2>
<p>
Using these agents will require the VM to locate the shared library file
before any actual Java code is run.
The JDK installation should contain all the agent libraries in
the ${JAVA_HOME}/demo/jvmti/<i>agent-name</i>/lib directories.
The Solaris 64bit version would be contained in the sparcv9 or amd64
subdirectory.
If 'java' complains that it can't find the library,
you may need to add the directory containing the library into the
LD_LIBRARY_PATH environment variable (Unix), or the PATH environment
variable (Windows).
This is system and platform specific.
If you are using 64bit Solaris (e.g. 'java -d64'),
you should use LD_LIBRARY_PATH64.
Some agents such as the jdwp (debugger backend)
are located inside the primary JDK directories and will always be found
in those locations.
<p>
The agents that instrument classfiles
(i.e. BCI, usually through the java_crw_demo library)
such as heapTracker, mtrace, and minst,
also need to have the Java classes they use available in the bootclasspath.
The agents will make attempts at automatically adding their jar file
(e.g. heapTracker.jar, mtrace.jar, or minst.jar) to the bootclasspath
with AddToBootstrapClassLoaderSearch from JVM TI at startup
(see the agent_util code).
This is done by locating this jar file at
${JAVA_HOME}/demo/jvmti/<i>agent-name</i>
where JAVA_HOME is obtained by calling GetSystemProperty from JVM TI
with "java.home".
We recognize that this is not ideal, but felt that as just demonstration
code it was acceptable.
Ideally the agent could find out the actual directory it came from and
locate the jar file relative to that location.
Our demonstration agents currently do not do this.
<p>
If you choose to modify or change these agents, the above information
is important in making everything is found.
It is recommended that you change the name of the agent when you
modify it to avoid conflicts with the existing demo agents.
Or better yet, go to http://jdk.dev.java.net and submit your
changes to the agent as an RFE to the JDK.
<h2> Demonstration Agents Available </h2>
<ul>
<li>
<A HREF="versionCheck">versionCheck</A>
<br>
This is a extremely small agent that does nothing but check the
version string supplied in the jvmti.h file, with the version
number supplied by the VM at runtime.
</li>
<li>
<A HREF="compiledMethodLoad">compiledMethodLoad</A>
<br>
This is a small agent that traces CompiledMethodLoad events along
with the HotSpot specific compile_info parameter.
</li>
<li>
<A HREF="mtrace">mtrace</A>
<br>
This is a small agent that does method tracing.
It uses Bytecode Instrumentation (BCI) via the java_crw_demo library.
</li>
<li>
<A HREF="minst">minst</A>
<br>
This is an even smaller agent that does just method entry tracing.
It also uses Bytecode Instrumentation (BCI) via the java_crw_demo library,
but the instrumentation code is pure Java (no Java native methods used).
NOTE: Be sure to check out java.lang.instrument for a way to avoid
native code agents completely.
</li>
<li>
<A HREF="gctest">gctest</A>
<br>
This is a small agent that does garbage collection counting.
</li>
<li>
<A HREF="heapViewer">heapViewer</A>
<br>
This is a small agent that does some basic heap inspections.
</li>
<li>
<A HREF="heapTracker">heapTracker</A>
<br>
This is a small agent that does BCI to capture object creation
and track them.
It uses Bytecode Instrumentation (BCI) via the java_crw_demo library.
</li>
<li>
<A HREF="waiters">waiters</A>
<br>
This is a small agent that gets information about threads
waiting on monitors.
</li>
</ul>
<h2>Agent Support</h2>
<ul>
<li>
<A HREF="java_crw_demo">java_crw_demo</A>
<br>
This is a demo C library that does class file to class file
transformations or BCI (Bytecode Instrumentation).
It is used by several of the above agents.
</li>
</ul>
<h2>Native Library Build Hints</h2>
<p>
All libraries loaded into java are assumed to be MT-safe (Multi-thread safe).
This means that multiple threads could be executing the code at the same
time, and static or global data may need to be placed in critical
sections. See the Raw Monitor interfaces for more information.
<p>
All native libraries loaded into the
Java Virtual Machine,
including Agent libraries,
need to be compiled and built in a compatible way.
Certain native compilation options or optimizations should be avoided,
and some are required.
More information on this options is available in the man pages for
the various compilers.
<p>
Some native compiler and linker options can create fatal or
erroneous behavior when native agent libraries are operating
inside the Java Virtual Machine.
It would take too many words to describe all the possible issues with all
the native compiler options, optimizations, and settings.
Here are some recommendations on the basic compiler and linker options
we recommend:
<ul>
<h3> Solaris </h3>
<li>
On Solaris, using the Sun Studio 11 C compiler,
the typical compile and link command lines might look something like:
<br>
For 32bit SPARC:
<br>
<code><ul>
cc -xO2 -mt -xregs=no%appl -xmemalign=4s -xarch=v8 -KPIC -c <i>*.c</i>
<br>
cc -mt -xarch=v8 -z defs -ztext -G -o <i>libXXX.so *.o</i> -lc
</code></ul>
<br>
For 64bit SPARC:
<br>
<code><ul>
cc -xO2 -mt -xregs=no%appl -xarch=v9 -KPIC -c <i>*.c</i>
<br>
cc -mt -xarch=v9 -z defs -ztext -G -o <i>libXXX.so *.o</i> -lc
</code></ul>
<br>
For X86:
<br>
<code><ul>
cc -xO2 -mt -xregs=no%frameptr -KPIC -c <i>*.c</i>
<br>
cc -mt -z defs -ztext -G -o <i>libXXX.so *.o</i> -lc
</code></ul>
<br>
For AMD64:
<br>
<code><ul>
cc -xO2 -mt -xregs=no%frameptr -xarch=amd64 -KPIC -c <i>*.c</i>
<br>
cc -mt -xarch=amd64 -z defs -ztext -G -o <i>libXXX.so *.o</i> -lc
</code></ul>
<br>
</li>
<li>
Architecture/File Format:
For SPARC 32bit use <code>-xarch=v8</code>,
for SPARC 64bit use <code>-xarch=v9</code>,
for X86 (32-bit)
<i>
leave the option off or use <code>-xarch=generic</code>
</i>,
and for AMD64 (64bit) use <code>-xarch=amd64</code>
with both C and C++.
<br>
This is to be specific as to the architecture and the file format
of the .o files (and ultimately of the .so).
</li>
<li>
MT-Safe, Position Independent: Use <code>-KPIC -mt</code>
with both C and C++.
</li>
<li>
Register usage: For SPARC (both 32bit and 64bit) use
<code>-xregs=no%appl</code> and for X86 and AMD64 use <code>-xregs=no%frameptr</code>
with both C and C++.
</li>
<li>
Alignment: For SPARC 32bit use -xmemalign=4s and for SPARC 64bit do NOT use <code>-xmemalign=4</code>
with both C and C++.
</li>
<li>
Dependencies: Use <code>ldd -r <i>LibraryName</i></code>.
<br>
After the shared library has been built, the utility
<code>ldd</code> can be used to verify that all dependent libraries
have been satisfied, and all externs can be found.
If <code>ldd</code> says anything is missing, it is very likely that the JVM will also
be unable to load this library.
This usually means that you missed some <code>-l<i>name</i></code>
options when building the library, or perhaps forgot a <code>-R path</code>
option that tells the library where to look for libraries at runtime.
</li>
<h3> Linux </h3>
<li>
On Linux, using the gcc version 3.2,
the typical compile and link command lines might look something like:
<br>
For X86:
<br>
<code><ul>
gcc -O2 -fPIC -pthread -DLINUX -c <i>*.c</i>
<br>
gcc -z defs -static-libgcc -shared -o <i>libXXX.so *.o</i> -lc
</code></ul>
<br>
For AMD64:
<br>
<code><ul>
gcc -O2 -fPIC -pthread -DLINUX -D_LP64=1 -c <i>*.c</i>
<br>
gcc -z defs -static-libgcc -shared -o <i>libXXX.so *.o</i> -lc
</code></ul>
<br>
</li>
<li>
MT-Safe, Position Independent:
Use <code>-fPIC -pthread</code>.
</li>
<li>
Agent Demo Code: Needs -DLINUX
</li>
<li>
Register Usage: Use <code>-fno-omit-frame-pointer</code>.
<br>
It is important that these libraries have frame pointer register usage, see the above comments on the Solaris
<code>-xregs=no%frameptr</code>
option.
</li>
<li>
Library: Use -static-libgcc.
<br>
When building the shared library (-shared option), this option
allows for maximum portability of the library between different
flavors of Linux.
The problem we have seen with Linux is that we cannot depend
on a compatible shared gcc library existing on all the versions of
Linux we can run on.
By doing this static link, the version script becomes more
important, making sure you don't expose any extern symbols
you didn't intend to.
</li>
<li>
Dependencies: Use <code>ldd -r <i>LibraryName</i></code>.
<br>
Provides the same checking as Solaris (see above).
</li>
<h3> Windows </h3>
<li>
On Windows and using the Microsoft C++ Compiler Visual Studio .NET 2003,
the typical compile and link command lines might look something like:
<br>
For X86:
<br>
<code><ul>
cl /O1 /MD /D _STATIC_CPPLIB /c <i>*.c</i>
<br>
link /dll /opt:REF /out:<i>XXX.dll *.obj</i>
</code></ul>
<br>
For AMD64:
<br>
<code><ul>
cl /O1 /MD /D _STATIC_CPPLIB /c <i>*.c</i>
<br>
link /dll /opt:REF /out:<i>XXX.dll *.obj</i>
</code></ul>
<br>
</li>
<li>
Library: Use <code>/opt:REF </code> when building the dll.
</li>
<li>
MS DLL Runtime: Use the <code>/MD /D _STATIC_CPPLIB</code> option.
<br>
This causes your dll to become dependent on just MSVCR*.DLL.
The option /D _STATIC_CPPLIB prevents you from becoming dependent on the
C++ library MSVCP*.DLL.
This is what we use in the JDK, but there are probably many combinations
that you could safely use, unfortunately there are many combinations
of runtimes that will not work.
Check the Microsoft site on proper use of runtimes.
</li>
<li>
Dependencies: Use VC++ <code>dumpbin /exports</code> and the VC++ "Dependency Walker".
<br>
Provides dependency information similar to <code>ldd</code>.
</li>
</ul>
<h2>For More Information</h2>
<p>
Remember, the complete source to all these agents is contained in the JDK
installations at demo/jvmti.
<p>
For more detailed information on JVM TI, refer to
<A HREF="http://java.sun.com/j2se/latest/docs/guide/jvmti">
http://java.sun.com/j2se/latest/docs/guide/jvmti.</A>
<p>
More information on using JNI and building native libraries refer to:
<A HREF="http://java.sun.com/j2se/latest/docs/guide/jni">
http://java.sun.com/j2se/latest/docs/guide/jni</A>.
<p>
Additional information can also be found by doing a search on "jvmti" at
<A HREF="http://java.sun.com/j2se">http://java.sun.com/j2se</A>.
Various technical articles are also available through this website.
And don't forget the
Java Tutorials at
<A HREF="http://docs.oracle.com/javase/tutorial">http://docs.oracle.com/javase/tutorial</A>
for getting a quick start on all the various interfaces.
<h2>Comments and Feedback</h2>
<p>
Comments regarding JVM TI or on any of these demonstrations should be
sent through
<A HREF="http://java.sun.com/mail">http://java.sun.com/mail/</A>
</html>

View File

@ -1,77 +0,0 @@
#
# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
java_crw_demo Library
The library java_crw_demo is a small C library that is used by HPROF
and other agent libraries to do some very basic bytecode
insertion (BCI) of class files. This is not an agent
library but a general purpose library that can be used to do some
very limited bytecode insertion.
In the demo sources, look for the use of java_crw_demo.h and
the C function java_crw_demo(). The java_crw_demo library is provided
as part of the JRE.
The basic BCI that this library does includes:
* On entry to the java.lang.Object init method (signature "()V"),
a invokestatic call to tclass.obj_init_method(object); is inserted.
* On any newarray type opcode, immediately following it, the array
object is duplicated on the stack and an invokestatic call to
tclass.newarray_method(object); is inserted.
* On entry to all methods, a invokestatic call to
tclass.call_method(cnum,mnum); is inserted. The agent can map the
two integers (cnum,mnum) to a method in a class, the cnum is the
number provided to the java_crw_demo library when the classfile was
modified.
* On return from any method (any return opcode), a invokestatic call to
tclass.return_method(cnum,mnum); is inserted.
Some methods are not modified at all, init methods and finalize methods
whose length is 1 will not be modified. Classes that are designated
"system" will not have their clinit methods modified. In addition, the
method java.lang.Thread.currentThread() is not modified.
No methods or fields will be added to any class, however new constant
pool entries will be added at the end of the original constant pool table.
The exception, line, and local variable tables for each method is adjusted
for the modification. The bytecodes are compressed to use smaller offsets
and the fewest 'wide' opcodes.
All attempts are made to minimize the number of bytecodes at each insertion
site, however, classes with N return opcodes or N newarray opcodes will get
N insertions. And only the necessary modification dictated by the input
arguments to java_crw_demo are actually made.

File diff suppressed because it is too large Load Diff

View File

@ -1,196 +0,0 @@
/*
* Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#ifndef JAVA_CRW_DEMO_H
#define JAVA_CRW_DEMO_H
#include <jni.h>
#ifdef __cplusplus
extern "C" {
#endif
/* This callback is used to notify the caller of a fatal error. */
typedef void (*FatalErrorHandler)(const char*message, const char*file, int line);
/* This callback is used to return the method information for a class.
* Since the information was already read here, it was useful to
* return it here, with no JVMTI phase restrictions.
* If the class file does represent a "class" and it has methods, then
* this callback will be called with the class number and pointers to
* the array of names, array of signatures, and the count of methods.
*/
typedef void (*MethodNumberRegister)(unsigned, const char**, const char**, int);
/* Class file reader/writer interface. Basic input is a classfile image
* and details about what to inject. The output is a new classfile image
* that was allocated with malloc(), and should be freed by the caller.
*/
/* Names of external symbols to look for. These are the names that we
* try and lookup in the shared library. On Windows 2000, the naming
* convention is to prefix a "_" and suffix a "@N" where N is 4 times
* the number or arguments supplied.It has 19 args, so 76 = 19*4.
* On Windows 2003, Linux, and Solaris, the first name will be
* found, on Windows 2000 a second try should find the second name.
*
* WARNING: If You change the JavaCrwDemo typedef, you MUST change
* multiple things in this file, including this name.
*/
#define JAVA_CRW_DEMO_SYMBOLS { "java_crw_demo", "_java_crw_demo@76" }
/* Typedef needed for type casting in dynamic access situations. */
typedef void (JNICALL *JavaCrwDemo)(
unsigned class_number,
const char *name,
const unsigned char *file_image,
long file_len,
int system_class,
char* tclass_name,
char* tclass_sig,
char* call_name,
char* call_sig,
char* return_name,
char* return_sig,
char* obj_init_name,
char* obj_init_sig,
char* newarray_name,
char* newarray_sig,
unsigned char **pnew_file_image,
long *pnew_file_len,
FatalErrorHandler fatal_error_handler,
MethodNumberRegister mnum_callback
);
/* Function export (should match typedef above) */
JNIEXPORT void JNICALL java_crw_demo(
unsigned class_number, /* Caller assigned class number for class */
const char *name, /* Internal class name, e.g. java/lang/Object */
/* (Do not use "java.lang.Object" format) */
const unsigned char
*file_image, /* Pointer to classfile image for this class */
long file_len, /* Length of the classfile in bytes */
int system_class, /* Set to 1 if this is a system class */
/* (prevents injections into empty */
/* <clinit>, finalize, and <init> methods) */
char* tclass_name, /* Class that has methods we will call at */
/* the injection sites (tclass) */
char* tclass_sig, /* Signature of tclass */
/* (Must be "L" + tclass_name + ";") */
char* call_name, /* Method name in tclass to call at offset 0 */
/* for every method */
char* call_sig, /* Signature of this call_name method */
/* (Must be "(II)V") */
char* return_name, /* Method name in tclass to call at all */
/* return opcodes in every method */
char* return_sig, /* Signature of this return_name method */
/* (Must be "(II)V") */
char* obj_init_name, /* Method name in tclass to call first thing */
/* when injecting java.lang.Object.<init> */
char* obj_init_sig, /* Signature of this obj_init_name method */
/* (Must be "(Ljava/lang/Object;)V") */
char* newarray_name, /* Method name in tclass to call after every */
/* newarray opcode in every method */
char* newarray_sig, /* Signature of this method */
/* (Must be "(Ljava/lang/Object;II)V") */
unsigned char
**pnew_file_image, /* Returns a pointer to new classfile image */
long *pnew_file_len, /* Returns the length of the new image */
FatalErrorHandler
fatal_error_handler, /* Pointer to function to call on any */
/* fatal error. NULL sends error to stderr */
MethodNumberRegister
mnum_callback /* Pointer to function that gets called */
/* with all details on methods in this */
/* class. NULL means skip this call. */
);
/* External to read the class name out of a class file .
*
* WARNING: If You change the typedef, you MUST change
* multiple things in this file, including this name.
*/
#define JAVA_CRW_DEMO_CLASSNAME_SYMBOLS \
{ "java_crw_demo_classname", "_java_crw_demo_classname@12" }
/* Typedef needed for type casting in dynamic access situations. */
typedef char * (JNICALL *JavaCrwDemoClassname)(
const unsigned char *file_image,
long file_len,
FatalErrorHandler fatal_error_handler);
JNIEXPORT char * JNICALL java_crw_demo_classname(
const unsigned char *file_image,
long file_len,
FatalErrorHandler fatal_error_handler);
#ifdef __cplusplus
} /* extern "C" */
#endif /* __cplusplus */
#endif

View File

@ -1,144 +0,0 @@
#
# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
########################################################################
#
# Sample GNU Makefile for building
#
# Example uses:
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparc]
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparcv9]
# gnumake JDK=<java_home> OSNAME=linux [OPT=true]
# gnumake JDK=<java_home> OSNAME=win32 [OPT=true]
#
########################################################################
# Source lists
LIBNAME=java_crw_demo
SOURCES=java_crw_demo.c
# Solaris Studio C Compiler Version 12.4
ifeq ($(OSNAME), solaris)
# Sun Solaris Compiler options needed
COMMON_FLAGS=-mt -KPIC
# Options that help find errors
COMMON_FLAGS+= -Xa -v -xc99=%none
# Check LIBARCH for any special compiler options
LIBARCH=$(shell uname -p)
ifeq ($(LIBARCH), sparc)
COMMON_FLAGS+=-xarch=v8 -xregs=no%appl
endif
ifeq ($(LIBARCH), sparcv9)
COMMON_FLAGS+=-xarch=v9 -xregs=no%appl
endif
ifeq ($(OPT), true)
CFLAGS=-xO2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-z defs -ztext
# Libraries we are dependent on
LIBRARIES=-lc
# Building a shared library
LINK_SHARED=$(LINK.c) -G -o $@
endif
# Linux GNU C Compiler
ifeq ($(OSNAME), linux)
# GNU Compiler options needed to build it
COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer
# Options that help find errors
COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses
ifeq ($(OPT), true)
CFLAGS=-O2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc
# Libraries we are dependent on
LIBRARIES=-lc
# Building a shared library
LINK_SHARED=$(LINK.c) -shared -o $@
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OSNAME), win32)
CC=cl
# Compiler options needed to build it
COMMON_FLAGS=-Gy -DWIN32
# Options that help find errors
COMMON_FLAGS+=-W0 -WX
ifeq ($(OPT), true)
CFLAGS= -Ox -Op -Zi $(COMMON_FLAGS)
else
CFLAGS= -Od -Zi $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.obj)
# Library name and options needed to build it
LIBRARY=$(LIBNAME).dll
LDFLAGS=
# Libraries we are dependent on
LIBRARIES=
# Building a shared library
LINK_SHARED=link -dll -out:$@
endif
# Common -I options
CFLAGS += -I.
CFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME)
# Default rule (build both native library and jar file)
all: $(LIBRARY)
# Build native library
$(LIBRARY): $(OBJECTS)
$(LINK_SHARED) $(OBJECTS) $(LIBRARIES)
# Cleanup the built bits
clean:
rm -f -r classes
rm -f $(LIBRARY) $(OBJECTS)
# Compilation rule only needed on Windows
ifeq ($(OSNAME), win32)
%.obj: %.c
$(COMPILE.c) $<
endif

View File

@ -1,77 +0,0 @@
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* Java class to hold static methods which will be called in byte code
* injections of all class files.
*/
public class Minst {
/* Master switch that activates methods. */
private static int engaged = 0;
/* At the very beginning of every method, a call to method_entry()
* is injected.
*/
public static void method_entry(int cnum, int mnum) {
Class<Minst> x = Minst.class;
synchronized ( x ) {
if ( engaged > 0 ) {
engaged = 0;
String className = "Unknown";
String methodName = "Unknown";
Exception exp = new Exception();
StackTraceElement[] stack = exp.getStackTrace();
if (stack.length > 1) {
StackTraceElement location = stack[1];
className = location.getClassName();
methodName = location.getMethodName();
}
System.out.println("Reached method entry: " +
className + "." + methodName + "()");
engaged++;
}
}
}
}

View File

@ -1,49 +0,0 @@
#
# Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
minst
This agent library can be used to inject code at method calls.
It uses the same java_crw_demo library used by HPROF to do BCI on all
or selected classfiles loaded into the Virtual Machine.
The class Minst.java can be customized to do whatever you wish,
within reason of course, and does not call native methods directly.
You can use this agent library as follows:
java -agentlib:minst ...
To get help on the available options try:
java -agentlib:minst=help
See ${JAVA_HOME}/demo/jvmti/index.html for help running and building agents.

View File

@ -1,481 +0,0 @@
/*
* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#include "stdlib.h"
#include "minst.h"
#include "java_crw_demo.h"
/* ------------------------------------------------------------------- */
/* Some constant maximum sizes */
#define MAX_TOKEN_LENGTH 80
#define MAX_METHOD_NAME_LENGTH 256
/* Some constant names that tie to Java class/method names.
* We assume the Java class whose static methods we will be calling
* looks like:
*
* public class Minst {
* private static int engaged;
* private static native void _method_entry(Object thr, int cnum, int mnum);
* public static void method_entry(int cnum, int mnum)
* {
* ...
* }
* }
*
*/
#define MINST_class Minst /* Name of class we are using */
#define MINST_entry method_entry /* Name of java entry method */
#define MINST_engaged engaged /* Name of java static field */
/* C macros to create strings from tokens */
#define _STRING(s) #s
#define STRING(s) _STRING(s)
/* ------------------------------------------------------------------- */
/* Global agent data structure */
typedef struct {
/* JVMTI Environment */
jvmtiEnv *jvmti;
jboolean vm_is_dead;
jboolean vm_is_started;
/* Data access Lock */
jrawMonitorID lock;
/* Options */
char *include;
char *exclude;
/* Class Count/ID */
jint ccount;
} GlobalAgentData;
static GlobalAgentData *gdata;
/* Enter a critical section by doing a JVMTI Raw Monitor Enter */
static void
enter_critical_section(jvmtiEnv *jvmti)
{
jvmtiError error;
error = (*jvmti)->RawMonitorEnter(jvmti, gdata->lock);
check_jvmti_error(jvmti, error, "Cannot enter with raw monitor");
}
/* Exit a critical section by doing a JVMTI Raw Monitor Exit */
static void
exit_critical_section(jvmtiEnv *jvmti)
{
jvmtiError error;
error = (*jvmti)->RawMonitorExit(jvmti, gdata->lock);
check_jvmti_error(jvmti, error, "Cannot exit with raw monitor");
}
/* Callback for JVMTI_EVENT_VM_START */
static void JNICALL
cbVMStart(jvmtiEnv *jvmti, JNIEnv *env)
{
enter_critical_section(jvmti); {
/* Indicate VM has started */
gdata->vm_is_started = JNI_TRUE;
} exit_critical_section(jvmti);
}
/* Callback for JVMTI_EVENT_VM_INIT */
static void JNICALL
cbVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
enter_critical_section(jvmti); {
jclass klass;
jfieldID field;
/* Register Natives for class whose methods we use */
klass = (*env)->FindClass(env, STRING(MINST_class));
if ( klass == NULL ) {
fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
STRING(MINST_class));
}
/* Engage calls. */
field = (*env)->GetStaticFieldID(env, klass, STRING(MINST_engaged), "I");
if ( field == NULL ) {
fatal_error("ERROR: JNI: Cannot get field from %s\n",
STRING(MINST_class));
}
(*env)->SetStaticIntField(env, klass, field, 1);
} exit_critical_section(jvmti);
}
/* Callback for JVMTI_EVENT_VM_DEATH */
static void JNICALL
cbVMDeath(jvmtiEnv *jvmti, JNIEnv *env)
{
enter_critical_section(jvmti); {
jclass klass;
jfieldID field;
/* The VM has died. */
stdout_message("VMDeath\n");
/* Disengage calls in MINST_class. */
klass = (*env)->FindClass(env, STRING(MINST_class));
if ( klass == NULL ) {
fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
STRING(MINST_class));
}
field = (*env)->GetStaticFieldID(env, klass, STRING(MINST_engaged), "I");
if ( field == NULL ) {
fatal_error("ERROR: JNI: Cannot get field from %s\n",
STRING(MINST_class));
}
(*env)->SetStaticIntField(env, klass, field, -1);
/* The critical section here is important to hold back the VM death
* until all other callbacks have completed.
*/
/* Since this critical section could be holding up other threads
* in other event callbacks, we need to indicate that the VM is
* dead so that the other callbacks can short circuit their work.
* We don't expect any further events after VmDeath but we do need
* to be careful that existing threads might be in our own agent
* callback code.
*/
gdata->vm_is_dead = JNI_TRUE;
} exit_critical_section(jvmti);
}
/* Callback for JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */
static void JNICALL
cbClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv* env,
jclass class_being_redefined, jobject loader,
const char* name, jobject protection_domain,
jint class_data_len, const unsigned char* class_data,
jint* new_class_data_len, unsigned char** new_class_data)
{
enter_critical_section(jvmti); {
/* It's possible we get here right after VmDeath event, be careful */
if ( !gdata->vm_is_dead ) {
const char *classname;
/* Name could be NULL */
if ( name == NULL ) {
classname = java_crw_demo_classname(class_data, class_data_len,
NULL);
if ( classname == NULL ) {
fatal_error("ERROR: No classname inside classfile\n");
}
} else {
classname = strdup(name);
if ( classname == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
}
*new_class_data_len = 0;
*new_class_data = NULL;
/* The tracker class itself? */
if ( interested((char*)classname, "", gdata->include, gdata->exclude)
&& strcmp(classname, STRING(MINST_class)) != 0 ) {
jint cnum;
int system_class;
unsigned char *new_image;
long new_length;
/* Get unique number for every class file image loaded */
cnum = gdata->ccount++;
/* Is it a system class? If the class load is before VmStart
* then we will consider it a system class that should
* be treated carefully. (See java_crw_demo)
*/
system_class = 0;
if ( !gdata->vm_is_started ) {
system_class = 1;
}
new_image = NULL;
new_length = 0;
/* Call the class file reader/write demo code */
java_crw_demo(cnum,
classname,
class_data,
class_data_len,
system_class,
STRING(MINST_class), "L" STRING(MINST_class) ";",
STRING(MINST_entry), "(II)V",
NULL, NULL,
NULL, NULL,
NULL, NULL,
&new_image,
&new_length,
NULL,
NULL);
/* If we got back a new class image, return it back as "the"
* new class image. This must be JVMTI Allocate space.
*/
if ( new_length > 0 ) {
unsigned char *jvmti_space;
jvmti_space = (unsigned char *)allocate(jvmti, (jint)new_length);
(void)memcpy((void*)jvmti_space, (void*)new_image, (int)new_length);
*new_class_data_len = (jint)new_length;
*new_class_data = jvmti_space; /* VM will deallocate */
}
/* Always free up the space we get from java_crw_demo() */
if ( new_image != NULL ) {
(void)free((void*)new_image); /* Free malloc() space with free() */
}
}
(void)free((void*)classname);
}
} exit_critical_section(jvmti);
}
/* Parse the options for this minst agent */
static void
parse_agent_options(char *options)
{
char token[MAX_TOKEN_LENGTH];
char *next;
/* Parse options and set flags in gdata */
if ( options==NULL ) {
return;
}
/* Get the first token from the options string. */
next = get_token(options, ",=", token, sizeof(token));
/* While not at the end of the options string, process this option. */
while ( next != NULL ) {
if ( strcmp(token,"help")==0 ) {
stdout_message("The minst JVMTI demo agent\n");
stdout_message("\n");
stdout_message(" java -agent:minst[=options] ...\n");
stdout_message("\n");
stdout_message("The options are comma separated:\n");
stdout_message("\t help\t\t\t Print help information\n");
stdout_message("\t include=item\t\t Only these classes/methods\n");
stdout_message("\t exclude=item\t\t Exclude these classes/methods\n");
stdout_message("\n");
stdout_message("item\t Qualified class and/or method names\n");
stdout_message("\t\t e.g. (*.<init>;Foobar.method;sun.*)\n");
stdout_message("\n");
exit(0);
} else if ( strcmp(token,"include")==0 ) {
int used;
int maxlen;
maxlen = MAX_METHOD_NAME_LENGTH;
if ( gdata->include == NULL ) {
gdata->include = (char*)calloc(maxlen+1, 1);
used = 0;
} else {
used = (int)strlen(gdata->include);
gdata->include[used++] = ',';
gdata->include[used] = 0;
gdata->include = (char*)
realloc((void*)gdata->include, used+maxlen+1);
}
if ( gdata->include == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
/* Add this item to the list */
next = get_token(next, ",=", gdata->include+used, maxlen);
/* Check for token scan error */
if ( next==NULL ) {
fatal_error("ERROR: include option error\n");
}
} else if ( strcmp(token,"exclude")==0 ) {
int used;
int maxlen;
maxlen = MAX_METHOD_NAME_LENGTH;
if ( gdata->exclude == NULL ) {
gdata->exclude = (char*)calloc(maxlen+1, 1);
used = 0;
} else {
used = (int)strlen(gdata->exclude);
gdata->exclude[used++] = ',';
gdata->exclude[used] = 0;
gdata->exclude = (char*)
realloc((void*)gdata->exclude, used+maxlen+1);
}
if ( gdata->exclude == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
/* Add this item to the list */
next = get_token(next, ",=", gdata->exclude+used, maxlen);
/* Check for token scan error */
if ( next==NULL ) {
fatal_error("ERROR: exclude option error\n");
}
} else if ( token[0]!=0 ) {
/* We got a non-empty token and we don't know what it is. */
fatal_error("ERROR: Unknown option: %s\n", token);
}
/* Get the next token (returns NULL if there are no more) */
next = get_token(next, ",=", token, sizeof(token));
}
}
/* Agent_OnLoad: This is called immediately after the shared library is
* loaded. This is the first code executed.
*/
JNIEXPORT jint JNICALL
DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{
static GlobalAgentData data;
jvmtiEnv *jvmti;
jvmtiError error;
jint res;
jvmtiCapabilities capabilities;
jvmtiEventCallbacks callbacks;
/* Setup initial global agent data area
* Use of static/extern data should be handled carefully here.
* We need to make sure that we are able to cleanup after ourselves
* so anything allocated in this library needs to be freed in
* the Agent_OnUnload() function.
*/
(void)memset((void*)&data, 0, sizeof(data));
gdata = &data;
/* First thing we need to do is get the jvmtiEnv* or JVMTI environment */
res = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION_1);
if (res != JNI_OK) {
/* This means that the VM was unable to obtain this version of the
* JVMTI interface, this is a fatal error.
*/
fatal_error("ERROR: Unable to access JVMTI Version 1 (0x%x),"
" is your JDK a 5.0 or newer version?"
" JNIEnv's GetEnv() returned %d\n",
JVMTI_VERSION_1, res);
}
/* Here we save the jvmtiEnv* for Agent_OnUnload(). */
gdata->jvmti = jvmti;
/* Parse any options supplied on java command line */
parse_agent_options(options);
/* Immediately after getting the jvmtiEnv* we need to ask for the
* capabilities this agent will need. In this case we need to make
* sure that we can get all class load hooks.
*/
(void)memset(&capabilities,0, sizeof(capabilities));
capabilities.can_generate_all_class_hook_events = 1;
error = (*jvmti)->AddCapabilities(jvmti, &capabilities);
check_jvmti_error(jvmti, error, "Unable to get necessary JVMTI capabilities.");
/* Next we need to provide the pointers to the callback functions to
* to this jvmtiEnv*
*/
(void)memset(&callbacks,0, sizeof(callbacks));
/* JVMTI_EVENT_VM_START */
callbacks.VMStart = &cbVMStart;
/* JVMTI_EVENT_VM_INIT */
callbacks.VMInit = &cbVMInit;
/* JVMTI_EVENT_VM_DEATH */
callbacks.VMDeath = &cbVMDeath;
/* JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */
callbacks.ClassFileLoadHook = &cbClassFileLoadHook;
error = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, (jint)sizeof(callbacks));
check_jvmti_error(jvmti, error, "Cannot set jvmti callbacks");
/* At first the only initial events we are interested in are VM
* initialization, VM death, and Class File Loads.
* Once the VM is initialized we will request more events.
*/
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_VM_START, (jthread)NULL);
check_jvmti_error(jvmti, error, "Cannot set event notification");
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_VM_INIT, (jthread)NULL);
check_jvmti_error(jvmti, error, "Cannot set event notification");
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_VM_DEATH, (jthread)NULL);
check_jvmti_error(jvmti, error, "Cannot set event notification");
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, (jthread)NULL);
check_jvmti_error(jvmti, error, "Cannot set event notification");
/* Here we create a raw monitor for our use in this agent to
* protect critical sections of code.
*/
error = (*jvmti)->CreateRawMonitor(jvmti, "agent data", &(gdata->lock));
check_jvmti_error(jvmti, error, "Cannot create raw monitor");
/* Add demo jar file to boot classpath */
add_demo_jar_to_bootclasspath(jvmti, "minst");
/* We return JNI_OK to signify success */
return JNI_OK;
}
/* Agent_OnUnload: This is called immediately before the shared library is
* unloaded. This is the last code executed.
*/
JNIEXPORT void JNICALL
DEF_Agent_OnUnload(JavaVM *vm)
{
/* Make sure all malloc/calloc/strdup space is freed */
if ( gdata->include != NULL ) {
(void)free((void*)gdata->include);
gdata->include = NULL;
}
if ( gdata->exclude != NULL ) {
(void)free((void*)gdata->exclude);
gdata->exclude = NULL;
}
}

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2006, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* Primary minst #include file, should be included by most if not
* all minst source files. Gives access to the global data structure
* and all global macros.
*/
#ifndef MINST_H
#define MINST_H
/* Standard C functions used throughout. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdarg.h>
/* General JVM/Java functions, types and macros. */
#include <sys/types.h>
#include "jni.h"
#include "jvmti.h"
/* Utility functions */
#include "agent_util.h"
#endif

View File

@ -1,163 +0,0 @@
#
# Copyright (c) 2006, 2016, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
########################################################################
#
# Sample GNU Makefile for building JVMTI Demo minst
#
# Example uses:
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparc]
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparcv9]
# gnumake JDK=<java_home> OSNAME=linux [OPT=true]
# gnumake JDK=<java_home> OSNAME=win32 [OPT=true]
#
########################################################################
# Source lists
LIBNAME=minst
SOURCES=minst.c ../agent_util/agent_util.c
JAVA_SOURCES=Minst.java
# Name of jar file that needs to be created
JARFILE=minst.jar
# Solaris Studio C Compiler Version 12.4
ifeq ($(OSNAME), solaris)
# Sun Solaris Compiler options needed
COMMON_FLAGS=-mt -KPIC
# Options that help find errors
COMMON_FLAGS+= -Xa -v -xc99=%none
# Check LIBARCH for any special compiler options
LIBARCH=$(shell uname -p)
ifeq ($(LIBARCH), sparc)
COMMON_FLAGS+=-xarch=v8 -xregs=no%appl
endif
ifeq ($(LIBARCH), sparcv9)
COMMON_FLAGS+=-xarch=v9 -xregs=no%appl
endif
ifeq ($(OPT), true)
CFLAGS=-xO2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-z defs -ztext
# Libraries we are dependent on
LIBRARIES=-L $(JDK)/jre/lib/$(LIBARCH) -ljava_crw_demo -lc
# Building a shared library
LINK_SHARED=$(LINK.c) -G -o $@
endif
# Linux GNU C Compiler
ifeq ($(OSNAME), linux)
# GNU Compiler options needed to build it
COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer
# Options that help find errors
COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses
ifeq ($(OPT), true)
CFLAGS=-O2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc
# Libraries we are dependent on
LIBRARIES=-L $(JDK)/jre/lib/$(LIBARCH) -ljava_crw_demo -lc
# Building a shared library
LINK_SHARED=$(LINK.c) -shared -o $@
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OSNAME), win32)
CC=cl
# Compiler options needed to build it
COMMON_FLAGS=-Gy -DWIN32
# Options that help find errors
COMMON_FLAGS+=-W0 -WX
ifeq ($(OPT), true)
CFLAGS= -Ox -Op -Zi $(COMMON_FLAGS)
else
CFLAGS= -Od -Zi $(COMMON_FLAGS)
endif
# Add in java_crw_demo obj file on windows (easier)
SOURCES+=../java_crw_demo/java_crw_demo.c
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.obj)
# Library name and options needed to build it
LIBRARY=$(LIBNAME).dll
LDFLAGS=
# Libraries we are dependent on
LIBRARIES=$(JDK)/
# Building a shared library
LINK_SHARED=link -dll -out:$@
endif
# Common -I options
CFLAGS += -I.
CFLAGS += -I../agent_util
CFLAGS += -I../java_crw_demo
CFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME)
# Default rule (build both native library and jar file)
all: $(LIBRARY) $(JARFILE)
# Build native library
$(LIBRARY): $(OBJECTS)
$(LINK_SHARED) $(OBJECTS) $(LIBRARIES)
# Build jar file
$(JARFILE): $(JAVA_SOURCES)
rm -f -r classes
mkdir -p classes
$(JDK)/bin/javac -d classes $(JAVA_SOURCES)
(cd classes; $(JDK)/bin/jar cf ../$@ *)
# Cleanup the built bits
clean:
rm -f -r classes
rm -f $(LIBRARY) $(JARFILE) $(OBJECTS)
# Simple tester
test: all
LD_LIBRARY_PATH=. $(JDK)/bin/java -agentlib:$(LIBNAME) -Xbootclasspath/a:./$(JARFILE) -version
# Compilation rule only needed on Windows
ifeq ($(OSNAME), win32)
%.obj: %.c
$(COMPILE.c) $<
endif

View File

@ -1,76 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* Java class to hold static methods which will be called in byte code
* injections of all class files.
*/
public class Mtrace {
/* Master switch that activates methods. */
private static int engaged = 0;
/* At the very beginning of every method, a call to method_entry()
* is injected.
*/
private static native void _method_entry(Object thr, int cnum, int mnum);
public static void method_entry(int cnum, int mnum)
{
if ( engaged != 0 ) {
_method_entry(Thread.currentThread(), cnum, mnum);
}
}
/* Before any of the return bytecodes, a call to method_exit()
* is injected.
*/
private static native void _method_exit(Object thr, int cnum, int mnum);
public static void method_exit(int cnum, int mnum)
{
if ( engaged != 0 ) {
_method_exit(Thread.currentThread(), cnum, mnum);
}
}
}

View File

@ -1,50 +0,0 @@
#
# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
mtrace
This agent library can be used to track method call and return counts.
It uses the same java_crw_demo library used by HPROF to do BCI on all or
selected classfiles loaded into the Virtual Machine. It will print out a
sorted list of the most heavily used classes (as determined by the number
of method calls into the class) and also include the call and return counts
for all methods that are called.
You can use this agent library as follows:
java -Xbootclasspath/a:mtrace.jar -agentlib:mtrace ...
To get help on the available options try:
java -agentlib:mtrace=help
See ${JAVA_HOME}/demo/jvmti/index.html for help running and building agents.

View File

@ -1,833 +0,0 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#include "stdlib.h"
#include "mtrace.h"
#include "java_crw_demo.h"
/* ------------------------------------------------------------------- */
/* Some constant maximum sizes */
#define MAX_TOKEN_LENGTH 16
#define MAX_THREAD_NAME_LENGTH 512
#define MAX_METHOD_NAME_LENGTH 1024
/* Some constant names that tie to Java class/method names.
* We assume the Java class whose static methods we will be calling
* looks like:
*
* public class Mtrace {
* private static int engaged;
* private static native void _method_entry(Object thr, int cnum, int mnum);
* public static void method_entry(int cnum, int mnum)
* {
* if ( engaged != 0 ) {
* _method_entry(Thread.currentThread(), cnum, mnum);
* }
* }
* private static native void _method_exit(Object thr, int cnum, int mnum);
* public static void method_exit(int cnum, int mnum)
* {
* if ( engaged != 0 ) {
* _method_exit(Thread.currentThread(), cnum, mnum);
* }
* }
* }
*
* The engaged field allows us to inject all classes (even system classes)
* and delay the actual calls to the native code until the VM has reached
* a safe time to call native methods (Past the JVMTI VM_START event).
*
*/
#define MTRACE_class Mtrace /* Name of class we are using */
#define MTRACE_entry method_entry /* Name of java entry method */
#define MTRACE_exit method_exit /* Name of java exit method */
#define MTRACE_native_entry _method_entry /* Name of java entry native */
#define MTRACE_native_exit _method_exit /* Name of java exit native */
#define MTRACE_engaged engaged /* Name of java static field */
/* C macros to create strings from tokens */
#define _STRING(s) #s
#define STRING(s) _STRING(s)
/* ------------------------------------------------------------------- */
/* Data structure to hold method and class information in agent */
typedef struct MethodInfo {
const char *name; /* Method name */
const char *signature; /* Method signature */
int calls; /* Method call count */
int returns; /* Method return count */
} MethodInfo;
typedef struct ClassInfo {
const char *name; /* Class name */
int mcount; /* Method count */
MethodInfo *methods; /* Method information */
int calls; /* Method call count for this class */
} ClassInfo;
/* Global agent data structure */
typedef struct {
/* JVMTI Environment */
jvmtiEnv *jvmti;
jboolean vm_is_dead;
jboolean vm_is_started;
/* Data access Lock */
jrawMonitorID lock;
/* Options */
char *include;
char *exclude;
int max_count;
/* ClassInfo Table */
ClassInfo *classes;
jint ccount;
} GlobalAgentData;
static GlobalAgentData *gdata;
/* Enter a critical section by doing a JVMTI Raw Monitor Enter */
static void
enter_critical_section(jvmtiEnv *jvmti)
{
jvmtiError error;
error = (*jvmti)->RawMonitorEnter(jvmti, gdata->lock);
check_jvmti_error(jvmti, error, "Cannot enter with raw monitor");
}
/* Exit a critical section by doing a JVMTI Raw Monitor Exit */
static void
exit_critical_section(jvmtiEnv *jvmti)
{
jvmtiError error;
error = (*jvmti)->RawMonitorExit(jvmti, gdata->lock);
check_jvmti_error(jvmti, error, "Cannot exit with raw monitor");
}
/* Get a name for a jthread */
static void
get_thread_name(jvmtiEnv *jvmti, jthread thread, char *tname, int maxlen)
{
jvmtiThreadInfo info;
jvmtiError error;
/* Make sure the stack variables are garbage free */
(void)memset(&info,0, sizeof(info));
/* Assume the name is unknown for now */
(void)strcpy(tname, "Unknown");
/* Get the thread information, which includes the name */
error = (*jvmti)->GetThreadInfo(jvmti, thread, &info);
check_jvmti_error(jvmti, error, "Cannot get thread info");
/* The thread might not have a name, be careful here. */
if ( info.name != NULL ) {
int len;
/* Copy the thread name into tname if it will fit */
len = (int)strlen(info.name);
if ( len < maxlen ) {
(void)strcpy(tname, info.name);
}
/* Every string allocated by JVMTI needs to be freed */
deallocate(jvmti, (void*)info.name);
}
}
/* Qsort class compare routine */
static int
class_compar(const void *e1, const void *e2)
{
ClassInfo *c1 = (ClassInfo*)e1;
ClassInfo *c2 = (ClassInfo*)e2;
if ( c1->calls > c2->calls ) return 1;
if ( c1->calls < c2->calls ) return -1;
return 0;
}
/* Qsort method compare routine */
static int
method_compar(const void *e1, const void *e2)
{
MethodInfo *m1 = (MethodInfo*)e1;
MethodInfo *m2 = (MethodInfo*)e2;
if ( m1->calls > m2->calls ) return 1;
if ( m1->calls < m2->calls ) return -1;
return 0;
}
/* Callback from java_crw_demo() that gives us mnum mappings */
static void
mnum_callbacks(unsigned cnum, const char **names, const char**sigs, int mcount)
{
ClassInfo *cp;
int mnum;
if ( cnum >= (unsigned)gdata->ccount ) {
fatal_error("ERROR: Class number out of range\n");
}
if ( mcount == 0 ) {
return;
}
cp = gdata->classes + (int)cnum;
cp->calls = 0;
cp->mcount = mcount;
cp->methods = (MethodInfo*)calloc(mcount, sizeof(MethodInfo));
if ( cp->methods == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
for ( mnum = 0 ; mnum < mcount ; mnum++ ) {
MethodInfo *mp;
mp = cp->methods + mnum;
mp->name = (const char *)strdup(names[mnum]);
if ( mp->name == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
mp->signature = (const char *)strdup(sigs[mnum]);
if ( mp->signature == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
}
}
/* Java Native Method for entry */
static void
MTRACE_native_entry(JNIEnv *env, jclass klass, jobject thread, jint cnum, jint mnum)
{
enter_critical_section(gdata->jvmti); {
/* It's possible we get here right after VmDeath event, be careful */
if ( !gdata->vm_is_dead ) {
ClassInfo *cp;
MethodInfo *mp;
if ( cnum >= gdata->ccount ) {
fatal_error("ERROR: Class number out of range\n");
}
cp = gdata->classes + cnum;
if ( mnum >= cp->mcount ) {
fatal_error("ERROR: Method number out of range\n");
}
mp = cp->methods + mnum;
if ( interested((char*)cp->name, (char*)mp->name,
gdata->include, gdata->exclude) ) {
mp->calls++;
cp->calls++;
}
}
} exit_critical_section(gdata->jvmti);
}
/* Java Native Method for exit */
static void
MTRACE_native_exit(JNIEnv *env, jclass klass, jobject thread, jint cnum, jint mnum)
{
enter_critical_section(gdata->jvmti); {
/* It's possible we get here right after VmDeath event, be careful */
if ( !gdata->vm_is_dead ) {
ClassInfo *cp;
MethodInfo *mp;
if ( cnum >= gdata->ccount ) {
fatal_error("ERROR: Class number out of range\n");
}
cp = gdata->classes + cnum;
if ( mnum >= cp->mcount ) {
fatal_error("ERROR: Method number out of range\n");
}
mp = cp->methods + mnum;
if ( interested((char*)cp->name, (char*)mp->name,
gdata->include, gdata->exclude) ) {
mp->returns++;
}
}
} exit_critical_section(gdata->jvmti);
}
/* Callback for JVMTI_EVENT_VM_START */
static void JNICALL
cbVMStart(jvmtiEnv *jvmti, JNIEnv *env)
{
enter_critical_section(jvmti); {
jclass klass;
jfieldID field;
int rc;
/* Java Native Methods for class */
static JNINativeMethod registry[2] = {
{STRING(MTRACE_native_entry), "(Ljava/lang/Object;II)V",
(void*)&MTRACE_native_entry},
{STRING(MTRACE_native_exit), "(Ljava/lang/Object;II)V",
(void*)&MTRACE_native_exit}
};
/* The VM has started. */
stdout_message("VMStart\n");
/* Register Natives for class whose methods we use */
klass = (*env)->FindClass(env, STRING(MTRACE_class));
if ( klass == NULL ) {
fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
STRING(MTRACE_class));
}
rc = (*env)->RegisterNatives(env, klass, registry, 2);
if ( rc != 0 ) {
fatal_error("ERROR: JNI: Cannot register native methods for %s\n",
STRING(MTRACE_class));
}
/* Engage calls. */
field = (*env)->GetStaticFieldID(env, klass, STRING(MTRACE_engaged), "I");
if ( field == NULL ) {
fatal_error("ERROR: JNI: Cannot get field from %s\n",
STRING(MTRACE_class));
}
(*env)->SetStaticIntField(env, klass, field, 1);
/* Indicate VM has started */
gdata->vm_is_started = JNI_TRUE;
} exit_critical_section(jvmti);
}
/* Callback for JVMTI_EVENT_VM_INIT */
static void JNICALL
cbVMInit(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
enter_critical_section(jvmti); {
char tname[MAX_THREAD_NAME_LENGTH];
static jvmtiEvent events[] =
{ JVMTI_EVENT_THREAD_START, JVMTI_EVENT_THREAD_END };
int i;
/* The VM has started. */
get_thread_name(jvmti, thread, tname, sizeof(tname));
stdout_message("VMInit %s\n", tname);
/* The VM is now initialized, at this time we make our requests
* for additional events.
*/
for( i=0; i < (int)(sizeof(events)/sizeof(jvmtiEvent)); i++) {
jvmtiError error;
/* Setup event notification modes */
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
events[i], (jthread)NULL);
check_jvmti_error(jvmti, error, "Cannot set event notification");
}
} exit_critical_section(jvmti);
}
/* Callback for JVMTI_EVENT_VM_DEATH */
static void JNICALL
cbVMDeath(jvmtiEnv *jvmti, JNIEnv *env)
{
enter_critical_section(jvmti); {
jclass klass;
jfieldID field;
/* The VM has died. */
stdout_message("VMDeath\n");
/* Disengage calls in MTRACE_class. */
klass = (*env)->FindClass(env, STRING(MTRACE_class));
if ( klass == NULL ) {
fatal_error("ERROR: JNI: Cannot find %s with FindClass\n",
STRING(MTRACE_class));
}
field = (*env)->GetStaticFieldID(env, klass, STRING(MTRACE_engaged), "I");
if ( field == NULL ) {
fatal_error("ERROR: JNI: Cannot get field from %s\n",
STRING(MTRACE_class));
}
(*env)->SetStaticIntField(env, klass, field, 0);
/* The critical section here is important to hold back the VM death
* until all other callbacks have completed.
*/
/* Since this critical section could be holding up other threads
* in other event callbacks, we need to indicate that the VM is
* dead so that the other callbacks can short circuit their work.
* We don't expect any further events after VmDeath but we do need
* to be careful that existing threads might be in our own agent
* callback code.
*/
gdata->vm_is_dead = JNI_TRUE;
/* Dump out stats */
stdout_message("Begin Class Stats\n");
if ( gdata->ccount > 0 ) {
int cnum;
/* Sort table (in place) by number of method calls into class. */
/* Note: Do not use this table after this qsort! */
qsort(gdata->classes, gdata->ccount, sizeof(ClassInfo),
&class_compar);
/* Dump out gdata->max_count most called classes */
for ( cnum=gdata->ccount-1 ;
cnum >= 0 && cnum >= gdata->ccount - gdata->max_count;
cnum-- ) {
ClassInfo *cp;
int mnum;
cp = gdata->classes + cnum;
stdout_message("Class %s %d calls\n", cp->name, cp->calls);
if ( cp->calls==0 ) continue;
/* Sort method table (in place) by number of method calls. */
/* Note: Do not use this table after this qsort! */
qsort(cp->methods, cp->mcount, sizeof(MethodInfo),
&method_compar);
for ( mnum=cp->mcount-1 ; mnum >= 0 ; mnum-- ) {
MethodInfo *mp;
mp = cp->methods + mnum;
if ( mp->calls==0 ) continue;
stdout_message("\tMethod %s %s %d calls %d returns\n",
mp->name, mp->signature, mp->calls, mp->returns);
}
}
}
stdout_message("End Class Stats\n");
(void)fflush(stdout);
} exit_critical_section(jvmti);
}
/* Callback for JVMTI_EVENT_THREAD_START */
static void JNICALL
cbThreadStart(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
enter_critical_section(jvmti); {
/* It's possible we get here right after VmDeath event, be careful */
if ( !gdata->vm_is_dead ) {
char tname[MAX_THREAD_NAME_LENGTH];
get_thread_name(jvmti, thread, tname, sizeof(tname));
stdout_message("ThreadStart %s\n", tname);
}
} exit_critical_section(jvmti);
}
/* Callback for JVMTI_EVENT_THREAD_END */
static void JNICALL
cbThreadEnd(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
enter_critical_section(jvmti); {
/* It's possible we get here right after VmDeath event, be careful */
if ( !gdata->vm_is_dead ) {
char tname[MAX_THREAD_NAME_LENGTH];
get_thread_name(jvmti, thread, tname, sizeof(tname));
stdout_message("ThreadEnd %s\n", tname);
}
} exit_critical_section(jvmti);
}
/* Callback for JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */
static void JNICALL
cbClassFileLoadHook(jvmtiEnv *jvmti, JNIEnv* env,
jclass class_being_redefined, jobject loader,
const char* name, jobject protection_domain,
jint class_data_len, const unsigned char* class_data,
jint* new_class_data_len, unsigned char** new_class_data)
{
enter_critical_section(jvmti); {
/* It's possible we get here right after VmDeath event, be careful */
if ( !gdata->vm_is_dead ) {
const char *classname;
/* Name could be NULL */
if ( name == NULL ) {
classname = java_crw_demo_classname(class_data, class_data_len,
NULL);
if ( classname == NULL ) {
fatal_error("ERROR: No classname inside classfile\n");
}
} else {
classname = strdup(name);
if ( classname == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
}
*new_class_data_len = 0;
*new_class_data = NULL;
/* The tracker class itself? */
if ( interested((char*)classname, "", gdata->include, gdata->exclude)
&& strcmp(classname, STRING(MTRACE_class)) != 0 ) {
jint cnum;
int system_class;
unsigned char *new_image;
long new_length;
ClassInfo *cp;
/* Get unique number for every class file image loaded */
cnum = gdata->ccount++;
/* Save away class information */
if ( gdata->classes == NULL ) {
gdata->classes = (ClassInfo*)malloc(
gdata->ccount*sizeof(ClassInfo));
} else {
gdata->classes = (ClassInfo*)
realloc((void*)gdata->classes,
gdata->ccount*sizeof(ClassInfo));
}
if ( gdata->classes == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
cp = gdata->classes + cnum;
cp->name = (const char *)strdup(classname);
if ( cp->name == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
cp->calls = 0;
cp->mcount = 0;
cp->methods = NULL;
/* Is it a system class? If the class load is before VmStart
* then we will consider it a system class that should
* be treated carefully. (See java_crw_demo)
*/
system_class = 0;
if ( !gdata->vm_is_started ) {
system_class = 1;
}
new_image = NULL;
new_length = 0;
/* Call the class file reader/write demo code */
java_crw_demo(cnum,
classname,
class_data,
class_data_len,
system_class,
STRING(MTRACE_class), "L" STRING(MTRACE_class) ";",
STRING(MTRACE_entry), "(II)V",
STRING(MTRACE_exit), "(II)V",
NULL, NULL,
NULL, NULL,
&new_image,
&new_length,
NULL,
&mnum_callbacks);
/* If we got back a new class image, return it back as "the"
* new class image. This must be JVMTI Allocate space.
*/
if ( new_length > 0 ) {
unsigned char *jvmti_space;
jvmti_space = (unsigned char *)allocate(jvmti, (jint)new_length);
(void)memcpy((void*)jvmti_space, (void*)new_image, (int)new_length);
*new_class_data_len = (jint)new_length;
*new_class_data = jvmti_space; /* VM will deallocate */
}
/* Always free up the space we get from java_crw_demo() */
if ( new_image != NULL ) {
(void)free((void*)new_image); /* Free malloc() space with free() */
}
}
(void)free((void*)classname);
}
} exit_critical_section(jvmti);
}
/* Parse the options for this mtrace agent */
static void
parse_agent_options(char *options)
{
char token[MAX_TOKEN_LENGTH];
char *next;
gdata->max_count = 10; /* Default max=n */
/* Parse options and set flags in gdata */
if ( options==NULL ) {
return;
}
/* Get the first token from the options string. */
next = get_token(options, ",=", token, sizeof(token));
/* While not at the end of the options string, process this option. */
while ( next != NULL ) {
if ( strcmp(token,"help")==0 ) {
stdout_message("The mtrace JVMTI demo agent\n");
stdout_message("\n");
stdout_message(" java -agent:mtrace[=options] ...\n");
stdout_message("\n");
stdout_message("The options are comma separated:\n");
stdout_message("\t help\t\t\t Print help information\n");
stdout_message("\t max=n\t\t Only list top n classes\n");
stdout_message("\t include=item\t\t Only these classes/methods\n");
stdout_message("\t exclude=item\t\t Exclude these classes/methods\n");
stdout_message("\n");
stdout_message("item\t Qualified class and/or method names\n");
stdout_message("\t\t e.g. (*.<init>;Foobar.method;sun.*)\n");
stdout_message("\n");
exit(0);
} else if ( strcmp(token,"max")==0 ) {
char number[MAX_TOKEN_LENGTH];
/* Get the numeric option */
next = get_token(next, ",=", number, (int)sizeof(number));
/* Check for token scan error */
if ( next==NULL ) {
fatal_error("ERROR: max=n option error\n");
}
/* Save numeric value */
gdata->max_count = atoi(number);
} else if ( strcmp(token,"include")==0 ) {
int used;
int maxlen;
maxlen = MAX_METHOD_NAME_LENGTH;
if ( gdata->include == NULL ) {
gdata->include = (char*)calloc(maxlen+1, 1);
used = 0;
} else {
used = (int)strlen(gdata->include);
gdata->include[used++] = ',';
gdata->include[used] = 0;
gdata->include = (char*)
realloc((void*)gdata->include, used+maxlen+1);
}
if ( gdata->include == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
/* Add this item to the list */
next = get_token(next, ",=", gdata->include+used, maxlen);
/* Check for token scan error */
if ( next==NULL ) {
fatal_error("ERROR: include option error\n");
}
} else if ( strcmp(token,"exclude")==0 ) {
int used;
int maxlen;
maxlen = MAX_METHOD_NAME_LENGTH;
if ( gdata->exclude == NULL ) {
gdata->exclude = (char*)calloc(maxlen+1, 1);
used = 0;
} else {
used = (int)strlen(gdata->exclude);
gdata->exclude[used++] = ',';
gdata->exclude[used] = 0;
gdata->exclude = (char*)
realloc((void*)gdata->exclude, used+maxlen+1);
}
if ( gdata->exclude == NULL ) {
fatal_error("ERROR: Out of malloc memory\n");
}
/* Add this item to the list */
next = get_token(next, ",=", gdata->exclude+used, maxlen);
/* Check for token scan error */
if ( next==NULL ) {
fatal_error("ERROR: exclude option error\n");
}
} else if ( token[0]!=0 ) {
/* We got a non-empty token and we don't know what it is. */
fatal_error("ERROR: Unknown option: %s\n", token);
}
/* Get the next token (returns NULL if there are no more) */
next = get_token(next, ",=", token, sizeof(token));
}
}
/* Agent_OnLoad: This is called immediately after the shared library is
* loaded. This is the first code executed.
*/
JNIEXPORT jint JNICALL
DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{
static GlobalAgentData data;
jvmtiEnv *jvmti;
jvmtiError error;
jint res;
jvmtiCapabilities capabilities;
jvmtiEventCallbacks callbacks;
/* Setup initial global agent data area
* Use of static/extern data should be handled carefully here.
* We need to make sure that we are able to cleanup after ourselves
* so anything allocated in this library needs to be freed in
* the Agent_OnUnload() function.
*/
(void)memset((void*)&data, 0, sizeof(data));
gdata = &data;
/* First thing we need to do is get the jvmtiEnv* or JVMTI environment */
res = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION_1);
if (res != JNI_OK) {
/* This means that the VM was unable to obtain this version of the
* JVMTI interface, this is a fatal error.
*/
fatal_error("ERROR: Unable to access JVMTI Version 1 (0x%x),"
" is your JDK a 5.0 or newer version?"
" JNIEnv's GetEnv() returned %d\n",
JVMTI_VERSION_1, res);
}
/* Here we save the jvmtiEnv* for Agent_OnUnload(). */
gdata->jvmti = jvmti;
/* Parse any options supplied on java command line */
parse_agent_options(options);
/* Immediately after getting the jvmtiEnv* we need to ask for the
* capabilities this agent will need. In this case we need to make
* sure that we can get all class load hooks.
*/
(void)memset(&capabilities,0, sizeof(capabilities));
capabilities.can_generate_all_class_hook_events = 1;
error = (*jvmti)->AddCapabilities(jvmti, &capabilities);
check_jvmti_error(jvmti, error, "Unable to get necessary JVMTI capabilities.");
/* Next we need to provide the pointers to the callback functions to
* to this jvmtiEnv*
*/
(void)memset(&callbacks,0, sizeof(callbacks));
/* JVMTI_EVENT_VM_START */
callbacks.VMStart = &cbVMStart;
/* JVMTI_EVENT_VM_INIT */
callbacks.VMInit = &cbVMInit;
/* JVMTI_EVENT_VM_DEATH */
callbacks.VMDeath = &cbVMDeath;
/* JVMTI_EVENT_CLASS_FILE_LOAD_HOOK */
callbacks.ClassFileLoadHook = &cbClassFileLoadHook;
/* JVMTI_EVENT_THREAD_START */
callbacks.ThreadStart = &cbThreadStart;
/* JVMTI_EVENT_THREAD_END */
callbacks.ThreadEnd = &cbThreadEnd;
error = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, (jint)sizeof(callbacks));
check_jvmti_error(jvmti, error, "Cannot set jvmti callbacks");
/* At first the only initial events we are interested in are VM
* initialization, VM death, and Class File Loads.
* Once the VM is initialized we will request more events.
*/
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_VM_START, (jthread)NULL);
check_jvmti_error(jvmti, error, "Cannot set event notification");
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_VM_INIT, (jthread)NULL);
check_jvmti_error(jvmti, error, "Cannot set event notification");
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_VM_DEATH, (jthread)NULL);
check_jvmti_error(jvmti, error, "Cannot set event notification");
error = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, (jthread)NULL);
check_jvmti_error(jvmti, error, "Cannot set event notification");
/* Here we create a raw monitor for our use in this agent to
* protect critical sections of code.
*/
error = (*jvmti)->CreateRawMonitor(jvmti, "agent data", &(gdata->lock));
check_jvmti_error(jvmti, error, "Cannot create raw monitor");
/* Add demo jar file to boot classpath */
add_demo_jar_to_bootclasspath(jvmti, "mtrace");
/* We return JNI_OK to signify success */
return JNI_OK;
}
/* Agent_OnUnload: This is called immediately before the shared library is
* unloaded. This is the last code executed.
*/
JNIEXPORT void JNICALL
DEF_Agent_OnUnload(JavaVM *vm)
{
/* Make sure all malloc/calloc/strdup space is freed */
if ( gdata->include != NULL ) {
(void)free((void*)gdata->include);
gdata->include = NULL;
}
if ( gdata->exclude != NULL ) {
(void)free((void*)gdata->exclude);
gdata->exclude = NULL;
}
if ( gdata->classes != NULL ) {
int cnum;
for ( cnum = 0 ; cnum < gdata->ccount ; cnum++ ) {
ClassInfo *cp;
cp = gdata->classes + cnum;
(void)free((void*)cp->name);
if ( cp->mcount > 0 ) {
int mnum;
for ( mnum = 0 ; mnum < cp->mcount ; mnum++ ) {
MethodInfo *mp;
mp = cp->methods + mnum;
(void)free((void*)mp->name);
(void)free((void*)mp->signature);
}
(void)free((void*)cp->methods);
}
}
(void)free((void*)gdata->classes);
gdata->classes = NULL;
}
}

View File

@ -1,67 +0,0 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* Primary mtrace #include file, should be included by most if not
* all mtrace source files. Gives access to the global data structure
* and all global macros.
*/
#ifndef MTRACE_H
#define MTRACE_H
/* Standard C functions used throughout. */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include <stdarg.h>
/* General JVM/Java functions, types and macros. */
#include <sys/types.h>
#include "jni.h"
#include "jvmti.h"
/* Utility functions */
#include "agent_util.h"
#endif

View File

@ -1,163 +0,0 @@
#
# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
########################################################################
#
# Sample GNU Makefile for building JVMTI Demo mtrace
#
# Example uses:
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparc]
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparcv9]
# gnumake JDK=<java_home> OSNAME=linux [OPT=true]
# gnumake JDK=<java_home> OSNAME=win32 [OPT=true]
#
########################################################################
# Source lists
LIBNAME=mtrace
SOURCES=mtrace.c ../agent_util/agent_util.c
JAVA_SOURCES=Mtrace.java
# Name of jar file that needs to be created
JARFILE=mtrace.jar
# Solaris Studio C Compiler Version 12.4
ifeq ($(OSNAME), solaris)
# Sun Solaris Compiler options needed
COMMON_FLAGS=-mt -KPIC
# Options that help find errors
COMMON_FLAGS+= -Xa -v -xc99=%none
# Check LIBARCH for any special compiler options
LIBARCH=$(shell uname -p)
ifeq ($(LIBARCH), sparc)
COMMON_FLAGS+=-xarch=v8 -xregs=no%appl
endif
ifeq ($(LIBARCH), sparcv9)
COMMON_FLAGS+=-xarch=v9 -xregs=no%appl
endif
ifeq ($(OPT), true)
CFLAGS=-xO2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-z defs -ztext
# Libraries we are dependent on
LIBRARIES=-L $(JDK)/jre/lib/$(LIBARCH) -ljava_crw_demo -lc
# Building a shared library
LINK_SHARED=$(LINK.c) -G -o $@
endif
# Linux GNU C Compiler
ifeq ($(OSNAME), linux)
# GNU Compiler options needed to build it
COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer
# Options that help find errors
COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses
ifeq ($(OPT), true)
CFLAGS=-O2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc
# Libraries we are dependent on
LIBRARIES=-L $(JDK)/jre/lib/$(LIBARCH) -ljava_crw_demo -lc
# Building a shared library
LINK_SHARED=$(LINK.c) -shared -o $@
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OSNAME), win32)
CC=cl
# Compiler options needed to build it
COMMON_FLAGS=-Gy -DWIN32
# Options that help find errors
COMMON_FLAGS+=-W0 -WX
ifeq ($(OPT), true)
CFLAGS= -Ox -Op -Zi $(COMMON_FLAGS)
else
CFLAGS= -Od -Zi $(COMMON_FLAGS)
endif
# Add in java_crw_demo obj file on windows (easier)
SOURCES+=../java_crw_demo/java_crw_demo.c
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.obj)
# Library name and options needed to build it
LIBRARY=$(LIBNAME).dll
LDFLAGS=
# Libraries we are dependent on
LIBRARIES=$(JDK)/
# Building a shared library
LINK_SHARED=link -dll -out:$@
endif
# Common -I options
CFLAGS += -I.
CFLAGS += -I../agent_util
CFLAGS += -I../java_crw_demo
CFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME)
# Default rule (build both native library and jar file)
all: $(LIBRARY) $(JARFILE)
# Build native library
$(LIBRARY): $(OBJECTS)
$(LINK_SHARED) $(OBJECTS) $(LIBRARIES)
# Build jar file
$(JARFILE): $(JAVA_SOURCES)
rm -f -r classes
mkdir -p classes
$(JDK)/bin/javac -d classes $(JAVA_SOURCES)
(cd classes; $(JDK)/bin/jar cf ../$@ *)
# Cleanup the built bits
clean:
rm -f -r classes
rm -f $(LIBRARY) $(JARFILE) $(OBJECTS)
# Simple tester
test: all
LD_LIBRARY_PATH=. $(JDK)/bin/java -agentlib:$(LIBNAME) -Xbootclasspath/a:./$(JARFILE) -version
# Compilation rule only needed on Windows
ifeq ($(OSNAME), win32)
%.obj: %.c
$(COMPILE.c) $<
endif

View File

@ -1,43 +0,0 @@
#
# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
versionCheck
This agent library just makes some simple calls and checks
the version of the interface being used to build the agent,
with that supplied by the VM at runtime.
You can use this agent library as follows:
java -agentlib:versionCheck ...
See ${JAVA_HOME}/demo/jvmti/index.html for help running and building agents.

View File

@ -1,148 +0,0 @@
#
# Copyright (c) 2004, 2016, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
########################################################################
#
# Sample GNU Makefile for building JVMTI Demo versionCheck
#
# Example uses:
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparc]
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparcv9]
# gnumake JDK=<java_home> OSNAME=linux [OPT=true]
# gnumake JDK=<java_home> OSNAME=win32 [OPT=true]
#
########################################################################
# Source lists
LIBNAME=versionCheck
SOURCES=versionCheck.c ../agent_util/agent_util.c
# Solaris Studio C Compiler Version 12.4
ifeq ($(OSNAME), solaris)
# Sun Solaris Compiler options needed
COMMON_FLAGS=-mt -KPIC
# Options that help find errors
COMMON_FLAGS+= -Xa -v -xc99=%none
# Check LIBARCH for any special compiler options
LIBARCH=$(shell uname -p)
ifeq ($(LIBARCH), sparc)
COMMON_FLAGS+=-xarch=v8 -xregs=no%appl
endif
ifeq ($(LIBARCH), sparcv9)
COMMON_FLAGS+=-xarch=v9 -xregs=no%appl
endif
ifeq ($(OPT), true)
CFLAGS=-xO2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-z defs -ztext
# Libraries we are dependent on
LIBRARIES= -lc
# Building a shared library
LINK_SHARED=$(LINK.c) -G -o $@
endif
# Linux GNU C Compiler
ifeq ($(OSNAME), linux)
# GNU Compiler options needed to build it
COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer
# Options that help find errors
COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses
ifeq ($(OPT), true)
CFLAGS=-O2 $(COMMON_FLAGS)
else
CFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc
# Libraries we are dependent on
LIBRARIES=-lc
# Building a shared library
LINK_SHARED=$(LINK.c) -shared -o $@
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OSNAME), win32)
CC=cl
# Compiler options needed to build it
COMMON_FLAGS=-Gy -DWIN32
# Options that help find errors
COMMON_FLAGS+=-W0 -WX
ifeq ($(OPT), true)
CFLAGS= -Ox -Op -Zi $(COMMON_FLAGS)
else
CFLAGS= -Od -Zi $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.c=%.obj)
# Library name and options needed to build it
LIBRARY=$(LIBNAME).dll
LDFLAGS=
# Libraries we are dependent on
LIBRARIES=
# Building a shared library
LINK_SHARED=link -dll -out:$@
endif
# Common -I options
CFLAGS += -I.
CFLAGS += -I../agent_util
CFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME)
# Default rule
all: $(LIBRARY)
# Build native library
$(LIBRARY): $(OBJECTS)
$(LINK_SHARED) $(OBJECTS) $(LIBRARIES)
# Cleanup the built bits
clean:
rm -f $(LIBRARY) $(OBJECTS)
# Simple tester
test: all
LD_LIBRARY_PATH=`pwd` $(JDK)/bin/java -agentlib:$(LIBNAME) -version
# Compilation rule only needed on Windows
ifeq ($(OSNAME), win32)
%.obj: %.c
$(COMPILE.c) $<
endif

View File

@ -1,121 +0,0 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jni.h"
#include "jvmti.h"
#include "agent_util.h"
/* Create major.minor.micro version string */
static void
version_check(jint cver, jint rver)
{
jint cmajor, cminor, cmicro;
jint rmajor, rminor, rmicro;
cmajor = (cver & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR;
cminor = (cver & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR;
cmicro = (cver & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO;
rmajor = (rver & JVMTI_VERSION_MASK_MAJOR) >> JVMTI_VERSION_SHIFT_MAJOR;
rminor = (rver & JVMTI_VERSION_MASK_MINOR) >> JVMTI_VERSION_SHIFT_MINOR;
rmicro = (rver & JVMTI_VERSION_MASK_MICRO) >> JVMTI_VERSION_SHIFT_MICRO;
stdout_message("Compile Time JVMTI Version: %d.%d.%d (0x%08x)\n",
cmajor, cminor, cmicro, cver);
stdout_message("Run Time JVMTI Version: %d.%d.%d (0x%08x)\n",
rmajor, rminor, rmicro, rver);
if ( (cmajor > rmajor) || (cmajor == rmajor && cminor > rminor) ) {
fatal_error(
"ERROR: Compile Time JVMTI and Run Time JVMTI are incompatible\n");
}
}
/* Callback for JVMTI_EVENT_VM_INIT */
static void JNICALL
vm_init(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
jvmtiError err;
jint runtime_version;
/* The exact JVMTI version doesn't have to match, however this
* code demonstrates how you can check that the JVMTI version seen
* in the jvmti.h include file matches that being supplied at runtime
* by the VM.
*/
err = (*jvmti)->GetVersionNumber(jvmti, &runtime_version);
check_jvmti_error(jvmti, err, "get version number");
version_check(JVMTI_VERSION, runtime_version);
}
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
JNIEXPORT jint JNICALL
DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{
jint rc;
jvmtiError err;
jvmtiEventCallbacks callbacks;
jvmtiEnv *jvmti;
/* Get JVMTI environment */
rc = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION);
if (rc != JNI_OK) {
fatal_error("ERROR: Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc);
return -1;
}
/* Set callbacks and enable event notifications */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.VMInit = &vm_init;
err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(callbacks));
check_jvmti_error(jvmti, err, "set event callbacks");
err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE,
JVMTI_EVENT_VM_INIT, NULL);
check_jvmti_error(jvmti, err, "set event notify");
return 0;
}
/* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL
DEF_Agent_OnUnload(JavaVM *vm)
{
}

View File

@ -1,225 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stddef.h>
#include "jni.h"
#include "jvmti.h"
#include "agent_util.h"
#include "Monitor.hpp"
#include "Thread.hpp"
#include "Agent.hpp"
/* Implementation of the Agent class */
/* Given a jvmtiEnv* and jthread, find the Thread instance */
Thread *
Agent::get_thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
jvmtiError err;
Thread *t;
/* This should always be in the Thread Local Storage */
t = NULL;
err = jvmti->GetThreadLocalStorage(thread, (void**)&t);
check_jvmti_error(jvmti, err, "get thread local storage");
if ( t == NULL ) {
/* This jthread has never been seen before? */
stdout_message("WARNING: Never before seen jthread?\n");
t = new Thread(jvmti, env, thread);
err = jvmti->SetThreadLocalStorage(thread, (const void*)t);
check_jvmti_error(jvmti, err, "set thread local storage");
}
return t;
}
/* Given a jvmtiEnv* and jobject, find the Monitor instance or create one */
Monitor *
Agent::get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object)
{
jvmtiError err;
Monitor *m;
jlong tag;
m = NULL;
tag = (jlong)0;
err = jvmti->GetTag(object, &tag);
check_jvmti_error(jvmti, err, "get tag");
/*LINTED*/
m = (Monitor *)(void *)(ptrdiff_t)tag;
if ( m == NULL ) {
m = new Monitor(jvmti, env, object);
/* Save monitor on list */
if (monitor_count == monitor_list_size) {
monitor_list_size += monitor_list_grow_size;
monitor_list = (Monitor**)realloc((void*)monitor_list,
(monitor_list_size)*(int)sizeof(Monitor*));
}
monitor_list[monitor_count] = m;
m->set_slot(monitor_count);
monitor_count++;
/*LINTED*/
tag = (jlong)(ptrdiff_t)(void *)m;
err = jvmti->SetTag(object, tag);
check_jvmti_error(jvmti, err, "set tag");
}
return m;
}
/* VM initialization and VM death calls to Agent */
Agent::Agent(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
stdout_message("Agent created..\n");
stdout_message("VMInit...\n");
/* Start monitor list */
monitor_count = 0;
monitor_list_size = initial_monitor_list_size;
monitor_list = (Monitor**)
malloc(monitor_list_size*(int)sizeof(Monitor*));
}
Agent::~Agent()
{
stdout_message("Agent reclaimed..\n");
}
void Agent::vm_death(jvmtiEnv *jvmti, JNIEnv *env)
{
/* Delete all Monitors we allocated */
for ( int i = 0; i < (int)monitor_count; i++ ) {
delete monitor_list[i];
}
free(monitor_list);
/* Print death message */
stdout_message("VMDeath...\n");
}
/* Thread start event, setup a new thread */
void Agent::thread_start(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
jvmtiError err;
Thread *t;
/* Allocate a new Thread instance, put it in the Thread Local
* Storage for easy access later.
*/
t = new Thread(jvmti, env, thread);
err = jvmti->SetThreadLocalStorage(thread, (const void*)t);
check_jvmti_error(jvmti, err, "set thread local storage");
}
/* Thread end event, we need to reclaim the space */
void Agent::thread_end(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
jvmtiError err;
Thread *t;
/* Find the thread */
t = get_thread(jvmti, env, thread);
/* Clear out the Thread Local Storage */
err = jvmti->SetThreadLocalStorage(thread, (const void*)NULL);
check_jvmti_error(jvmti, err, "set thread local storage");
/* Reclaim the C++ object space */
delete t;
}
/* Monitor contention begins for a thread. */
void Agent::monitor_contended_enter(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object)
{
get_monitor(jvmti, env, object)->contended();
get_thread(jvmti, env, thread)->
monitor_contended_enter(jvmti, env, thread, object);
}
/* Monitor contention ends for a thread. */
void Agent::monitor_contended_entered(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object)
{
/* Do nothing for now */
}
/* Monitor wait begins for a thread. */
void Agent::monitor_wait(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jlong timeout)
{
get_monitor(jvmti, env, object)->waited();
get_thread(jvmti, env, thread)->
monitor_wait(jvmti, env, thread, object, timeout);
}
/* Monitor wait ends for a thread. */
void Agent::monitor_waited(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jboolean timed_out)
{
if ( timed_out ) {
get_monitor(jvmti, env, object)->timeout();
}
get_thread(jvmti, env, thread)->
monitor_waited(jvmti, env, thread, object, timed_out);
}
/* A tagged object has been freed */
void Agent::object_free(jvmtiEnv* jvmti, jlong tag)
{
/* We just cast the tag to a C++ pointer and delete it.
* we know it can only be a Monitor *.
*/
Monitor *m;
/*LINTED*/
m = (Monitor *)(ptrdiff_t)tag;
if (monitor_count > 1) {
/* Move the last element to this Monitor's slot */
int slot = m->get_slot();
Monitor *last = monitor_list[monitor_count-1];
monitor_list[slot] = last;
last->set_slot(slot);
}
monitor_count--;
delete m;
}

View File

@ -1,72 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* C++ Agent class */
class Agent {
private:
enum {
initial_monitor_list_size = 64,
monitor_list_grow_size = 16
};
Monitor **monitor_list;
unsigned monitor_list_size;
unsigned monitor_count;
Thread *get_thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread);
Monitor *get_monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object);
public:
Agent(jvmtiEnv *jvmti, JNIEnv *env, jthread thread);
~Agent();
void vm_death(jvmtiEnv *jvmti, JNIEnv *env);
void thread_start(jvmtiEnv *jvmti, JNIEnv *env, jthread thread);
void thread_end(jvmtiEnv *jvmti, JNIEnv *env, jthread thread);
void monitor_contended_enter(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object);
void monitor_contended_entered(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object);
void monitor_wait(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jlong timeout);
void monitor_waited(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jboolean timed_out);
void object_free(jvmtiEnv* jvmti, jlong tag);
};

View File

@ -1,108 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jni.h"
#include "jvmti.h"
#include "agent_util.h"
#include "Monitor.hpp"
/* Implementation of the Monitor class */
Monitor::Monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object)
{
jvmtiError err;
jclass klass;
char *signature;
/* Clear counters */
contends = 0;
waits = 0;
timeouts = 0;
/* Get the class name for this monitor object */
(void)strcpy(name, "Unknown");
klass = env->GetObjectClass(object);
if ( klass == NULL ) {
fatal_error("ERROR: Cannot find jclass from jobject\n");
}
err = jvmti->GetClassSignature(klass, &signature, NULL);
check_jvmti_error(jvmti, err, "get class signature");
if ( signature != NULL ) {
(void)strncpy(name, signature, (int)sizeof(name)-1);
deallocate(jvmti, signature);
}
}
Monitor::~Monitor()
{
stdout_message("Monitor %s summary: %d contends, %d waits, %d timeouts\n",
name, contends, waits, timeouts);
}
int Monitor::get_slot()
{
return slot;
}
void Monitor::set_slot(int aslot)
{
slot = aslot;
}
void Monitor::contended()
{
contends++;
}
void Monitor::waited()
{
waits++;
}
void Monitor::timeout()
{
timeouts++;
}

View File

@ -1,65 +0,0 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#ifdef STATIC_BUILD
#define Monitor WaiterMonitor
#endif
/* C++ Monitor class */
class Monitor {
private:
char name[64];
int slot;
unsigned contends;
unsigned waits;
unsigned timeouts;
public:
Monitor(jvmtiEnv *jvmti, JNIEnv *env, jobject object);
~Monitor();
int get_slot();
void set_slot(int i);
void contended();
void waited();
void timeout();
};

View File

@ -1,46 +0,0 @@
#
# Copyright (c) 2004, 2007, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
waiters
This agent library can be used to track threads that wait on monitors.
This agent is written in C++.
You can use this agent library as follows:
java -agentlib:waiters ...
To get help on the available options try:
java -agentlib:waiters=help
See ${JAVA_HOME}/demo/jvmti/index.html for help running and building agents.

View File

@ -1,104 +0,0 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
#ifdef STATIC_BUILD
#define Thread WaiterThread
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jni.h"
#include "jvmti.h"
#include "agent_util.h"
#include "Thread.hpp"
/* Implementation of the Thread class */
Thread::Thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
jvmtiError err;
jvmtiThreadInfo info;
/* Get and save the name of the thread */
info.name = NULL;
(void)strcpy(name, "Unknown");
err = jvmti->GetThreadInfo(thread, &info);
check_jvmti_error(jvmti, err, "get thread info");
if ( info.name != NULL ) {
(void)strncpy(name, info.name, (int)sizeof(name)-1);
name[(int)sizeof(name)-1] = 0;
deallocate(jvmti, info.name);
}
/* Clear thread counters */
contends = 0;
waits = 0;
timeouts = 0;
}
Thread::~Thread()
{
/* Send out summary message */
stdout_message("Thread %s summary: %d waits plus %d contended\n",
name, waits, contends);
}
void Thread::monitor_contended_enter(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object)
{
contends++;
}
void Thread::monitor_wait(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jlong timeout)
{
waits++;
}
void Thread::monitor_waited(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jboolean timed_out)
{
if ( timed_out ) {
timeouts++;
}
}

View File

@ -1,61 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* C++ Thread class */
class Thread {
private:
char name[64];
unsigned contends;
unsigned waits;
unsigned timeouts;
public:
Thread(jvmtiEnv *jvmti, JNIEnv *env, jthread thread);
~Thread();
void monitor_contended_enter(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object);
void monitor_wait(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jlong timeout);
void monitor_waited(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jboolean timed_out);
};

View File

@ -1,149 +0,0 @@
#
# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
########################################################################
#
# Sample GNU Makefile for building JVMTI Demo waiters
#
# Example uses:
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparc]
# gnumake JDK=<java_home> OSNAME=solaris [OPT=true] [LIBARCH=sparcv9]
# gnumake JDK=<java_home> OSNAME=linux [OPT=true]
# gnumake JDK=<java_home> OSNAME=win32 [OPT=true]
#
########################################################################
# Source lists
LIBNAME=waiters
SOURCES=waiters.cpp Agent.cpp Thread.cpp Monitor.cpp ../agent_util/agent_util.c
# Solaris Sun C Compiler Version 5.5
ifeq ($(OSNAME), solaris)
# Tell gnumake which compilers to use
CC=cc
CXX=CC
# Sun Solaris Compiler options needed
COMMON_FLAGS=-mt -KPIC
# Check LIBARCH for any special compiler options
LIBARCH=$(shell uname -p)
ifeq ($(LIBARCH), sparc)
COMMON_FLAGS+=-xarch=v8 -xregs=no%appl
endif
ifeq ($(LIBARCH), sparcv9)
COMMON_FLAGS+=-xarch=v9 -xregs=no%appl
endif
ifeq ($(OPT), true)
CXXFLAGS=-xO2 $(COMMON_FLAGS)
else
CXXFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.cpp=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-z defs -ztext
# Libraries we are dependent on
LIBRARIES= -lc
# Building a shared library
LINK_SHARED=$(LINK.cc) -G -o $@
endif
# Linux GNU C Compiler
ifeq ($(OSNAME), linux)
# GNU Compiler options needed to build it
COMMON_FLAGS=-fno-strict-aliasing -fPIC -fno-omit-frame-pointer
# Options that help find errors
COMMON_FLAGS+= -W -Wall -Wno-unused -Wno-parentheses
ifeq ($(OPT), true)
CXXFLAGS=-O2 $(COMMON_FLAGS)
else
CXXFLAGS=-g $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.cpp=%.o)
# Library name and options needed to build it
LIBRARY=lib$(LIBNAME).so
LDFLAGS=-Wl,-soname=$(LIBRARY) -static-libgcc
# Libraries we are dependent on
LIBRARIES=
# Building a shared library
LINK_SHARED=$(LINK.cc) -shared -o $@
endif
# Windows Microsoft C/C++ Optimizing Compiler Version 12
ifeq ($(OSNAME), win32)
CC=cl
# Compiler options needed to build it
COMMON_FLAGS=-Gy -DWIN32
# Options that help find errors
COMMON_FLAGS+=-W0 -WX
ifeq ($(OPT), true)
CXXFLAGS= -Ox -Op -Zi $(COMMON_FLAGS)
else
CXXFLAGS= -Od -Zi $(COMMON_FLAGS)
endif
# Object files needed to create library
OBJECTS=$(SOURCES:%.cpp=%.obj)
# Library name and options needed to build it
LIBRARY=$(LIBNAME).dll
LDFLAGS=
# Libraries we are dependent on
LIBRARIES=
# Building a shared library
LINK_SHARED=link -dll -out:$@
endif
# Common -I options
CXXFLAGS += -I.
CXXFLAGS += -I../agent_util
CXXFLAGS += -I$(JDK)/include -I$(JDK)/include/$(OSNAME)
# Default rule
all: $(LIBRARY)
# Build native library
$(LIBRARY): $(OBJECTS)
$(LINK_SHARED) $(OBJECTS) $(LIBRARIES)
# Cleanup the built bits
clean:
rm -f $(LIBRARY) $(OBJECTS)
# Simple tester
test: all
LD_LIBRARY_PATH=`pwd` $(JDK)/bin/java -agentlib:$(LIBNAME) -version
# Compilation rule only needed on Windows
ifeq ($(OSNAME), win32)
%.obj: %.cpp
$(COMPILE.cc) $<
endif

View File

@ -1,295 +0,0 @@
/*
* Copyright (c) 2004, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/* Example of using JVMTI events:
* JVMTI_EVENT_VM_INIT
* JVMTI_EVENT_VM_DEATH
* JVMTI_EVENT_THREAD_START
* JVMTI_EVENT_THREAD_END
* JVMTI_EVENT_MONITOR_CONTENDED_ENTER
* JVMTI_EVENT_MONITOR_WAIT
* JVMTI_EVENT_MONITOR_WAITED
* JVMTI_EVENT_OBJECT_FREE
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "jni.h"
#include "jvmti.h"
#include "agent_util.h"
#include "Monitor.hpp"
#include "Thread.hpp"
#include "Agent.hpp"
static jrawMonitorID vm_death_lock;
static jboolean vm_death_active;
/* Given a jvmtiEnv*, return the C++ Agent class instance */
static Agent *
get_agent(jvmtiEnv *jvmti)
{
jvmtiError err;
Agent *agent;
agent = NULL;
err = jvmti->GetEnvironmentLocalStorage((void**)&agent);
check_jvmti_error(jvmti, err, "get env local storage");
if ( agent == NULL ) {
/* This should never happen, but we should check */
fatal_error("ERROR: GetEnvironmentLocalStorage() returned NULL");
}
return agent;
}
/* Enter raw monitor */
static void
menter(jvmtiEnv *jvmti, jrawMonitorID rmon)
{
jvmtiError err;
err = jvmti->RawMonitorEnter(rmon);
check_jvmti_error(jvmti, err, "raw monitor enter");
}
/* Exit raw monitor */
static void
mexit(jvmtiEnv *jvmti, jrawMonitorID rmon)
{
jvmtiError err;
err = jvmti->RawMonitorExit(rmon);
check_jvmti_error(jvmti, err, "raw monitor exit");
}
/* All callbacks need to be extern "C" */
extern "C" {
static void JNICALL
vm_init(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
jvmtiError err;
Agent *agent;
/* Create raw monitor to protect against threads running after death */
err = jvmti->CreateRawMonitor("Waiters vm_death lock", &vm_death_lock);
check_jvmti_error(jvmti, err, "create raw monitor");
vm_death_active = JNI_FALSE;
/* Create an Agent instance, set JVMTI Local Storage */
agent = new Agent(jvmti, env, thread);
err = jvmti->SetEnvironmentLocalStorage((const void*)agent);
check_jvmti_error(jvmti, err, "set env local storage");
/* Enable all other events we want */
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_VM_DEATH, NULL);
check_jvmti_error(jvmti, err, "set event notify");
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_THREAD_START, NULL);
check_jvmti_error(jvmti, err, "set event notify");
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_THREAD_END, NULL);
check_jvmti_error(jvmti, err, "set event notify");
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_MONITOR_CONTENDED_ENTER, NULL);
check_jvmti_error(jvmti, err, "set event notify");
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_MONITOR_CONTENDED_ENTERED, NULL);
check_jvmti_error(jvmti, err, "set event notify");
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_MONITOR_WAIT, NULL);
check_jvmti_error(jvmti, err, "set event notify");
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_MONITOR_WAITED, NULL);
check_jvmti_error(jvmti, err, "set event notify");
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_OBJECT_FREE, NULL);
check_jvmti_error(jvmti, err, "set event notify");
}
static void JNICALL
vm_death(jvmtiEnv *jvmti, JNIEnv *env)
{
jvmtiError err;
Agent *agent;
/* Block all callbacks */
menter(jvmti, vm_death_lock); {
/* Set flag for other callbacks */
vm_death_active = JNI_TRUE;
/* Inform Agent instance of VM_DEATH */
agent = get_agent(jvmti);
agent->vm_death(jvmti, env);
/* Reclaim space of Agent */
err = jvmti->SetEnvironmentLocalStorage((const void*)NULL);
check_jvmti_error(jvmti, err, "set env local storage");
delete agent;
} mexit(jvmti, vm_death_lock);
}
static void JNICALL
thread_start(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
menter(jvmti, vm_death_lock); {
if ( !vm_death_active ) {
get_agent(jvmti)->thread_start(jvmti, env, thread);
}
} mexit(jvmti, vm_death_lock);
}
static void JNICALL
thread_end(jvmtiEnv *jvmti, JNIEnv *env, jthread thread)
{
menter(jvmti, vm_death_lock); {
if ( !vm_death_active ) {
get_agent(jvmti)->thread_end(jvmti, env, thread);
}
} mexit(jvmti, vm_death_lock);
}
static void JNICALL
monitor_contended_enter(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object)
{
menter(jvmti, vm_death_lock); {
if ( !vm_death_active ) {
get_agent(jvmti)->monitor_contended_enter(jvmti, env,
thread, object);
}
} mexit(jvmti, vm_death_lock);
}
static void JNICALL
monitor_contended_entered(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object)
{
menter(jvmti, vm_death_lock); {
if ( !vm_death_active ) {
get_agent(jvmti)->monitor_contended_entered(jvmti, env,
thread, object);
}
} mexit(jvmti, vm_death_lock);
}
static void JNICALL
monitor_wait(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jlong timeout)
{
menter(jvmti, vm_death_lock); {
if ( !vm_death_active ) {
get_agent(jvmti)->monitor_wait(jvmti, env, thread,
object, timeout);
}
} mexit(jvmti, vm_death_lock);
}
static void JNICALL
monitor_waited(jvmtiEnv* jvmti, JNIEnv *env,
jthread thread, jobject object, jboolean timed_out)
{
menter(jvmti, vm_death_lock); {
if ( !vm_death_active ) {
get_agent(jvmti)->monitor_waited(jvmti, env, thread,
object, timed_out);
}
} mexit(jvmti, vm_death_lock);
}
static void JNICALL
object_free(jvmtiEnv* jvmti, jlong tag)
{
menter(jvmti, vm_death_lock); {
if ( !vm_death_active ) {
get_agent(jvmti)->object_free(jvmti, tag);
}
} mexit(jvmti, vm_death_lock);
}
/* Agent_OnLoad() is called first, we prepare for a VM_INIT event here. */
JNIEXPORT jint JNICALL
DEF_Agent_OnLoad(JavaVM *vm, char *options, void *reserved)
{
jvmtiEnv *jvmti;
jint rc;
jvmtiError err;
jvmtiCapabilities capabilities;
jvmtiEventCallbacks callbacks;
/* Get JVMTI environment */
rc = vm->GetEnv((void **)&jvmti, JVMTI_VERSION);
if (rc != JNI_OK) {
fatal_error("ERROR: Unable to create jvmtiEnv, GetEnv failed, error=%d\n", rc);
return -1;
}
/* Get/Add JVMTI capabilities */
(void)memset(&capabilities, 0, sizeof(capabilities));
capabilities.can_generate_monitor_events = 1;
capabilities.can_get_monitor_info = 1;
capabilities.can_tag_objects = 1;
capabilities.can_generate_object_free_events = 1;
err = jvmti->AddCapabilities(&capabilities);
check_jvmti_error(jvmti, err, "add capabilities");
/* Set all callbacks and enable VM_INIT event notification */
memset(&callbacks, 0, sizeof(callbacks));
callbacks.VMInit = &vm_init;
callbacks.VMDeath = &vm_death;
callbacks.ThreadStart = &thread_start;
callbacks.ThreadEnd = &thread_end;
callbacks.MonitorContendedEnter = &monitor_contended_enter;
callbacks.MonitorContendedEntered = &monitor_contended_entered;
callbacks.MonitorWait = &monitor_wait;
callbacks.MonitorWaited = &monitor_waited;
callbacks.ObjectFree = &object_free;
err = jvmti->SetEventCallbacks(&callbacks, (jint)sizeof(callbacks));
check_jvmti_error(jvmti, err, "set event callbacks");
err = jvmti->SetEventNotificationMode(JVMTI_ENABLE,
JVMTI_EVENT_VM_INIT, NULL);
check_jvmti_error(jvmti, err, "set event notify");
return 0;
}
/* Agent_OnUnload() is called last */
JNIEXPORT void JNICALL
DEF_Agent_OnUnload(JavaVM *vm)
{
}
} /* of extern "C" */

View File

@ -1,214 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
*/
import java.util.concurrent.CyclicBarrier;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.io.IOException;
/**
* This Deadlock class demonstrates the capability of performing
* deadlock detection programmatically within the application using
* the java.lang.management API.
*
* See ThreadMonitor.java for the use of java.lang.management.ThreadMXBean
* API.
*/
public class Deadlock {
public static void main(String[] argv) {
new Deadlock();
// Now find deadlock
ThreadMonitor monitor = new ThreadMonitor();
boolean found = false;
while (!found) {
found = monitor.findDeadlock();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
System.exit(1);
}
}
System.out.println("\nPress <Enter> to exit this Deadlock program.\n");
waitForEnterPressed();
}
private CyclicBarrier barrier = new CyclicBarrier(6);
public Deadlock() {
DeadlockThread[] dThreads = new DeadlockThread[6];
Monitor a = new Monitor("a");
Monitor b = new Monitor("b");
Monitor c = new Monitor("c");
dThreads[0] = new DeadlockThread("MThread-1", a, b);
dThreads[1] = new DeadlockThread("MThread-2", b, c);
dThreads[2] = new DeadlockThread("MThread-3", c, a);
Lock d = new ReentrantLock();
Lock e = new ReentrantLock();
Lock f = new ReentrantLock();
dThreads[3] = new DeadlockThread("SThread-4", d, e);
dThreads[4] = new DeadlockThread("SThread-5", e, f);
dThreads[5] = new DeadlockThread("SThread-6", f, d);
// make them daemon threads so that the test will exit
for (int i = 0; i < 6; i++) {
dThreads[i].setDaemon(true);
dThreads[i].start();
}
}
class DeadlockThread extends Thread {
private Lock lock1 = null;
private Lock lock2 = null;
private Monitor mon1 = null;
private Monitor mon2 = null;
private boolean useSync;
DeadlockThread(String name, Lock lock1, Lock lock2) {
super(name);
this.lock1 = lock1;
this.lock2 = lock2;
this.useSync = true;
}
DeadlockThread(String name, Monitor mon1, Monitor mon2) {
super(name);
this.mon1 = mon1;
this.mon2 = mon2;
this.useSync = false;
}
@Override
public void run() {
if (useSync) {
syncLock();
} else {
monitorLock();
}
}
private void syncLock() {
lock1.lock();
try {
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
} catch (BrokenBarrierException e) {
e.printStackTrace();
System.exit(1);
}
goSyncDeadlock();
} finally {
lock1.unlock();
}
}
private void goSyncDeadlock() {
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
} catch (BrokenBarrierException e) {
e.printStackTrace();
System.exit(1);
}
lock2.lock();
throw new RuntimeException("should not reach here.");
}
private void monitorLock() {
synchronized (mon1) {
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
} catch (BrokenBarrierException e) {
e.printStackTrace();
System.exit(1);
}
goMonitorDeadlock();
}
}
private void goMonitorDeadlock() {
try {
barrier.await();
} catch (InterruptedException e) {
e.printStackTrace();
System.exit(1);
} catch (BrokenBarrierException e) {
e.printStackTrace();
System.exit(1);
}
synchronized (mon2) {
throw new RuntimeException(getName() + " should not reach here.");
}
}
}
class Monitor {
String name;
Monitor(String name) {
this.name = name;
}
}
private static void waitForEnterPressed() {
try {
boolean done = false;
while (!done) {
char ch = (char) System.in.read();
if (ch<0||ch=='\n') {
done = true;
}
}
}
catch (IOException e) {
e.printStackTrace();
System.exit(0);
}
}
}

View File

@ -1,122 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
*/
import javax.management.*;
import javax.management.remote.*;
import java.io.IOException;
import java.net.MalformedURLException;
/**
* This FullThreadDump class demonstrates the capability to get
* a full thread dump and also detect deadlock remotely.
*/
public class FullThreadDump {
private MBeanServerConnection server;
private JMXConnector jmxc;
public FullThreadDump(String hostname, int port) {
System.out.println("Connecting to " + hostname + ":" + port);
// Create an RMI connector client and connect it to
// the RMI connector server
String urlPath = "/jndi/rmi://" + hostname + ":" + port + "/jmxrmi";
connect(urlPath);
}
public void dump() {
try {
ThreadMonitor monitor = new ThreadMonitor(server);
monitor.threadDump();
if (!monitor.findDeadlock()) {
System.out.println("No deadlock found.");
}
} catch (IOException e) {
System.err.println("\nCommunication error: " + e.getMessage());
System.exit(1);
}
}
/**
* Connect to a JMX agent of a given URL.
*/
private void connect(String urlPath) {
try {
JMXServiceURL url = new JMXServiceURL("rmi", "", 0, urlPath);
this.jmxc = JMXConnectorFactory.connect(url);
this.server = jmxc.getMBeanServerConnection();
} catch (MalformedURLException e) {
// should not reach here
} catch (IOException e) {
System.err.println("\nCommunication error: " + e.getMessage());
System.exit(1);
}
}
public static void main(String[] args) {
if (args.length != 1) {
usage();
}
String[] arg2 = args[0].split(":");
if (arg2.length != 2) {
usage();
}
String hostname = arg2[0];
int port = -1;
try {
port = Integer.parseInt(arg2[1]);
} catch (NumberFormatException x) {
usage();
}
if (port < 0) {
usage();
}
// get full thread dump and perform deadlock detection
FullThreadDump ftd = new FullThreadDump(hostname, port);
ftd.dump();
}
private static void usage() {
System.out.println("Usage: java FullThreadDump <hostname>:<port>");
}
}

View File

@ -1,52 +0,0 @@
FullThreadDump demonstrates the use of the java.lang.management API
to print the full thread dump. JDK 6 defines a new API to dump
the information about monitors and java.util.concurrent ownable
synchronizers.
This demo also illustrates how to monitor JDK 5 and JDK 6 VMs with
two versions of APIs.
It contains two parts:
a) Local monitoring within the application
b) Remote monitoring by connecting to a JMX agent with a JMX service URL:
service:jmx:rmi:///jndi/rmi://<hostName>:<portNum>/jmxrmi
where <hostName> is the hostname and <portNum> is the port number
to which the JMX agent will be connected.
To run the demo
---------------
a) Local Monitoring
java -cp <JDK_HOME>/demo/management/FullThreadDump/FullThreadDump.jar Deadlock
This will dump the stack trace and then detect deadlocks locally
within the application.
b) Remote Monitoring
(1) Start the Deadlock application (or any other application)
with the JMX agent as follows:
java -Dcom.sun.management.jmxremote.port=1090
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-cp <JDK_HOME>/demo/management/FullThreadDump/FullThreadDump.jar
Deadlock
This instruction uses the Sun's built-in support to enable a JMX agent.
You can programmatically start a JMX agent with the RMI connector
using javax.management.remote API. See the javadoc and examples for
javax.management.remote API for details.
(2) Run FullThreadDump
java -jar <JDK_HOME>/demo/management/FullThreadDump/FullThreadDump.jar \
localhost:1090
This will dump the stack trace and then print out the deadlocked threads.
These instructions assume that this installation's version of the java
command is in your path. If it isn't, then you should either
specify the complete path to the java command or update your
PATH environment variable as described in the installation
instructions for the Java(TM) SDK.

View File

@ -1,266 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
*/
import static java.lang.management.ManagementFactory.*;
import java.lang.management.ThreadMXBean;
import java.lang.management.ThreadInfo;
import java.lang.management.LockInfo;
import java.lang.management.MonitorInfo;
import javax.management.*;
import java.io.*;
/**
* Example of using the java.lang.management API to dump stack trace
* and to perform deadlock detection.
*
* @author Mandy Chung
*/
public class ThreadMonitor {
private MBeanServerConnection server;
private ThreadMXBean tmbean;
private ObjectName objname;
// default - JDK 6+ VM
private String findDeadlocksMethodName = "findDeadlockedThreads";
private boolean canDumpLocks = true;
/**
* Constructs a ThreadMonitor object to get thread information
* in a remote JVM.
*/
public ThreadMonitor(MBeanServerConnection server) throws IOException {
this.server = server;
this.tmbean = newPlatformMXBeanProxy(server,
THREAD_MXBEAN_NAME,
ThreadMXBean.class);
try {
objname = new ObjectName(THREAD_MXBEAN_NAME);
} catch (MalformedObjectNameException e) {
// should not reach here
InternalError ie = new InternalError(e.getMessage());
ie.initCause(e);
throw ie;
}
parseMBeanInfo();
}
/**
* Constructs a ThreadMonitor object to get thread information
* in the local JVM.
*/
public ThreadMonitor() {
this.tmbean = getThreadMXBean();
}
/**
* Prints the thread dump information to System.out.
*/
public void threadDump() {
if (canDumpLocks) {
if (tmbean.isObjectMonitorUsageSupported() &&
tmbean.isSynchronizerUsageSupported()) {
// Print lock info if both object monitor usage
// and synchronizer usage are supported.
// This sample code can be modified to handle if
// either monitor usage or synchronizer usage is supported.
dumpThreadInfoWithLocks();
}
} else {
dumpThreadInfo();
}
}
private void dumpThreadInfo() {
System.out.println("Full Java thread dump");
long[] tids = tmbean.getAllThreadIds();
ThreadInfo[] tinfos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
for (ThreadInfo ti : tinfos) {
printThreadInfo(ti);
}
}
/**
* Prints the thread dump information with locks info to System.out.
*/
private void dumpThreadInfoWithLocks() {
System.out.println("Full Java thread dump with locks info");
ThreadInfo[] tinfos = tmbean.dumpAllThreads(true, true);
for (ThreadInfo ti : tinfos) {
printThreadInfo(ti);
LockInfo[] syncs = ti.getLockedSynchronizers();
printLockInfo(syncs);
}
System.out.println();
}
private static String INDENT = " ";
private void printThreadInfo(ThreadInfo ti) {
// print thread information
printThread(ti);
// print stack trace with locks
StackTraceElement[] stacktrace = ti.getStackTrace();
MonitorInfo[] monitors = ti.getLockedMonitors();
for (int i = 0; i < stacktrace.length; i++) {
StackTraceElement ste = stacktrace[i];
System.out.println(INDENT + "at " + ste.toString());
for (MonitorInfo mi : monitors) {
if (mi.getLockedStackDepth() == i) {
System.out.println(INDENT + " - locked " + mi);
}
}
}
System.out.println();
}
private void printThread(ThreadInfo ti) {
StringBuilder sb = new StringBuilder("\"" + ti.getThreadName() + "\"" +
" Id=" + ti.getThreadId() +
" in " + ti.getThreadState());
if (ti.getLockName() != null) {
sb.append(" on lock=" + ti.getLockName());
}
if (ti.isSuspended()) {
sb.append(" (suspended)");
}
if (ti.isInNative()) {
sb.append(" (running in native)");
}
System.out.println(sb.toString());
if (ti.getLockOwnerName() != null) {
System.out.println(INDENT + " owned by " + ti.getLockOwnerName() +
" Id=" + ti.getLockOwnerId());
}
}
private void printMonitorInfo(ThreadInfo ti) {
MonitorInfo[] monitors = ti.getLockedMonitors();
System.out.println(INDENT + "Locked monitors: count = " + monitors.length);
for (MonitorInfo mi : monitors) {
System.out.println(INDENT + " - " + mi + " locked at ");
System.out.println(INDENT + " " + mi.getLockedStackDepth() +
" " + mi.getLockedStackFrame());
}
}
private void printLockInfo(LockInfo[] locks) {
System.out.println(INDENT + "Locked synchronizers: count = " + locks.length);
for (LockInfo li : locks) {
System.out.println(INDENT + " - " + li);
}
System.out.println();
}
/**
* Checks if any threads are deadlocked. If any, print
* the thread dump information.
*/
public boolean findDeadlock() {
long[] tids;
if (findDeadlocksMethodName.equals("findDeadlockedThreads") &&
tmbean.isSynchronizerUsageSupported()) {
tids = tmbean.findDeadlockedThreads();
if (tids == null) {
return false;
}
System.out.println("Deadlock found :-");
ThreadInfo[] infos = tmbean.getThreadInfo(tids, true, true);
for (ThreadInfo ti : infos) {
printThreadInfo(ti);
printMonitorInfo(ti);
printLockInfo(ti.getLockedSynchronizers());
System.out.println();
}
} else {
tids = tmbean.findMonitorDeadlockedThreads();
if (tids == null) {
return false;
}
ThreadInfo[] infos = tmbean.getThreadInfo(tids, Integer.MAX_VALUE);
for (ThreadInfo ti : infos) {
// print thread information
printThreadInfo(ti);
}
}
return true;
}
private void parseMBeanInfo() throws IOException {
try {
MBeanOperationInfo[] mopis = server.getMBeanInfo(objname).getOperations();
// look for findDeadlockedThreads operations;
boolean found = false;
for (MBeanOperationInfo op : mopis) {
if (op.getName().equals(findDeadlocksMethodName)) {
found = true;
break;
}
}
if (!found) {
// if findDeadlockedThreads operation doesn't exist,
// the target VM is running on JDK 5 and details about
// synchronizers and locks cannot be dumped.
findDeadlocksMethodName = "findMonitorDeadlockedThreads";
canDumpLocks = false;
}
} catch (IntrospectionException e) {
InternalError ie = new InternalError(e.getMessage());
ie.initCause(e);
throw ie;
} catch (InstanceNotFoundException e) {
InternalError ie = new InternalError(e.getMessage());
ie.initCause(e);
throw ie;
} catch (ReflectionException e) {
InternalError ie = new InternalError(e.getMessage());
ie.initCause(e);
throw ie;
}
}
}

View File

@ -1,427 +0,0 @@
/*
* Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
*
* Example of using the java.lang.management API to sort threads
* by CPU usage.
*
* JTop class can be run as a standalone application.
* It first establishs a connection to a target VM specified
* by the given hostname and port number where the JMX agent
* to be connected. It then polls for the thread information
* and the CPU consumption of each thread to display every 2
* seconds.
*
* It is also used by JTopPlugin which is a JConsolePlugin
* that can be used with JConsole (see README.txt). The JTop
* GUI will be added as a JConsole tab by the JTop plugin.
*
* @see com.sun.tools.jconsole.JConsolePlugin
*
* @author Mandy Chung
*/
import java.lang.management.*;
import javax.management.*;
import javax.management.remote.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.Timer;
import java.util.TimerTask;
import java.util.TreeMap;
import java.util.concurrent.ExecutionException;
import java.text.NumberFormat;
import java.net.MalformedURLException;
import static java.lang.management.ManagementFactory.*;
import java.awt.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.table.*;
/**
* JTop is a JPanel to display thread's name, CPU time, and its state
* in a table.
*/
public class JTop extends JPanel {
private static class StatusBar extends JPanel {
private static final long serialVersionUID = -6483392381797633018L;
private final JLabel statusText;
public StatusBar(boolean defaultVisible) {
super(new GridLayout(1, 1));
statusText = new JLabel();
statusText.setVisible(defaultVisible);
add(statusText);
}
@Override
public Dimension getMaximumSize() {
Dimension maximum = super.getMaximumSize();
Dimension minimum = getMinimumSize();
return new Dimension(maximum.width, minimum.height);
}
public void setMessage(String text) {
statusText.setText(text);
statusText.setVisible(true);
}
}
private static final long serialVersionUID = -1499762160973870696L;
private MBeanServerConnection server;
private ThreadMXBean tmbean;
private MyTableModel tmodel;
private final StatusBar statusBar;
public JTop() {
super(new GridBagLayout());
tmodel = new MyTableModel();
JTable table = new JTable(tmodel);
table.setPreferredScrollableViewportSize(new Dimension(500, 300));
// Set the renderer to format Double
table.setDefaultRenderer(Double.class, new DoubleRenderer());
// Add some space
table.setIntercellSpacing(new Dimension(6,3));
table.setRowHeight(table.getRowHeight() + 4);
// Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
// Add the scroll pane to this panel.
GridBagConstraints c1 = new GridBagConstraints();
c1.fill = GridBagConstraints.BOTH;
c1.gridy = 0;
c1.gridx = 0;
c1.weightx = 1;
c1.weighty = 1;
add(scrollPane, c1);
statusBar = new StatusBar(false);
GridBagConstraints c2 = new GridBagConstraints();
c2.fill = GridBagConstraints.HORIZONTAL;
c2.gridy = 1;
c2.gridx = 0;
c2.weightx = 1.0;
c2.weighty = 0.0;
add(statusBar, c2);
}
// Set the MBeanServerConnection object for communicating
// with the target VM
public void setMBeanServerConnection(MBeanServerConnection mbs) {
this.server = mbs;
try {
this.tmbean = newPlatformMXBeanProxy(server,
THREAD_MXBEAN_NAME,
ThreadMXBean.class);
} catch (IOException e) {
e.printStackTrace();
}
if (!tmbean.isThreadCpuTimeSupported()) {
statusBar.setMessage("Monitored VM does not support thread CPU time measurement");
} else {
try {
tmbean.setThreadCpuTimeEnabled(true);
} catch (SecurityException e) {
statusBar.setMessage("Monitored VM does not have permission for enabling thread cpu time measurement");
}
}
}
class MyTableModel extends AbstractTableModel {
private static final long serialVersionUID = -7877310288576779514L;
private String[] columnNames = {"ThreadName",
"CPU(sec)",
"State"};
// List of all threads. The key of each entry is the CPU time
// and its value is the ThreadInfo object with no stack trace.
private List<Map.Entry<Long, ThreadInfo>> threadList =
Collections.emptyList();
public MyTableModel() {
}
@Override
public int getColumnCount() {
return columnNames.length;
}
@Override
public int getRowCount() {
return threadList.size();
}
@Override
public String getColumnName(int col) {
return columnNames[col];
}
@Override
public Object getValueAt(int row, int col) {
Map.Entry<Long, ThreadInfo> me = threadList.get(row);
switch (col) {
case 0 :
// Column 0 shows the thread name
return me.getValue().getThreadName();
case 1 :
// Column 1 shows the CPU usage
long ns = me.getKey().longValue();
double sec = ns / 1000000000;
return new Double(sec);
case 2 :
// Column 2 shows the thread state
return me.getValue().getThreadState();
default:
return null;
}
}
@Override
public Class<?> getColumnClass(int c) {
return getValueAt(0, c).getClass();
}
void setThreadList(List<Map.Entry<Long, ThreadInfo>> list) {
threadList = list;
}
}
/**
* Get the thread list with CPU consumption and the ThreadInfo
* for each thread sorted by the CPU time.
*/
private List<Map.Entry<Long, ThreadInfo>> getThreadList() {
// Get all threads and their ThreadInfo objects
// with no stack trace
long[] tids = tmbean.getAllThreadIds();
ThreadInfo[] tinfos = tmbean.getThreadInfo(tids);
// build a map with key = CPU time and value = ThreadInfo
SortedMap<Long, ThreadInfo> map = new TreeMap<Long, ThreadInfo>();
for (int i = 0; i < tids.length; i++) {
long cpuTime = tmbean.getThreadCpuTime(tids[i]);
// filter out threads that have been terminated
if (cpuTime != -1 && tinfos[i] != null) {
map.put(new Long(cpuTime), tinfos[i]);
}
}
// build the thread list and sort it with CPU time
// in decreasing order
Set<Map.Entry<Long, ThreadInfo>> set = map.entrySet();
List<Map.Entry<Long, ThreadInfo>> list =
new ArrayList<Map.Entry<Long, ThreadInfo>>(set);
Collections.reverse(list);
return list;
}
/**
* Format Double with 4 fraction digits
*/
class DoubleRenderer extends DefaultTableCellRenderer {
private static final long serialVersionUID = 1704639497162584382L;
NumberFormat formatter;
public DoubleRenderer() {
super();
setHorizontalAlignment(JLabel.RIGHT);
}
@Override
public void setValue(Object value) {
if (formatter==null) {
formatter = NumberFormat.getInstance();
formatter.setMinimumFractionDigits(4);
}
setText((value == null) ? "" : formatter.format(value));
}
}
// SwingWorker responsible for updating the GUI
//
// It first gets the thread and CPU usage information as a
// background task done by a worker thread so that
// it will not block the event dispatcher thread.
//
// When the worker thread finishes, the event dispatcher
// thread will invoke the done() method which will update
// the UI.
class Worker extends SwingWorker<List<Map.Entry<Long, ThreadInfo>>,Object> {
private MyTableModel tmodel;
Worker(MyTableModel tmodel) {
this.tmodel = tmodel;
}
// Get the current thread info and CPU time
@Override
public List<Map.Entry<Long, ThreadInfo>> doInBackground() {
return getThreadList();
}
// fire table data changed to trigger GUI update
// when doInBackground() is finished
@Override
protected void done() {
try {
// Set table model with the new thread list
tmodel.setThreadList(get());
// refresh the table model
tmodel.fireTableDataChanged();
} catch (InterruptedException e) {
} catch (ExecutionException e) {
}
}
}
// Return a new SwingWorker for UI update
public SwingWorker<?,?> newSwingWorker() {
return new Worker(tmodel);
}
public static void main(String[] args) throws Exception {
// Validate the input arguments
if (args.length != 1) {
usage();
}
String[] arg2 = args[0].split(":");
if (arg2.length != 2) {
usage();
}
String hostname = arg2[0];
int port = -1;
try {
port = Integer.parseInt(arg2[1]);
} catch (NumberFormatException x) {
usage();
}
if (port < 0) {
usage();
}
// Create the JTop Panel
final JTop jtop = new JTop();
// Set up the MBeanServerConnection to the target VM
MBeanServerConnection server = connect(hostname, port);
jtop.setMBeanServerConnection(server);
// A timer task to update GUI per each interval
TimerTask timerTask = new TimerTask() {
@Override
public void run() {
// Schedule the SwingWorker to update the GUI
jtop.newSwingWorker().execute();
}
};
// Create the standalone window with JTop panel
// by the event dispatcher thread
SwingUtilities.invokeAndWait(new Runnable() {
@Override
public void run() {
createAndShowGUI(jtop);
}
});
// refresh every 2 seconds
Timer timer = new Timer("JTop Sampling thread");
timer.schedule(timerTask, 0, 2000);
}
// Establish a connection with the remote application
//
// You can modify the urlPath to the address of the JMX agent
// of your application if it has a different URL.
//
// You can also modify the following code to take
// username and password for client authentication.
private static MBeanServerConnection connect(String hostname, int port) {
// Create an RMI connector client and connect it to
// the RMI connector server
String urlPath = "/jndi/rmi://" + hostname + ":" + port + "/jmxrmi";
MBeanServerConnection server = null;
try {
JMXServiceURL url = new JMXServiceURL("rmi", "", 0, urlPath);
JMXConnector jmxc = JMXConnectorFactory.connect(url);
server = jmxc.getMBeanServerConnection();
} catch (MalformedURLException e) {
// should not reach here
} catch (IOException e) {
System.err.println("\nCommunication error: " + e.getMessage());
System.exit(1);
}
return server;
}
private static void usage() {
System.out.println("Usage: java JTop <hostname>:<port>");
System.exit(1);
}
/**
* Create the GUI and show it. For thread safety,
* this method should be invoked from the
* event-dispatching thread.
*/
private static void createAndShowGUI(JPanel jtop) {
// Create and set up the window.
JFrame frame = new JFrame("JTop");
frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
// Create and set up the content pane.
JComponent contentPane = (JComponent) frame.getContentPane();
contentPane.add(jtop, BorderLayout.CENTER);
contentPane.setOpaque(true); //content panes must be opaque
contentPane.setBorder(new EmptyBorder(12, 12, 12, 12));
frame.setContentPane(contentPane);
// Display the window.
frame.pack();
frame.setVisible(true);
}
}

View File

@ -1,130 +0,0 @@
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
*
* Example of a JConsole Plugin. This loads JTop as a JConsole tab.
*
* @author Mandy Chung
*/
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.LinkedHashMap;
import java.util.Map;
import javax.swing.JPanel;
import javax.swing.SwingWorker;
import com.sun.tools.jconsole.JConsoleContext;
import com.sun.tools.jconsole.JConsoleContext.ConnectionState;
import com.sun.tools.jconsole.JConsolePlugin;
/**
* JTopPlugin is a subclass to com.sun.tools.jconsole.JConsolePlugin
*
* JTopPlugin is loaded and instantiated by JConsole. One instance
* is created for each window that JConsole creates. It listens to
* the connected property change so that it will update JTop with
* the valid MBeanServerConnection object. JTop is a JPanel object
* displaying the thread and its CPU usage information.
*/
public class JTopPlugin extends JConsolePlugin implements PropertyChangeListener
{
private JTop jtop = null;
private Map<String, JPanel> tabs = null;
public JTopPlugin() {
// register itself as a listener
addContextPropertyChangeListener(this);
}
/*
* Returns a JTop tab to be added in JConsole.
*/
@Override
public synchronized Map<String, JPanel> getTabs() {
if (tabs == null) {
jtop = new JTop();
jtop.setMBeanServerConnection(
getContext().getMBeanServerConnection());
// use LinkedHashMap if you want a predictable order
// of the tabs to be added in JConsole
tabs = new LinkedHashMap<String, JPanel>();
tabs.put("JTop", jtop);
}
return tabs;
}
/*
* Returns a SwingWorker which is responsible for updating the JTop tab.
*/
@Override
public SwingWorker<?,?> newSwingWorker() {
return jtop.newSwingWorker();
}
// You can implement the dispose() method if you need to release
// any resource when the plugin instance is disposed when the JConsole
// window is closed.
//
// public void dispose() {
// }
/*
* Property listener to reset the MBeanServerConnection
* at reconnection time.
*/
@Override
public void propertyChange(PropertyChangeEvent ev) {
String prop = ev.getPropertyName();
if (prop == JConsoleContext.CONNECTION_STATE_PROPERTY) {
ConnectionState newState = (ConnectionState)ev.getNewValue();
// JConsole supports disconnection and reconnection
// The MBeanServerConnection will become invalid when
// disconnected. Need to use the new MBeanServerConnection object
// created at reconnection time.
if (newState == ConnectionState.CONNECTED && jtop != null) {
jtop.setMBeanServerConnection(
getContext().getMBeanServerConnection());
}
}
}
}

View File

@ -1,61 +0,0 @@
JTop monitors the CPU usage of all threads in a remote application
which has remote management enabled. JTop demonstrates the use of
the java.lang.management API to obtain the CPU consumption for
each thread.
JTop is also a JConsole Plugin. See below for details.
JTop Standalone GUI
===================
JTop first establishes a connection to a JMX agent in a remote
application with a JMX service URL:
service:jmx:rmi:///jndi/rmi://<hostName>:<portNum>/jmxrmi
where <hostName> is the hostname and <portNum> is the port number
to which the JMX agent will be connected.
To run the demo
---------------
(1) Start the application with the JMX agent - here's an example of
how the Java2D is started
java -Dcom.sun.management.jmxremote.port=1090
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-jar <JDK_HOME>/demo/jfc/Java2D/Java2Demo.jar
This instruction uses the Sun's built-in support to enable a JMX agent
with a JMX service URL as described above.
You can programmatically start a JMX agent with the RMI connector
using javax.management.remote API. See the javadoc and examples for
javax.management.remote API for details.
(2) Run JTop on a different machine:
java -jar <JDK_HOME>/demo/management/JTop/JTop.jar <hostname>:1090
where <hostname> is where the Java2Demo.jar runs in step (1).
These instructions assume that this installation's version of the java
command is in your path. If it isn't, then you should either
specify the complete path to the java command or update your
PATH environment variable as described in the installation
instructions for the Java(TM) SDK.
JTop JConsole Plugin
====================
JTop is a JConsole Plugin which adds a "JTop" tab to JConsole.
To run JConsole with the JTop plugin
------------------------------------
jconsole -pluginpath <JDK_HOME>/demo/management/JTop/JTop.jar
To compile
----------
javac -classpath <JDK_HOME>/lib/jconsole.jar JTopPlugin.java
com.sun.tools.jconsole API is in jconsole.jar which is needed
in the classpath for compilation.

View File

@ -1,491 +0,0 @@
/*
* Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
*/
import java.awt.*;
import java.awt.event.*;
import java.awt.image.BufferedImage;
import java.awt.geom.Line2D;
import java.awt.geom.Rectangle2D;
import java.util.Date;
import javax.swing.*;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;
import java.lang.management.*;
/**
* Demo code which plots the memory usage by all memory pools.
* The memory usage is sampled at some time interval using
* java.lang.management API. This demo code is modified based
* java2d MemoryMonitor demo.
*/
public class MemoryMonitor extends JPanel {
private static final long serialVersionUID = -3463003810776195761L;
static JCheckBox dateStampCB = new JCheckBox("Output Date Stamp");
public Surface surf;
JPanel controls;
boolean doControls;
JTextField tf;
// Get memory pools.
static java.util.List<MemoryPoolMXBean> mpools =
ManagementFactory.getMemoryPoolMXBeans();
// Total number of memory pools.
static int numPools = mpools.size();
public MemoryMonitor() {
setLayout(new BorderLayout());
setBorder(new TitledBorder(new EtchedBorder(), "Memory Monitor"));
add(surf = new Surface());
controls = new JPanel();
controls.setPreferredSize(new Dimension(135,80));
Font font = new Font("serif", Font.PLAIN, 10);
JLabel label = new JLabel("Sample Rate");
label.setFont(font);
label.setForeground(Color.red);
controls.add(label);
tf = new JTextField("1000");
tf.setPreferredSize(new Dimension(45,20));
controls.add(tf);
controls.add(label = new JLabel("ms"));
label.setFont(font);
label.setForeground(Color.red);
controls.add(dateStampCB);
dateStampCB.setFont(font);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
removeAll();
if ((doControls = !doControls)) {
surf.stop();
add(controls);
} else {
try {
surf.sleepAmount = Long.parseLong(tf.getText().trim());
} catch (Exception ex) {}
surf.start();
add(surf);
}
validate();
repaint();
}
});
}
public class Surface extends JPanel implements Runnable {
public Thread thread;
public long sleepAmount = 1000;
public int usageHistCount = 20000;
private int w, h;
private BufferedImage bimg;
private Graphics2D big;
private Font font = new Font("Times New Roman", Font.PLAIN, 11);
private int columnInc;
private float usedMem[][];
private float usedMemMax[]; // Used when max pool size is undefined
private int ptNum[];
private int ascent, descent;
private Rectangle graphOutlineRect = new Rectangle();
private Rectangle2D mfRect = new Rectangle2D.Float();
private Rectangle2D muRect = new Rectangle2D.Float();
private Line2D graphLine = new Line2D.Float();
private Color graphColor = new Color(46, 139, 87);
private Color mfColor = new Color(0, 100, 0);
private String usedStr;
public Surface() {
setBackground(Color.black);
addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
if (thread == null) start(); else stop();
}
});
usedMem = new float[numPools][];
usedMemMax = new float[numPools];
for (int i = 0; i < numPools; i++) {
usedMemMax[i] = 1024f * 1024f ;
}
ptNum = new int[numPools];
}
@Override
public Dimension getMinimumSize() {
return getPreferredSize();
}
@Override
public Dimension getMaximumSize() {
return getPreferredSize();
}
@Override
public Dimension getPreferredSize() {
return new Dimension(135,80);
}
@Override
public void paint(Graphics g) {
if (big == null) {
return;
}
big.setBackground(getBackground());
big.clearRect(0,0,w,h);
h = h / ((numPools + numPools%2) / 2);
w = w / 2;
int k=0; // index of memory pool.
for (int i=0; i < 2;i++) {
for (int j=0; j < (numPools + numPools%2)/ 2; j++) {
plotMemoryUsage(w*i,h*j,w,h,k);
if (++k >= numPools) {
i = 3;
j = (numPools + numPools%2)/ 2;
break;
}
}
}
g.drawImage(bimg, 0, 0, this);
}
public void plotMemoryUsage(int x1, int y1, int x2, int y2, int npool) {
MemoryPoolMXBean mp = mpools.get(npool);
float usedMemory = mp.getUsage().getUsed();
float totalMemory = mp.getUsage().getMax();
if (totalMemory < 0) { // Max is undefined for this pool
if (usedMemory > usedMemMax[npool]) {
usedMemMax[npool] = usedMemory;
}
totalMemory = usedMemMax[npool];
}
// .. Draw allocated and used strings ..
big.setColor(Color.green);
// Print Max memory allocated for this memory pool.
big.drawString(String.valueOf((int)totalMemory/1024) + "K Max ", x1+4.0f, (float) y1 + ascent+0.5f);
big.setColor(Color.yellow);
// Print the memory pool name.
big.drawString(mp.getName(), x1+x2/2, (float) y1 + ascent+0.5f);
// Print the memory used by this memory pool.
usedStr = String.valueOf((int)usedMemory/1024)
+ "K used";
big.setColor(Color.green);
big.drawString(usedStr, x1+4, y1+y2-descent);
// Calculate remaining size
float ssH = ascent + descent;
float remainingHeight = y2 - (ssH*2) - 0.5f;
float blockHeight = remainingHeight/10;
float blockWidth = 20.0f;
float remainingWidth = x2 - blockWidth - 10;
// .. Memory Free ..
big.setColor(mfColor);
int MemUsage = (int) (((totalMemory - usedMemory) / totalMemory) * 10);
int i = 0;
for ( ; i < MemUsage ; i++) {
mfRect.setRect(x1+5,(float) y1+ssH+i*blockHeight,
blockWidth, blockHeight-1);
big.fill(mfRect);
}
// .. Memory Used ..
big.setColor(Color.green);
for ( ; i < 10; i++) {
muRect.setRect(x1+5,(float) y1 + ssH+i*blockHeight,
blockWidth, blockHeight-1);
big.fill(muRect);
}
// .. Draw History Graph ..
if (remainingWidth <= 30) remainingWidth = (float)30;
if (remainingHeight <= ssH) remainingHeight = ssH;
big.setColor(graphColor);
int graphX = x1+30;
int graphY = y1 + (int) ssH;
int graphW = (int) remainingWidth;
int graphH = (int) remainingHeight;
graphOutlineRect.setRect(graphX, graphY, graphW, graphH);
big.draw(graphOutlineRect);
int graphRow = graphH/10;
// .. Draw row ..
for (int j = graphY; j <= graphH+graphY; j += graphRow) {
graphLine.setLine(graphX,j,graphX+graphW,j);
big.draw(graphLine);
}
// .. Draw animated column movement ..
int graphColumn = graphW/15;
if (columnInc == 0) {
columnInc = graphColumn;
}
for (int j = graphX+columnInc; j < graphW+graphX; j+=graphColumn) {
graphLine.setLine(j,graphY,j,graphY+graphH);
big.draw(graphLine);
}
--columnInc;
// Plot memory usage by this memory pool.
if (usedMem[npool] == null) {
usedMem[npool] = new float[usageHistCount];
ptNum[npool] = 0;
}
// save memory usage history.
usedMem[npool][ptNum[npool]] = usedMemory;
big.setColor(Color.yellow);
int w1; // width of memory usage history.
if (ptNum[npool] > graphW) {
w1 = graphW;
} else {
w1 = ptNum[npool];
}
for (int j=graphX+graphW-w1, k=ptNum[npool]-w1; k < ptNum[npool];
k++, j++) {
if (k != 0) {
if (usedMem[npool][k] != usedMem[npool][k-1]) {
int h1 = (int)(graphY + graphH * ((totalMemory -usedMem[npool][k-1])/totalMemory));
int h2 = (int)(graphY + graphH * ((totalMemory -usedMem[npool][k])/totalMemory));
big.drawLine(j-1, h1, j, h2);
} else {
int h1 = (int)(graphY + graphH * ((totalMemory -usedMem[npool][k])/totalMemory));
big.fillRect(j, h1, 1, 1);
}
}
}
if (ptNum[npool]+2 == usedMem[npool].length) {
// throw out oldest point
for (int j = 1;j < ptNum[npool]; j++) {
usedMem[npool][j-1] = usedMem[npool][j];
}
--ptNum[npool];
} else {
ptNum[npool]++;
}
}
public void start() {
thread = new Thread(this);
thread.setPriority(Thread.MIN_PRIORITY);
thread.setName("MemoryMonitor");
thread.start();
}
public synchronized void stop() {
thread = null;
notify();
}
@Override
public void run() {
Thread me = Thread.currentThread();
while (thread == me && !isShowing() || getSize().width == 0) {
try {
Thread.sleep(500);
} catch (InterruptedException e) { return; }
}
while (thread == me && isShowing()) {
Dimension d = getSize();
if (d.width != w || d.height != h) {
w = d.width;
h = d.height;
bimg = (BufferedImage) createImage(w, h);
big = bimg.createGraphics();
big.setFont(font);
FontMetrics fm = big.getFontMetrics(font);
ascent = fm.getAscent();
descent = fm.getDescent();
}
repaint();
try {
Thread.sleep(sleepAmount);
} catch (InterruptedException e) { break; }
if (MemoryMonitor.dateStampCB.isSelected()) {
System.out.println(new Date().toString() + " " + usedStr);
}
}
thread = null;
}
}
// Test thread to consume memory
static class Memeater extends ClassLoader implements Runnable {
Object y[];
public Memeater() {}
@Override
public void run() {
y = new Object[10000000];
int k =0;
while(true) {
if (k == 5000000) k=0;
y[k++] = new Object();
try {
Thread.sleep(20);
} catch (Exception x){}
// to consume perm gen storage
try {
// the classes are small so we load 10 at a time
for (int i=0; i<10; i++) {
loadNext();
}
} catch (ClassNotFoundException x) {
// ignore exception
}
}
}
Class<?> loadNext() throws ClassNotFoundException {
// public class TestNNNNNN extends java.lang.Object{
// public TestNNNNNN();
// Code:
// 0: aload_0
// 1: invokespecial #1; //Method java/lang/Object."<init>":()V
// 4: return
// }
int begin[] = {
0xca, 0xfe, 0xba, 0xbe, 0x00, 0x00, 0x00, 0x30,
0x00, 0x0a, 0x0a, 0x00, 0x03, 0x00, 0x07, 0x07,
0x00, 0x08, 0x07, 0x00, 0x09, 0x01, 0x00, 0x06,
0x3c, 0x69, 0x6e, 0x69, 0x74, 0x3e, 0x01, 0x00,
0x03, 0x28, 0x29, 0x56, 0x01, 0x00, 0x04, 0x43,
0x6f, 0x64, 0x65, 0x0c, 0x00, 0x04, 0x00, 0x05,
0x01, 0x00, 0x0a, 0x54, 0x65, 0x73, 0x74 };
int end [] = {
0x01, 0x00, 0x10,
0x6a, 0x61, 0x76, 0x61, 0x2f, 0x6c, 0x61, 0x6e,
0x67, 0x2f, 0x4f, 0x62, 0x6a, 0x65, 0x63, 0x74,
0x00, 0x21, 0x00, 0x02, 0x00, 0x03, 0x00, 0x00,
0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x04,
0x00, 0x05, 0x00, 0x01, 0x00, 0x06, 0x00, 0x00,
0x00, 0x11, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00,
0x00, 0x05, 0x2a, 0xb7, 0x00, 0x01, 0xb1, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00 };
// TestNNNNNN
String name = "Test" + Integer.toString(count++);
byte value[];
try {
value = name.substring(4).getBytes("UTF-8");
} catch (java.io.UnsupportedEncodingException x) {
throw new Error();
}
// construct class file
int len = begin.length + value.length + end.length;
byte b[] = new byte[len];
int pos=0;
for (int i: begin) {
b[pos++] = (byte) i;
}
for (byte v: value) {
b[pos++] = v;
}
for (int e: end) {
b[pos++] = (byte) e;
}
return defineClass(name, b, 0, b.length);
}
static int count = 100000;
}
public static void main(String s[]) {
final MemoryMonitor demo = new MemoryMonitor();
WindowListener l = new WindowAdapter() {
@Override
public void windowClosing(WindowEvent e) {System.exit(0);}
@Override
public void windowDeiconified(WindowEvent e) { demo.surf.start(); }
@Override
public void windowIconified(WindowEvent e) { demo.surf.stop(); }
};
JFrame f = new JFrame("MemoryMonitor");
f.addWindowListener(l);
f.getContentPane().add("Center", demo);
f.pack();
f.setSize(new Dimension(400,500));
f.setVisible(true);
demo.surf.start();
Thread thr = new Thread(new Memeater());
thr.start();
}
}

View File

@ -1,48 +0,0 @@
#
# Copyright (c) 2004, 2012, Oracle and/or its affiliates. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# - Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
#
# - Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in the
# documentation and/or other materials provided with the distribution.
#
# - Neither the name of Oracle nor the names of its
# contributors may be used to endorse or promote products derived
# from this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
# IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
# THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#
MemoryMonitor demonstrates the use of the java.lang.management API
in observing the memory usage of all memory pools consumed by
the application.
This simple demo program queries the memory usage of each memory pool
and plots the memory usage history graph.
To run the MemoryMonitor demo
java -jar <JDK_HOME>/demo/management/MemoryMonitor/MemoryMonitor.jar
These instructions assume that this installation's version of the java
command is in your path. If it isn't, then you should either
specify the complete path to the java command or update your
PATH environment variable as described in the installation
instructions for the Java(TM) SDK.

View File

@ -1,153 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
*/
import static java.lang.management.ManagementFactory.*;
import java.lang.management.*;
import javax.management.*;
import java.io.*;
import java.util.*;
/**
* Example of using the java.lang.management API to monitor
* the memory usage and garbage collection statistics.
*
* @author Mandy Chung
*/
public class PrintGCStat {
private RuntimeMXBean rmbean;
private MemoryMXBean mmbean;
private List<MemoryPoolMXBean> pools;
private List<GarbageCollectorMXBean> gcmbeans;
/**
* Constructs a PrintGCStat object to monitor a remote JVM.
*/
public PrintGCStat(MBeanServerConnection server) throws IOException {
// Create the platform mxbean proxies
this.rmbean = newPlatformMXBeanProxy(server,
RUNTIME_MXBEAN_NAME,
RuntimeMXBean.class);
this.mmbean = newPlatformMXBeanProxy(server,
MEMORY_MXBEAN_NAME,
MemoryMXBean.class);
ObjectName poolName = null;
ObjectName gcName = null;
try {
poolName = new ObjectName(MEMORY_POOL_MXBEAN_DOMAIN_TYPE+",*");
gcName = new ObjectName(GARBAGE_COLLECTOR_MXBEAN_DOMAIN_TYPE+",*");
} catch (MalformedObjectNameException e) {
// should not reach here
assert(false);
}
Set<ObjectName> mbeans = server.queryNames(poolName, null);
if (mbeans != null) {
pools = new ArrayList<MemoryPoolMXBean>();
for (ObjectName objName : mbeans) {
MemoryPoolMXBean p =
newPlatformMXBeanProxy(server,
objName.getCanonicalName(),
MemoryPoolMXBean.class);
pools.add(p);
}
}
mbeans = server.queryNames(gcName, null);
if (mbeans != null) {
gcmbeans = new ArrayList<GarbageCollectorMXBean>();
for (ObjectName objName : mbeans) {
GarbageCollectorMXBean gc =
newPlatformMXBeanProxy(server,
objName.getCanonicalName(),
GarbageCollectorMXBean.class);
gcmbeans.add(gc);
}
}
}
/**
* Constructs a PrintGCStat object to monitor the local JVM.
*/
public PrintGCStat() {
// Obtain the platform mxbean instances for the running JVM.
this.rmbean = getRuntimeMXBean();
this.mmbean = getMemoryMXBean();
this.pools = getMemoryPoolMXBeans();
this.gcmbeans = getGarbageCollectorMXBeans();
}
/**
* Prints the verbose GC log to System.out to list the memory usage
* of all memory pools as well as the GC statistics.
*/
public void printVerboseGc() {
System.out.println("Uptime: " + formatMillis(rmbean.getUptime()));
System.out.println("Heap usage: " + mmbean.getHeapMemoryUsage());
System.out.println("Non-Heap memory usage: " + mmbean.getNonHeapMemoryUsage());
for (GarbageCollectorMXBean gc : gcmbeans) {
System.out.print(" [" + gc.getName() + ": ");
System.out.print("Count=" + gc.getCollectionCount());
System.out.print(" GCTime=" + formatMillis(gc.getCollectionTime()));
System.out.print("]");
}
System.out.println();
for (MemoryPoolMXBean p : pools) {
System.out.print(" [" + p.getName() + ":");
MemoryUsage u = p.getUsage();
System.out.print(" Used=" + formatBytes(u.getUsed()));
System.out.print(" Committed=" + formatBytes(u.getCommitted()));
System.out.println("]");
}
}
private String formatMillis(long ms) {
return String.format("%.4fsec", ms / (double) 1000);
}
private String formatBytes(long bytes) {
long kb = bytes;
if (bytes > 0) {
kb = bytes / 1024;
}
return kb + "K";
}
}

View File

@ -1,31 +0,0 @@
VerboseGC demonstrates the use of the java.lang.management API to
print the garbage collection statistics and memory usage remotely
by connecting to a JMX agent with a JMX service URL:
service:jmx:rmi:///jndi/rmi://<hostName>:<portNum>/jmxrmi
where <hostName> is the hostname and <portNum> is the port number
to which the JMX agent will be connected.
To run the VerboseGC demo
(1) Start the application with the JMX agent - here's an example of
how the Java2D is started
java -Dcom.sun.management.jmxremote.port=1090
-Dcom.sun.management.jmxremote.ssl=false
-Dcom.sun.management.jmxremote.authenticate=false
-jar <JDK_HOME>/demo/jfc/Java2D/Java2Demo.jar
This instruction uses the Sun's built-in support to enable a JMX agent.
You can programmatically start a JMX agent with the RMI connector
using javax.management.remote API. See the javadoc and examples for
javax.management.remote API for details.
(2) Run VerboseGC
java -jar <JDK_HOME>/demo/management/VerboseGC/VerboseGC.jar localhost:1090
These instructions assume that this installation's version of the java
command is in your path. If it isn't, then you should either
specify the complete path to the java command or update your
PATH environment variable as described in the installation
instructions for the Java(TM) SDK.

View File

@ -1,158 +0,0 @@
/*
* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
*/
import javax.management.*;
import javax.management.remote.*;
import java.io.IOException;
import java.net.MalformedURLException;
/**
* This VerboseGC class demonstrates the capability to get
* the garbage collection statistics and memory usage remotely.
*/
public class VerboseGC {
private MBeanServerConnection server;
private JMXConnector jmxc;
public VerboseGC(String hostname, int port) {
System.out.println("Connecting to " + hostname + ":" + port);
// Create an RMI connector client and connect it to
// the RMI connector server
String urlPath = "/jndi/rmi://" + hostname + ":" + port + "/jmxrmi";
connect(urlPath);
}
public void dump(long interval, long samples) {
try {
PrintGCStat pstat = new PrintGCStat(server);
for (int i = 0; i < samples; i++) {
pstat.printVerboseGc();
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
System.exit(1);
}
}
} catch (IOException e) {
System.err.println("\nCommunication error: " + e.getMessage());
System.exit(1);
}
}
/**
* Connect to a JMX agent of a given URL.
*/
private void connect(String urlPath) {
try {
JMXServiceURL url = new JMXServiceURL("rmi", "", 0, urlPath);
this.jmxc = JMXConnectorFactory.connect(url);
this.server = jmxc.getMBeanServerConnection();
} catch (MalformedURLException e) {
// should not reach here
} catch (IOException e) {
System.err.println("\nCommunication error: " + e.getMessage());
System.exit(1);
}
}
public static void main(String[] args) {
if (args.length < 1) {
usage();
}
String hostname = "";
int port = -1;
long interval = 5000; // default is 5 second interval
long mins = 5;
for (String arg: args) {
if (arg.startsWith("-")) {
if (arg.equals("-h") ||
arg.equals("-help") ||
arg.equals("-?")) {
usage();
} else if (arg.startsWith("-interval=")) {
try {
interval = Integer.parseInt(arg.substring(10)) * 1000;
} catch (NumberFormatException ex) {
usage();
}
} else if (arg.startsWith("-duration=")) {
try {
mins = Integer.parseInt(arg.substring(10));
} catch (NumberFormatException ex) {
usage();
}
} else {
// Unknown switch
System.err.println("Unrecognized option: " + arg);
usage();
}
} else {
String[] arg2 = arg.split(":");
if (arg2.length != 2) {
usage();
}
hostname = arg2[0];
try {
port = Integer.parseInt(arg2[1]);
} catch (NumberFormatException x) {
usage();
}
if (port < 0) {
usage();
}
}
}
// get full thread dump and perform deadlock detection
VerboseGC vgc = new VerboseGC(hostname, port);
long samples = (mins * 60 * 1000) / interval;
vgc.dump(interval, samples);
}
private static void usage() {
System.out.print("Usage: java VerboseGC <hostname>:<port> ");
System.out.println(" [-interval=seconds] [-duration=minutes]");
}
}

View File

@ -1,46 +0,0 @@
<html>
<head> <title>java.lang.management Demonstration Code</title> </head>
<h1>java.lang.management Demonstration Code</h1>
<ul>
<li>
<A HREF="FullThreadDump">FullThreadDump</A>
<br>
Shows how to get thread dumps and look for deadlocks.
</li>
<li>
<A HREF="VerboseGC">VerboseGC</A>
<br>
Shows how you can find out about Garbage Collection in the VM.
</li>
<li>
<A HREF="MemoryMonitor">MemoryMonitor</A>
<br>
Shows how you can find out the memory usage in the VM.
</li>
<li>
<A HREF="JTop">JTop</A>
<br>
Shows how you can find out the threads with top CPU usage.
</li>
</ul>
<h2>Comments and Feedback</h2>
<p>
Comments regarding java.lang.management API or on any of these
demonstrations should be sent through
<A HREF="http://java.sun.com/mail">http://java.sun.com/mail/</A>
</html>

View File

@ -1,64 +0,0 @@
What is this demo about?
This is "script shell" plugin for jconsole - the monitoring and management
client tool shipped with JRE. This plugin adds "Script Shell" tab to jconsole.
This serves as a demo for jconsole plugin API (com.sun.tools.jconsole) as well
as a demo for scripting API (javax.script) for the Java platform.
Script console is an interactive read-eval-print interface that can be used
used to execute advanced monitoring and management queries. By default,
JavaScript is used as the scripting language. The scripting language can be
changed using the system property com.sun.demo.jconsole.console.language. To
use other scripting languages, you need to specify the corresponding engine
jar file in pluginpath along with this plugin's jar file.
The following 3 global variables are exposed to the script engine:
window javax.swing.JPanel
engine javax.script.ScriptEngine
plugin com.sun.tools.jconsole.JConsolePlugin
If you use JavaScript, there are many useful global functions defined in
./src/resources/jconsole.js. This is built into the script plugin jar file.
In addition, you can add other global functions and global variables by
defining those in ~/jconsole.js (or jconsole.<ext> where <ext> is the file
extension for your scripting language of choice under your home directory).
How do I compile script console plugin?
You can use the Java based build tool "ant" (http://ant.apache.org) to build
this plugin. To build using ant, please use the following command in the
current directory:
ant
How do I use script console plugin?
To start jconsole with this plugin, please use the following command
jconsole -pluginpath jconsole-plugin.jar
How do I load my own script files in script console?
If you use JavaScript (the default), then there is a global function called
"load" to load any script file from your file system. In script console
prompt, enter the following:
load(<script-file-path>);
where <script-file-path> is the path of your script file to load. If you don't
specify the file path, then the load function shows file dialog box to choose
the script file to load.
How do I get help on script global functions?
If you use JavaScript (the default), then there is a global function called
"help" that prints one-line help messages on global functions. In script
console prompt, enter the following:
help();
Where are the sample JavaScript files?
./src/scripts directory contains JavaScript files that can be loaded into
script console.

View File

@ -1,86 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of Oracle nor the names of its
contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-->
<!--
This is ant (http://ant.apache.org) build script to build the jconsole
script console plugin.
-->
<project name="JConsole Script Shell Plugin" default="all" basedir=".">
<!-- property definitions -->
<property name="app.name" value="jconsole-plugin"/>
<property name="src.dir" value="src"/>
<property name="jconsole.jar.dir" value="${java.home}/../lib"/>
<property name="build.dir" value="."/>
<property name="dist.jar" value="${build.dir}/${app.name}.jar"/>
<property name="classes.dir" value="${build.dir}/classes"/>
<property name="resources.dir" value="${classes.dir}/resources"/>
<!-- make directories required -->
<target name="prepare">
<mkdir dir="${classes.dir}"/>
</target>
<target name="clean">
<delete file="${dist.jar}"/>
<delete dir="${classes.dir}"/>
</target>
<!-- we need jconsole.jar in CLASSPATH to build -->
<path id="javac.classpath">
<pathelement path="${jconsole.jar.dir}/jconsole.jar" />
</path>
<target name="compile" depends="prepare" description="compiles the sources">
<javac srcdir="${src.dir}"
destdir="${classes.dir}"
debug="on" deprecation="on">
<classpath refid="javac.classpath" />
</javac>
<copy todir="${classes.dir}/META-INF/services">
<fileset dir="${src.dir}/META-INF/services"/>
</copy>
<copy todir="${resources.dir}">
<fileset dir="${src.dir}/resources"/>
</copy>
</target>
<target name="all" depends="compile" description="buile deployment bundle">
<jar jarfile="${dist.jar}"
basedir="${classes.dir}"/>
</target>
</project>

View File

@ -1 +0,0 @@
com.sun.demo.scripting.jconsole.ScriptJConsolePlugin

View File

@ -1,96 +0,0 @@
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.demo.scripting.jconsole;
import javax.swing.text.*;
/** This class implements a special type of document in which edits
* can only be performed at the end, from "mark" to the end of the
* document. This is used in ScriptShellPanel class as document for editor.
*/
public class EditableAtEndDocument extends PlainDocument {
private static final long serialVersionUID = 5358116444851502167L;
private int mark;
@Override
public void insertString(int offset, String text, AttributeSet a)
throws BadLocationException {
int len = getLength();
super.insertString(len, text, a);
}
@Override
public void remove(int offs, int len) throws BadLocationException {
int start = offs;
int end = offs + len;
int markStart = mark;
int markEnd = getLength();
if ((end < markStart) || (start > markEnd)) {
// no overlap
return;
}
// Determine interval intersection
int cutStart = Math.max(start, markStart);
int cutEnd = Math.min(end, markEnd);
super.remove(cutStart, cutEnd - cutStart);
}
public void setMark() {
mark = getLength();
}
public String getMarkedText() throws BadLocationException {
return getText(mark, getLength() - mark);
}
/** Used to reset the contents of this document */
public void clear() {
try {
super.remove(0, getLength());
setMark();
} catch (BadLocationException e) {
}
}
}

View File

@ -1,224 +0,0 @@
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.demo.scripting.jconsole;
import com.sun.tools.jconsole.*;
import java.io.*;
import java.util.concurrent.CountDownLatch;
import javax.script.*;
import javax.swing.*;
import java.util.*;
/**
* This is script console plugin. This class uses javax.script API to create
* interactive read-eval-print script shell within the jconsole GUI.
*/
public class ScriptJConsolePlugin extends JConsolePlugin
implements ScriptShellPanel.CommandProcessor {
// Panel for our tab
private volatile ScriptShellPanel window;
// Tabs that we add to jconsole GUI
private Map<String, JPanel> tabs;
// Script engine that evaluates scripts
private volatile ScriptEngine engine;
// script engine initialization occurs in background.
// This latch is used to coorrdinate engine init and eval.
private CountDownLatch engineReady = new CountDownLatch(1);
// File extension used for scripts of chosen language.
// For eg. ".js" for JavaScript, ".bsh" for BeanShell.
private String extension;
// Prompt to print in the read-eval-print loop. This is
// derived from the script file extension.
private volatile String prompt;
/**
* Constructor to create this plugin
*/
public ScriptJConsolePlugin() {
}
@Override public Map<String, JPanel> getTabs() {
// create ScriptEngine
createScriptEngine();
// create panel for tab
window = new ScriptShellPanel(this);
// add tab to tabs map
tabs = new HashMap<String, JPanel>();
tabs.put("Script Shell", window);
new Thread(new Runnable() {
@Override
public void run() {
// initialize the script engine
initScriptEngine();
engineReady.countDown();
}
}).start();
return tabs;
}
@Override public SwingWorker<?,?> newSwingWorker() {
return null;
}
@Override public void dispose() {
window.dispose();
}
@Override
public String getPrompt() {
return prompt;
}
@Override
public String executeCommand(String cmd) {
String res;
try {
engineReady.await();
Object tmp = engine.eval(cmd);
res = (tmp == null)? null : tmp.toString();
} catch (InterruptedException ie) {
res = ie.getMessage();
} catch (ScriptException se) {
res = se.getMessage();
}
return res;
}
//-- Internals only below this point
private void createScriptEngine() {
ScriptEngineManager manager = new ScriptEngineManager();
String language = getScriptLanguage();
engine = manager.getEngineByName(language);
if (engine == null) {
throw new RuntimeException("cannot load " + language + " engine");
}
extension = engine.getFactory().getExtensions().get(0);
prompt = extension + ">";
engine.setBindings(createBindings(), ScriptContext.ENGINE_SCOPE);
}
// Name of the System property used to select scripting language
private static final String LANGUAGE_KEY = "com.sun.demo.jconsole.console.language";
private String getScriptLanguage() {
// check whether explicit System property is set
String lang = System.getProperty(LANGUAGE_KEY);
if (lang == null) {
// default is JavaScript
lang = "JavaScript";
}
return lang;
}
// create Bindings that is backed by a synchronized HashMap
private Bindings createBindings() {
Map<String, Object> map =
Collections.synchronizedMap(new HashMap<String, Object>());
return new SimpleBindings(map);
}
// create and initialize script engine
private void initScriptEngine() {
// set pre-defined global variables
setGlobals();
// load pre-defined initialization file
loadInitFile();
// load current user's initialization file
loadUserInitFile();
}
// set pre-defined global variables for script
private void setGlobals() {
engine.put("engine", engine);
engine.put("window", window);
engine.put("plugin", this);
}
// load initial script file (jconsole.<extension>)
private void loadInitFile() {
String oldFilename = (String) engine.get(ScriptEngine.FILENAME);
engine.put(ScriptEngine.FILENAME, "<built-in jconsole." + extension + ">");
try {
Class<? extends ScriptJConsolePlugin> myClass = this.getClass();
InputStream stream = myClass.getResourceAsStream("/resources/jconsole." +
extension);
if (stream != null) {
engine.eval(new InputStreamReader(new BufferedInputStream(stream)));
}
} catch (Exception exp) {
exp.printStackTrace();
// FIXME: What else I can do here??
} finally {
engine.put(ScriptEngine.FILENAME, oldFilename);
}
}
// load user's initial script file (~/jconsole.<extension>)
private void loadUserInitFile() {
String oldFilename = (String) engine.get(ScriptEngine.FILENAME);
String home = System.getProperty("user.home");
if (home == null) {
// no user.home?? should not happen??
return;
}
String fileName = home + File.separator + "jconsole." + extension;
if (! (new File(fileName).exists())) {
// user does not have ~/jconsole.<extension>
return;
}
engine.put(ScriptEngine.FILENAME, fileName);
try {
engine.eval(new FileReader(fileName));
} catch (Exception exp) {
exp.printStackTrace();
// FIXME: What else I can do here??
} finally {
engine.put(ScriptEngine.FILENAME, oldFilename);
}
}
}

View File

@ -1,263 +0,0 @@
/*
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
package com.sun.demo.scripting.jconsole;
import java.awt.*;
import java.awt.event.*;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.text.*;
/**
* A JPanel subclass containing a scrollable text area displaying the
* jconsole's script console.
*/
public class ScriptShellPanel extends JPanel {
private static final long serialVersionUID = 4116273141148726319L;
// interface to evaluate script command and script prompt
interface CommandProcessor {
// execute given String as script and return the result
public String executeCommand(String cmd);
// get prompt used for interactive read-eval-loop
public String getPrompt();
}
// my script command processor
private CommandProcessor commandProcessor;
// editor component for command editing
private JTextComponent editor;
private final ExecutorService commandExecutor =
Executors.newSingleThreadExecutor();
// document management
private boolean updating;
public ScriptShellPanel(CommandProcessor cmdProc) {
setLayout(new BorderLayout());
this.commandProcessor = cmdProc;
this.editor = new JTextArea();
editor.setDocument(new EditableAtEndDocument());
JScrollPane scroller = new JScrollPane();
scroller.getViewport().add(editor);
add(scroller, BorderLayout.CENTER);
editor.getDocument().addDocumentListener(new DocumentListener() {
@Override
public void changedUpdate(DocumentEvent e) {
}
@Override
public void insertUpdate(DocumentEvent e) {
if (updating) return;
beginUpdate();
editor.setCaretPosition(editor.getDocument().getLength());
if (insertContains(e, '\n')) {
String cmd = getMarkedText();
// Handle multi-line input
if ((cmd.length() == 0) ||
(cmd.charAt(cmd.length() - 1) != '\\')) {
// Trim "\\n" combinations
final String cmd1 = trimContinuations(cmd);
commandExecutor.execute(new Runnable() {
@Override
public void run() {
final String result = executeCommand(cmd1);
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
if (result != null) {
print(result + "\n");
}
printPrompt();
setMark();
endUpdate();
}
});
}
});
} else {
endUpdate();
}
} else {
endUpdate();
}
}
@Override
public void removeUpdate(DocumentEvent e) {
}
});
// This is a bit of a hack but is probably better than relying on
// the JEditorPane to update the caret's position precisely the
// size of the insertion
editor.addCaretListener(new CaretListener() {
@Override
public void caretUpdate(CaretEvent e) {
int len = editor.getDocument().getLength();
if (e.getDot() > len) {
editor.setCaretPosition(len);
}
}
});
Box hbox = Box.createHorizontalBox();
hbox.add(Box.createGlue());
JButton button = new JButton("Clear"); // FIXME: i18n?
button.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
clear();
}
});
hbox.add(button);
hbox.add(Box.createGlue());
add(hbox, BorderLayout.SOUTH);
clear();
}
public void dispose() {
commandExecutor.shutdown();
}
@Override
public void requestFocus() {
editor.requestFocus();
}
public void clear() {
clear(true);
}
public void clear(boolean prompt) {
EditableAtEndDocument d = (EditableAtEndDocument) editor.getDocument();
d.clear();
if (prompt) printPrompt();
setMark();
editor.requestFocus();
}
public void setMark() {
((EditableAtEndDocument) editor.getDocument()).setMark();
}
public String getMarkedText() {
try {
String s = ((EditableAtEndDocument) editor.getDocument()).getMarkedText();
int i = s.length();
while ((i > 0) && (s.charAt(i - 1) == '\n')) {
i--;
}
return s.substring(0, i);
} catch (BadLocationException e) {
e.printStackTrace();
return null;
}
}
public void print(String s) {
Document d = editor.getDocument();
try {
d.insertString(d.getLength(), s, null);
} catch (BadLocationException e) {
e.printStackTrace();
}
}
//
// Internals only below this point
//
private String executeCommand(String cmd) {
return commandProcessor.executeCommand(cmd);
}
private String getPrompt() {
return commandProcessor.getPrompt();
}
private void beginUpdate() {
editor.setEditable(false);
updating = true;
}
private void endUpdate() {
editor.setEditable(true);
updating = false;
}
private void printPrompt() {
print(getPrompt());
}
private boolean insertContains(DocumentEvent e, char c) {
String s = null;
try {
s = editor.getText(e.getOffset(), e.getLength());
for (int i = 0; i < e.getLength(); i++) {
if (s.charAt(i) == c) {
return true;
}
}
} catch (BadLocationException ex) {
ex.printStackTrace();
}
return false;
}
private String trimContinuations(String text) {
int i;
while ((i = text.indexOf("\\\n")) >= 0) {
text = text.substring(0, i) + text.substring(i+1, text.length());
}
return text;
}
}

View File

@ -1,891 +0,0 @@
/*
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* -Redistribution of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* -Redistribution in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of Oracle nor the names of contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* This software is provided "AS IS," without a warranty of any kind. ALL
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES, INCLUDING
* ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE
* OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN MIDROSYSTEMS, INC. ("SUN")
* AND ITS LICENSORS SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY LICENSEE
* AS A RESULT OF USING, MODIFYING OR DISTRIBUTING THIS SOFTWARE OR ITS
* DERIVATIVES. IN NO EVENT WILL SUN OR ITS LICENSORS BE LIABLE FOR ANY LOST
* REVENUE, PROFIT OR DATA, OR FOR DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL,
* INCIDENTAL OR PUNITIVE DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY
* OF LIABILITY, ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE,
* EVEN IF SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
*
* You acknowledge that this software is not designed, licensed or intended
* for use in the design, construction, operation or maintenance of any
* nuclear facility.
*/
// This function depends on the pre-defined variable
// "plugin" of type com.sun.tools.jconsole.JConsolePlugin
function jcontext() {
return plugin.getContext();
}
jcontext.docString = "returns JConsoleContext for the current jconsole plugin";
function mbeanConnection() {
return jcontext().getMBeanServerConnection();
}
mbeanConnection.docString = "returns current MBeanServer connection";
// check if there is a build in sync function, define one if missing
if (typeof sync === "undefined") {
var sync = function(func, obj) {
if (arguments.length < 1 || arguments.length > 2 ) {
throw "sync(function [,object]) parameter count mismatch";
}
var syncobj = (arguments.length == 2 ? obj : this);
if (!syncobj._syncLock) {
syncobj._syncLock = new Lock();
}
return function() {
syncobj._syncLock.lock();
try {
func.apply(null, arguments);
} finally {
syncobj._syncLock.unlock();
}
};
};
sync.docString = "synchronize a function, optionally on an object";
}
/**
* Prints one liner help message for each function exposed here
* Note that this function depends on docString meta-data for
* each function
*/
function help() {
var i;
for (i in this) {
var func = this[i];
if (typeof(func) == "function" &&
("docString" in func)) {
echo(i + " - " + func["docString"]);
}
}
}
help.docString = "prints help message for global functions";
function connectionState() {
return jcontext().connectionState;
}
connectionState.docString = "return connection state of the current jcontext";
/**
* Returns a platform MXBean proxy for given MXBean name and interface class
*/
function newPlatformMXBeanProxy(name, intf) {
var factory = java.lang.management.ManagementFactory;
return factory.newPlatformMXBeanProxy(mbeanConnection(), name, intf);
}
newPlatformMXBeanProxy.docString = "returns a proxy for a platform MXBean";
/**
* Wraps a string to ObjectName if needed.
*/
function objectName(objName) {
var ObjectName = Packages.javax.management.ObjectName;
if (objName instanceof ObjectName) {
return objName;
} else {
return new ObjectName(objName);
}
}
objectName.docString = "creates JMX ObjectName for a given String";
/**
* Creates a new (M&M) Attribute object
*
* @param name name of the attribute
* @param value value of the attribute
*/
function attribute(name, value) {
var Attribute = Packages.javax.management.Attribute;
return new Attribute(name, value);
}
attribute.docString = "returns a new JMX Attribute using name and value given";
/**
* Returns MBeanInfo for given ObjectName. Strings are accepted.
*/
function mbeanInfo(objName) {
objName = objectName(objName);
return mbeanConnection().getMBeanInfo(objName);
}
mbeanInfo.docString = "returns MBeanInfo of a given ObjectName";
/**
* Returns ObjectInstance for a given ObjectName.
*/
function objectInstance(objName) {
objName = objectName(objName);
return mbeanConnection().objectInstance(objectName);
}
objectInstance.docString = "returns ObjectInstance for a given ObjectName";
/**
* Queries with given ObjectName and QueryExp.
* QueryExp may be null.
*
* @return set of ObjectNames.
*/
function queryNames(objName, query) {
objName = objectName(objName);
if (query == undefined) query = null;
return mbeanConnection().queryNames(objName, query);
}
queryNames.docString = "returns QueryNames using given ObjectName and optional query";
/**
* Queries with given ObjectName and QueryExp.
* QueryExp may be null.
*
* @return set of ObjectInstances.
*/
function queryMBeans(objName, query) {
objName = objectName(objName);
if (query == undefined) query = null;
return mbeanConnection().queryMBeans(objName, query);
}
queryMBeans.docString = "return MBeans using given ObjectName and optional query";
// wraps a script array as java.lang.Object[]
function objectArray(array) {
return Java.to(array, "java.lang.Object[]");
}
// wraps a script (string) array as java.lang.String[]
function stringArray(array) {
return Java.to(array, "java.lang.String[]");
}
// script array to Java List
function toAttrList(array) {
var AttributeList = Packages.javax.management.AttributeList;
if (array instanceof AttributeList) {
return array;
}
var list = new AttributeList(array.length);
for (var index = 0; index < array.length; index++) {
list.add(array[index]);
}
return list;
}
// Java Collection (Iterable) to script array
function toArray(collection) {
if (collection instanceof Array) {
return collection;
}
var itr = collection.iterator();
var array = new Array();
while (itr.hasNext()) {
array[array.length] = itr.next();
}
return array;
}
// gets MBean attributes
function getMBeanAttributes(objName, attributeNames) {
objName = objectName(objName);
return mbeanConnection().getAttributes(objName,stringArray(attributeNames));
}
getMBeanAttributes.docString = "returns specified Attributes of given ObjectName";
// gets MBean attribute
function getMBeanAttribute(objName, attrName) {
objName = objectName(objName);
return mbeanConnection().getAttribute(objName, attrName);
}
getMBeanAttribute.docString = "returns a single Attribute of given ObjectName";
// sets MBean attributes
function setMBeanAttributes(objName, attrList) {
objName = objectName(objName);
attrList = toAttrList(attrList);
return mbeanConnection().setAttributes(objName, attrList);
}
setMBeanAttributes.docString = "sets specified Attributes of given ObjectName";
// sets MBean attribute
function setMBeanAttribute(objName, attrName, attrValue) {
var Attribute = Packages.javax.management.Attribute;
objName = objectName(objName);
mbeanConnection().setAttribute(objName, new Attribute(attrName, attrValue));
}
setMBeanAttribute.docString = "sets a single Attribute of given ObjectName";
// invokes an operation on given MBean
function invokeMBean(objName, operation, params, signature) {
objName = objectName(objName);
params = objectArray(params);
signature = stringArray(signature);
return mbeanConnection().invoke(objName, operation, params, signature);
}
invokeMBean.docString = "invokes MBean operation on given ObjectName";
/**
* Wraps a MBean specified by ObjectName as a convenient
* script object -- so that setting/getting MBean attributes
* and invoking MBean method can be done with natural syntax.
*
* @param objName ObjectName of the MBean
* @param async asynchornous mode [optional, default is false]
* @return script wrapper for MBean
*
* With async mode, all field, operation access is async. Results
* will be of type FutureTask. When you need value, call 'get' on it.
*/
function mbean(objName, async) {
var index;
objName = objectName(objName);
var info = mbeanInfo(objName);
var attrs = info.attributes;
var attrMap = new Object;
for (index in attrs) {
attrMap[attrs[index].name] = attrs[index];
}
var opers = info.operations;
var operMap = new Object;
for (index in opers) {
operMap[opers[index].name] = opers[index];
}
function isAttribute(name) {
return name in attrMap;
}
function isOperation(name) {
return name in operMap;
}
return new JSAdapter() {
__has__: function (name) {
return isAttribute(name) || isOperation(name);
},
__get__: function (name) {
if (isAttribute(name)) {
if (async) {
return getMBeanAttribute.future(objName, name);
} else {
return getMBeanAttribute(objName, name);
}
} else {
return undefined;
}
},
__call__: function(name) {
if (isOperation(name)) {
var oper = operMap[name];
var params = [];
for (var j = 1; j < arguments.length; j++) {
params[j-1]= arguments[j];
}
var sigs = oper.signature;
var sigNames = new Array(sigs.length);
for (var index in sigs) {
sigNames[index] = sigs[index].getType();
}
if (async) {
return invokeMBean.future(objName, name, params, sigNames);
} else {
return invokeMBean(objName, name, params, sigNames);
}
} else {
return undefined;
}
},
__put__: function (name, value) {
if (isAttribute(name)) {
if (async) {
setMBeanAttribute.future(objName, name, value);
} else {
setMBeanAttribute(objName, name, value);
}
} else {
return undefined;
}
}
};
}
mbean.docString = "returns a conveninent script wrapper for a MBean of given ObjectName";
/**
* load and evaluate script file. If no script file is
* specified, file dialog is shown to choose the script.
*
* @param file script file name [optional]
* @return value returned from evaluating script
*/
function load(file) {
if (file == undefined || file == null) {
// file not specified, show file dialog to choose
file = fileDialog();
}
if (file == null) return;
var reader = new java.io.FileReader(file);
var oldFilename = engine.get(engine.FILENAME);
engine.put(engine.FILENAME, file);
try {
engine.eval(reader);
} finally {
engine.put(engine.FILENAME, oldFilename);
}
reader.close();
}
load.docString = "loads a script file and evaluates it";
/**
* Concurrency utilities for JavaScript. These are based on
* java.lang and java.util.concurrent API. The following functions
* provide a simpler API for scripts. Instead of directly using java.lang
* and java.util.concurrent classes, scripts can use functions and
* objects exported from here.
*/
/**
* Wrapper for java.lang.Object.wait
*
* can be called only within a sync method
*/
function wait(object) {
var objClazz = java.lang.Class.forName('java.lang.Object');
var waitMethod = objClazz.getMethod('wait', null);
waitMethod.invoke(object, null);
}
wait.docString = "convenient wrapper for java.lang.Object.wait method";
/**
* Wrapper for java.lang.Object.notify
*
* can be called only within a sync method
*/
function notify(object) {
var objClazz = java.lang.Class.forName('java.lang.Object');
var notifyMethod = objClazz.getMethod('notify', null);
notifyMethod.invoke(object, null);
}
notify.docString = "convenient wrapper for java.lang.Object.notify method";
/**
* Wrapper for java.lang.Object.notifyAll
*
* can be called only within a sync method
*/
function notifyAll(object) {
var objClazz = java.lang.Class.forName('java.lang.Object');
var notifyAllMethod = objClazz.getMethod('notifyAll', null);
notifyAllMethod.invoke(object, null);
}
notifyAll.docString = "convenient wrapper for java.lang.Object.notifyAll method";
/**
* Creates a java.lang.Runnable from a given script
* function.
*/
Function.prototype.runnable = function() {
var args = arguments;
var func = this;
return new java.lang.Runnable() {
run: function() {
func.apply(null, args);
}
}
}
/**
* Executes the function on a new Java Thread.
*/
Function.prototype.thread = function() {
var t = new java.lang.Thread(this.runnable.apply(this, arguments));
t.start();
return t;
}
/**
* Executes the function on a new Java daemon Thread.
*/
Function.prototype.daemon = function() {
var t = new java.lang.Thread(this.runnable.apply(this, arguments));
t.setDaemon(true);
t.start();
return t;
}
/**
* Creates a java.util.concurrent.Callable from a given script
* function.
*/
Function.prototype.callable = function() {
var args = arguments;
var func = this;
return new java.util.concurrent.Callable() {
call: function() { return func.apply(null, args); }
}
}
/**
* Registers the script function so that it will be called exit.
*/
Function.prototype.atexit = function () {
var args = arguments;
java.lang.Runtime.getRuntime().addShutdownHook(
new java.lang.Thread(this.runnable.apply(this, args)));
}
/**
* Executes the function asynchronously.
*
* @return a java.util.concurrent.FutureTask
*/
Function.prototype.future = (function() {
// default executor for future
var juc = java.util.concurrent;
var theExecutor = juc.Executors.newSingleThreadExecutor();
// clean-up the default executor at exit
(function() { theExecutor.shutdown(); }).atexit();
return function() {
return theExecutor.submit(this.callable.apply(this, arguments));
}
})();
// shortcut for j.u.c lock classes
var Lock = java.util.concurrent.locks.ReentrantLock;
var RWLock = java.util.concurrent.locks.ReentrantReadWriteLock;
/**
* Executes a function after acquiring given lock. On return,
* (normal or exceptional), lock is released.
*
* @param lock lock that is locked and unlocked
*/
Function.prototype.sync = function (lock) {
if (arguments.length == 0) {
throw "lock is missing";
}
var res = new Array(arguments.length - 1);
for (var i = 0; i < res.length; i++) {
res[i] = arguments[i + 1];
}
lock.lock();
try {
this.apply(null, res);
} finally {
lock.unlock();
}
};
/**
* Causes current thread to sleep for specified
* number of milliseconds
*
* @param interval in milliseconds
*/
function sleep(interval) {
java.lang.Thread.sleep(interval);
}
sleep.docString = "wrapper for java.lang.Thread.sleep method";
/**
* Schedules a task to be executed once in N milliseconds specified.
*
* @param callback function or expression to evaluate
* @param interval in milliseconds to sleep
* @return timeout ID (which is nothing but Thread instance)
*/
function setTimeout(callback, interval) {
if (! (callback instanceof Function)) {
callback = new Function(callback);
}
// start a new thread that sleeps given time
// and calls callback in an infinite loop
return (function() {
try {
sleep(interval);
} catch (x) { }
callback();
}).daemon();
}
setTimeout.docString = "calls given callback once after specified interval";
/**
* Cancels a timeout set earlier.
* @param tid timeout ID returned from setTimeout
*/
function clearTimeout(tid) {
// we just interrupt the timer thread
tid.interrupt();
}
clearTimeout.docString = "interrupt a setTimeout timer";
/**
* Schedules a task to be executed once in
* every N milliseconds specified.
*
* @param callback function or expression to evaluate
* @param interval in milliseconds to sleep
* @return timeout ID (which is nothing but Thread instance)
*/
function setInterval(callback, interval) {
if (! (callback instanceof Function)) {
callback = new Function(callback);
}
// start a new thread that sleeps given time
// and calls callback in an infinite loop
return (function() {
while (true) {
try {
sleep(interval);
} catch (x) {
break;
}
callback();
}
}).daemon();
}
setInterval.docString = "calls given callback every specified interval";
/**
* Cancels a timeout set earlier.
* @param tid timeout ID returned from setTimeout
*/
function clearInterval(tid) {
// we just interrupt the timer thread
tid.interrupt();
}
clearInterval.docString = "interrupt a setInterval timer";
/**
* Simple access to thread local storage.
*
* Script sample:
*
* __thread.x = 44;
* function f() {
* __thread.x = 'hello';
* print(__thread.x);
* }
* f.thread(); // prints 'hello'
* print(__thread.x); // prints 44 in main thread
*/
var __thread = (function () {
var map = new Object();
return new JSAdapter() {
__has__: function(name) {
return map[name] != undefined;
},
__get__: function(name) {
if (map[name] != undefined) {
return map[name].get();
} else {
return undefined;
}
},
__put__: sync(function(name, value) {
if (map[name] == undefined) {
var tmp = new java.lang.ThreadLocal();
tmp.set(value);
map[name] = tmp;
} else {
map[name].set(value);
}
}),
__delete__: function(name) {
if (map[name] != undefined) {
map[name].set(null);
}
}
}
})();
// user interface utilities
/**
* Swing invokeLater - invokes given function in AWT event thread
*/
Function.prototype.invokeLater = function() {
var SwingUtilities = Packages.javax.swing.SwingUtilities;
SwingUtilities.invokeLater(this.runnable.apply(this, arguments));
}
/**
* Swing invokeAndWait - invokes given function in AWT event thread
* and waits for it's completion
*/
Function.prototype.invokeAndWait = function() {
var SwingUtilities = Packages.javax.swing.SwingUtilities;
SwingUtilities.invokeAndWait(this.runnable.apply(this, arguments));
}
/**
* Am I running in AWT event dispatcher thread?
*/
function isEventThread() {
var SwingUtilities = Packages.javax.swing.SwingUtilities;
return SwingUtilities.isEventDispatchThread();
}
isEventThread.docString = "returns whether the current thread is GUI thread";
/**
* Opens a file dialog box
*
* @param curDir current directory [optional]
* @return absolute path if file selected or else null
*/
function fileDialog(curDir) {
var result;
function _fileDialog() {
if (curDir == undefined) curDir = undefined;
var JFileChooser = Packages.javax.swing.JFileChooser;
var dialog = new JFileChooser(curDir);
var res = dialog.showOpenDialog(null);
if (res == JFileChooser.APPROVE_OPTION) {
result = dialog.getSelectedFile().getAbsolutePath();
} else {
result = null;
}
}
if (isEventThread()) {
_fileDialog();
} else {
_fileDialog.invokeAndWait();
}
return result;
}
fileDialog.docString = "show a FileOpen dialog box";
/**
* Shows a message box
*
* @param msg message to be shown
* @param title title of message box [optional]
* @param msgType type of message box [constants in JOptionPane]
*/
function msgBox(msg, title, msgType) {
function _msgBox() {
var JOptionPane = Packages.javax.swing.JOptionPane;
if (msg === undefined) msg = "undefined";
if (msg === null) msg = "null";
if (title == undefined) title = msg;
if (msgType == undefined) msgType = JOptionPane.INFORMATION_MESSAGE;
JOptionPane.showMessageDialog(window, msg, title, msgType);
}
if (isEventThread()) {
_msgBox();
} else {
_msgBox.invokeAndWait();
}
}
msgBox.docString = "shows MessageBox to the user";
/**
* Shows an information alert box
*
* @param msg message to be shown
* @param title title of message box [optional]
*/
function alert(msg, title) {
var JOptionPane = Packages.javax.swing.JOptionPane;
msgBox(msg, title, JOptionPane.INFORMATION_MESSAGE);
}
alert.docString = "shows an alert message box to the user";
/**
* Shows an error alert box
*
* @param msg message to be shown
* @param title title of message box [optional]
*/
function error(msg, title) {
var JOptionPane = Packages.javax.swing.JOptionPane;
msgBox(msg, title, JOptionPane.ERROR_MESSAGE);
}
error.docString = "shows an error message box to the user";
/**
* Shows a warning alert box
*
* @param msg message to be shown
* @param title title of message box [optional]
*/
function warn(msg, title) {
var JOptionPane = Packages.javax.swing.JOptionPane;
msgBox(msg, title, JOptionPane.WARNING_MESSAGE);
}
warn.docString = "shows a warning message box to the user";
/**
* Shows a prompt dialog box
*
* @param question question to be asked
* @param answer default answer suggested [optional]
* @return answer given by user
*/
function prompt(question, answer) {
var result;
function _prompt() {
var JOptionPane = Packages.javax.swing.JOptionPane;
if (answer == undefined) answer = "";
result = JOptionPane.showInputDialog(window, question, answer);
}
if (isEventThread()) {
_prompt();
} else {
_prompt.invokeAndWait();
}
return result;
}
prompt.docString = "shows a prompt box to the user and returns the answer";
/**
* Shows a confirmation dialog box
*
* @param msg message to be shown
* @param title title of message box [optional]
* @return boolean (yes->true, no->false)
*/
function confirm(msg, title) {
var result;
var JOptionPane = Packages.javax.swing.JOptionPane;
function _confirm() {
if (title == undefined) title = msg;
var optionType = JOptionPane.YES_NO_OPTION;
result = JOptionPane.showConfirmDialog(null, msg, title, optionType);
}
if (isEventThread()) {
_confirm();
} else {
_confirm.invokeAndWait();
}
return result == JOptionPane.YES_OPTION;
}
confirm.docString = "shows a confirmation message box to the user";
/**
* Echoes zero or more arguments supplied to screen.
* This is print equivalent for GUI.
*
* @param zero or more items to echo.
*/
function echo() {
var args = arguments;
(function() {
var len = args.length;
for (var i = 0; i < len; i++) {
window.print(args[i]);
window.print(" ");
}
window.print("\n");
}).invokeLater();
}
echo.docString = "echoes arguments to interactive console screen";
/**
* Clear the screen
*/
function clear() {
(function() { window.clear(false); }).invokeLater();
}
clear.docString = "clears interactive console screen";
// synonym for clear
var cls = clear;
/**
* Exit the process after confirmation from user
*
* @param exitCode return code to OS [optional]
*/
function exit(exitCode) {
if (exitCode == undefined) exitCode = 0;
if (confirm("Do you really want to exit?")) {
java.lang.System.exit(exitCode);
}
}
exit.docString = "exits jconsole";
// synonym to exit
var quit = exit;

View File

@ -1,77 +0,0 @@
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
* This file defines heapdump function to heap dump
* in binary format. User can call this function
* based on events. For example, a timer thread can
* keep checking heap threshold and depending on
* specific expected threshold value, it can call
* heapdump to dump the keep. File name can contain
* timestamp so that multiple heapdumps can be generated
* for the same process.
*/
/**
* Function to dump heap in binary format.
*
* @param file heap dump file name [optional]
*/
function heapdump(file) {
// no file specified, show file open dialog
if (file == undefined) {
file = fileDialog();
// check whether user cancelled the dialog
if (file == null) return;
}
/*
* Get HotSpotDiagnostic MBean and wrap it as convenient
* script wrapper using 'mbean' function. Instead of using
* MBean proxies 'mbean' function creates a script wrapper
* that provides similar convenience but uses explicit
* invocation behind the scene. This implies that mbean
* wrapper would the same for dynamic MBeans as well.
*/
var diagBean = mbean("com.sun.management:type=HotSpotDiagnostic");
// dump the heap in the file
diagBean.dumpHeap(file, true);
}

View File

@ -1,46 +0,0 @@
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
* This is sample JavaScript file that can be loaded into script console.
* This file prints "hello, world".
*/
echo("hello, world");

View File

@ -1,58 +0,0 @@
/*
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
* This script demonstrates "invokeMBean" function. Instead
* of using MXBean proxy or script wrapper object returned by
* 'mbean' function, this file uses direct invoke on MBean.
*
* To use this particular script, load this script file in
* script console prompt and call resetPeakThreadCount().
*/
/**
* Resets the peak thread count to the current number of live threads.
*
*/
function resetPeakThreadCount() {
return invokeMBean("java.lang:type=Threading", "resetPeakThreadCount", [], {});
}

View File

@ -1,98 +0,0 @@
/*
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
* This file defines 'jstack' function to print stack traces of
* threads.'jstack' function which can be called once or periodically
* from a timer thread (calling it periodically would slow down the target
* application). To call this once, just call 'jstack()' in script
* console prompt. To call jstack in a timer thread, you can use
*
* var t = setInterval(function () { jstack(print); }, 5000);
*
* The above call prints threads in sorted order for every 5 seconds.
* The print output goes to OS console window from which jconsole was
* started. The timer can be cancelled later by clearTimeout() function
* as shown below:
*
* clearInterval(t);
*/
/**
* print given ThreadInfo using given printFunc
*/
function printThreadInfo(ti, printFunc) {
printFunc(ti.threadId + " - " + ti.threadName + " - " + ti.threadState);
var stackTrace = ti.stackTrace;
for (var i in stackTrace) {
printFunc("\t" + stackTrace[i]);
}
}
/**
* print stack traces of all threads.
*
* @param printFunc function called to print [optional]
* @param maxFrames maximum number of frames to print [optional]
*/
function jstack(printFunc, maxFrames) {
// by default use 'echo' to print. Other choices could be
// 'print' or custom function that writes in a text file
if (printFunc == undefined) {
printFunc = echo;
}
// by default print 25 frames
if (maxFrames == undefined) {
maxFrames = 25;
}
var tmbean = newPlatformMXBeanProxy(
"java.lang:type=Threading",
java.lang.management.ThreadMXBean.class);
var tids = tmbean.allThreadIds;
var tinfos = tmbean["getThreadInfo(long[],int)"](tids, maxFrames);
for (var i in tinfos) {
printThreadInfo(tinfos[i], printFunc);
}
}

View File

@ -1,113 +0,0 @@
/*
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
* This code is "ported" from JTop demo. This file defines
* 'jtop' function. jtop prints threads sorting by CPU time.
* jtop can be called once or periodically from a timer thread.
* To call this once, just call 'jtop()' in script console prompt.
* To call jtop in a timer thread, you can use
*
* var t = setInterval(function () { jtop(print); }, 2000);
*
* The above call prints threads in sorted order for every 2 seconds.
* The print output goes to OS console window from which jconsole was
* started. The timer can be cancelled later by clearTimeout() function
* as shown below:
*
* clearInterval(t);
*/
/**
* This function returns a List of Map.Entry objects
* in which each entry maps cpu time to ThreadInfo.
*/
function getThreadList() {
var tmbean = newPlatformMXBeanProxy(
"java.lang:type=Threading",
java.lang.management.ThreadMXBean.class);
if (!tmbean.isThreadCpuTimeSupported()) {
return java.util.Collections.EMPTY_LIST;
}
tmbean.setThreadCpuTimeEnabled(true);
var tids = tmbean.allThreadIds;
var tinfos = tmbean["getThreadInfo(long[])"](tids);
var map = new java.util.TreeMap();
for (var i in tids) {
var cpuTime = tmbean.getThreadCpuTime(tids[i]);
if (cpuTime != -1 && tinfos[i] != null) {
map.put(cpuTime, tinfos[i]);
}
}
var list = new java.util.ArrayList(map.entrySet());
java.util.Collections.reverse(list);
return list;
}
/**
* This function prints threads sorted by CPU time.
*
* @param printFunc function called back to print [optional]
*
* By default, it uses 'echo' function to print in screen.
* Other choices could be 'print' (prints in console), 'alert'
* to show message box. Or you can define a function that writes
* the output to a text file.
*/
function jtop(printFunc) {
if (printFunc == undefined) {
printFunc = echo;
}
var list = getThreadList();
var itr = list.iterator();
printFunc("time - state - name");
while (itr.hasNext()) {
var entry = itr.next();
// time is in nanoseconds - convert to seconds
var time = entry.key / 1.0e9;
var name = entry.value.threadName;
var state = entry.value.threadState;
printFunc(time + " - " + state + " - " + name);
}
}

View File

@ -1,88 +0,0 @@
/*
* Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
* This file defines 'sysprops' function to print Java System
* properties.'sysprops' function which can be called once or periodically
* from a timer thread (calling it periodically would slow down the target
* application). To call this once, just call 'sysprops()' in script
* console prompt. To call sysprops in a timer thread, you can use
*
* var t = setInterval(function () { sysprops(print); }, 5000);
*
* The above call prints threads in sorted order for every 5 seconds.
* The print output goes to OS console window from which jconsole was
* started. The timer can be cancelled later by clearTimeout() function
* as shown below:
*
* clearInterval(t);
*/
/**
* Returns System properties as a Map
*/
function getSystemProps() {
var runtimeBean = newPlatformMXBeanProxy(
"java.lang:type=Runtime",
java.lang.management.RuntimeMXBean.class);
return runtimeBean.systemProperties;
}
/**
* print System properties
*
* @param printFunc function called to print [optional]
*/
function sysprops(printFunc) {
// by default use 'echo' to print. Other choices could be
// 'print' or custom function that writes in a text file
if (printFunc == undefined) {
printFunc = echo;
}
var map = getSystemProps();
var keys = map.keySet().iterator();
while (keys.hasNext()) {
var key = keys.next();
var value = map.get(key);
printFunc(key + "=" + value);
}
}

View File

@ -1,89 +0,0 @@
/*
* Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
* This script demonstrates "getMBeanAttribute"
* and "setMBeanAttribute" functions. Instead of using
* MXBean proxy or script wrapper object returned by
* 'mbean' function, this file uses direct get/set MBean
* attribute functions.
*
* To use this particular script, load this script file in
* script console prompt and call verboseGC or verboseClass
* functions. These functions based on events such as
* heap threshold crossing a given limit. i.e., A timer thread
* can keep checking for threshold event and then turn on
* verbose:gc or verbose:class based on expected event.
*/
/**
* Get or set verbose GC flag.
*
* @param flag verbose mode flag [optional]
*
* If flag is not passed verboseGC returns current
* flag value.
*/
function verboseGC(flag) {
if (flag == undefined) {
// no argument passed. interpret this as 'get'
return getMBeanAttribute("java.lang:type=Memory", "Verbose");
} else {
return setMBeanAttribute("java.lang:type=Memory", "Verbose", flag);
}
}
/**
* Get or set verbose class flag.
*
* @param flag verbose mode flag [optional]
*
* If flag is not passed verboseClass returns current
* flag value.
*/
function verboseClass(flag) {
if (flag == undefined) {
// no argument passed. interpret this as 'get'
return getMBeanAttribute("java.lang:type=ClassLoading", "Verbose");
} else {
return setMBeanAttribute("java.lang:type=ClassLoading", "Verbose", flag);
}
}

View File

@ -1,116 +0,0 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
import java.util.*;
import java.net.*;
import java.io.*;
public class Client
{
private final static int BYTESPEROP= PollingServer.BYTESPEROP;
private final static int PORTNUM = PollingServer.PORTNUM;
private final static int MAXCONN = PollingServer.MAXCONN;
private static Socket[] sockArr = new Socket[MAXCONN];
private static int totalConn =10;
private static int bytesToSend =1024000;
private static int connections = 0;
private static int sends = 0;
public static void main (String args[]) {
String host = "localhost";
if (args.length < 1 || args.length > 3) {
System.out.println("Usage : java Client <num_connects>");
System.out.println(" | java Client <num_connects> <server_name>");
System.out.println(" | java Client <num_connects> <server_name>" +
" <max_Kbytes>");
System.exit(-1);
}
if (args.length >= 1)
totalConn = java.lang.Integer.valueOf(args[0]).intValue();
if (args.length >= 2)
host = args[1];
if (args.length == 3)
bytesToSend = java.lang.Integer.valueOf(args[2]).intValue() * 1024;
if (totalConn <= 0 || totalConn > MAXCONN) {
System.out.println("Connections out of range. Terminating.");
System.exit(-1);
}
System.out.println("Using " + totalConn + " connections for sending " +
bytesToSend + " bytes to " + host);
try {
Socket ctrlSock = new Socket (host, PORTNUM);
PrintStream ctrlStream =
new PrintStream(ctrlSock.getOutputStream());
ctrlStream.println(bytesToSend);
ctrlStream.println(totalConn);
while (connections < totalConn ) {
sockArr[connections] = new Socket (host, PORTNUM);
connections ++;
}
System.out.println("Connections made : " + connections);
byte[] buff = new byte[BYTESPEROP];
for (int i = 0; i < BYTESPEROP; i++) // just put some junk in!
buff[i] = (byte) i;
Random rand = new Random(5321L);
while (sends < bytesToSend/BYTESPEROP) {
int idx = java.lang.Math.abs(rand.nextInt()) % totalConn;
sockArr[idx].getOutputStream().write(buff,0,BYTESPEROP);
sends++;
}
// Wait for server to say done.
int bytes = ctrlSock.getInputStream().read(buff, 0, BYTESPEROP);
System.out.println (" Total connections : " + connections +
" Bytes sent : " + sends * BYTESPEROP +
"...Done!");
} catch (Exception e) { e.printStackTrace(); }
}
}

View File

@ -1,230 +0,0 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
File: SLQ.java
Originally: LinkedQueue.java
Originally written by Doug Lea and released into the public domain.
This may be used for any purposes whatsoever without acknowledgment.
Thanks for the assistance and support of Sun Microsystems Labs,
and everyone contributing, testing, and using this code.
History:
Date Who What
11Jun1998 dl Create public version
25aug1998 dl added peek
10dec1998 dl added isEmpty
10jun1999 bc modified for isolated use
*/
// Original was in package EDU.oswego.cs.dl.util.concurrent;
/**
* A linked list based channel implementation,
* adapted from the TwoLockQueue class from CPJ.
* The algorithm avoids contention between puts
* and takes when the queue is not empty.
* Normally a put and a take can proceed simultaneously.
* (Although it does not allow multiple concurrent puts or takes.)
* This class tends to perform more efficently than
* other Channel implementations in producer/consumer
* applications.
* <p>[<a href="http://gee.cs.oswego.edu/dl/classes/EDU/oswego/cs/dl/util/concurrent/intro.html"> Introduction to this package. </a>]
**/
public class LinkedQueue {
/**
* Dummy header node of list. The first actual node, if it exists, is always
* at head_.next. After each take, the old first node becomes the head.
**/
protected LinkedNode head_;
protected int count_;
/**
* Helper monitor for managing access to last node, in case it is also first.
* last_ and waitingForTake_ ONLY used with synch on appendMonitor_
**/
protected final Object lastMonitor_ = new Object();
/**
* The last node of list. Put() appends to list, so modifies last_
**/
protected LinkedNode last_;
/**
* The number of threads waiting for a take.
* Notifications are provided in put only if greater than zero.
* The bookkeeping is worth it here since in reasonably balanced
* usages, the notifications will hardly ever be necessary, so
* the call overhead to notify can be eliminated.
**/
protected int waitingForTake_ = 0;
public LinkedQueue() {
head_ = new LinkedNode(null);
last_ = head_;
count_ = 0;
}
/** Main mechanics for put/offer **/
protected void insert(Object x) {
synchronized(lastMonitor_) {
LinkedNode p = new LinkedNode(x);
last_.next = p;
last_ = p;
count_++;
if (count_ > 1000 && (count_ % 1000 == 0))
System.out.println("In Queue : " + count_);
if (waitingForTake_ > 0)
lastMonitor_.notify();
}
}
/** Main mechanics for take/poll **/
protected synchronized Object extract() {
Object x = null;
LinkedNode first = head_.next;
if (first != null) {
x = first.value;
first.value = null;
head_ = first;
count_ --;
}
return x;
}
public void put(Object x) throws InterruptedException {
if (x == null) throw new IllegalArgumentException();
if (Thread.interrupted()) throw new InterruptedException();
insert(x);
}
public boolean offer(Object x, long msecs) throws InterruptedException {
if (x == null) throw new IllegalArgumentException();
if (Thread.interrupted()) throw new InterruptedException();
insert(x);
return true;
}
public Object take() throws InterruptedException {
if (Thread.interrupted()) throw new InterruptedException();
// try to extract. If fail, then enter wait-based retry loop
Object x = extract();
if (x != null)
return x;
else {
synchronized(lastMonitor_) {
try {
++waitingForTake_;
for (;;) {
x = extract();
if (x != null) {
--waitingForTake_;
return x;
}
else {
lastMonitor_.wait();
}
}
}
catch(InterruptedException ex) {
--waitingForTake_;
lastMonitor_.notify();
throw ex;
}
}
}
}
public synchronized Object peek() {
LinkedNode first = head_.next;
if (first != null)
return first.value;
else
return null;
}
public synchronized boolean isEmpty() {
return head_.next == null;
}
public Object poll(long msecs) throws InterruptedException {
if (Thread.interrupted()) throw new InterruptedException();
Object x = extract();
if (x != null)
return x;
else {
synchronized(lastMonitor_) {
try {
long waitTime = msecs;
long start = (msecs <= 0)? 0 : System.currentTimeMillis();
++waitingForTake_;
for (;;) {
x = extract();
if (x != null || waitTime <= 0) {
--waitingForTake_;
return x;
}
else {
lastMonitor_.wait(waitTime);
waitTime = msecs - (System.currentTimeMillis() - start);
}
}
}
catch(InterruptedException ex) {
--waitingForTake_;
lastMonitor_.notify();
throw ex;
}
}
}
}
class LinkedNode {
Object value;
LinkedNode next = null;
LinkedNode(Object x) { value = x; }
LinkedNode(Object x, LinkedNode n) { value = x; next = n; }
}
}

View File

@ -1,753 +0,0 @@
/*
* Copyright (c) 1999, 2013, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
/*
**********************************************************************
* Poller.c :
* JNI code for use with Poller.java, principally to take advantage
* of poll() or /dev/poll multiplexing.
*
* One will need Solaris 8 or Solaris 7 with adequate patches to take
* advantage of the /dev/poll performance enhancements, though any
* version of Solaris 7 will automatically use the kernel poll()
* caching. And poll() will function in 2.5.1 and 2.6 as well, but
* will not perform well for large numbers of file descriptors.
*
* Several assumptions have been made to simplify this code :
* 1> At most MAX_HANDLES (32) separate pollable entities are currently
* supported.
* 2> Global synchronization from Java is assumed for all init, create
* and destroy routines. Per Object (handle passed in) synchronization
* is required for all AddFd, RemoveFd, IsMember, and Wait routines.
* 3> It is currently up to the user to handle waking up an
* existing nativeWait() call to do an addfd or removefd on
* that set...could implement that here with an extra pipe, or
* with a pair of loopback sockets in Poller.java or user code.
* In most cases interruption is not necessary for deletions,
* so long as deletions are queued up outside the Poller class
* and then executed the next time waitMultiple() returns.
* 4> /dev/poll performance could be slightly improved by coalescing
* adds/removes so that a write() is only done before the ioctl
* (DP_POLL), but this complicates exception handling and sees
* only modest performance gains so wasn't done.
* 5> /dev/poll does not report errors on attempts to remove non-
* extant fds, but a future bug fix to the /dev/poll device driver
* should solve this problem.
* 6> Could add simpler code for pre-Solaris 7 releases which will
* perform slightly better on those OSs. But again there
* are only modest gains to be had from these new code paths,
* so they've been omitted here.
*
* Compile "cc -G -o <dest_dir>/libpoller.so -I ${JAVA_HOME}/include " \
* -I ${JAVA_HOME}/include/solaris Poller.c" and place the <dest_dir>
* in your LD_LIBRARY_PATH
*
**********************************************************************
*/
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <poll.h>
#include <malloc.h>
#include <fcntl.h>
/*
* Remove "_NOT"s to turn on features
* Append "_NOT" to turn off features.
* Use of /dev/poll requires both the include file and kernel driver.
*/
#define DEBUG_NOT
#define DEVPOLL_NOT
#ifdef DEVPOLL
#include <sys/devpoll.h>
#endif
#include "Poller.h"
#define MAX_HANDLES 32
#ifdef DEBUG
#define DBGMSG(x) printf x
#define ASSERT(x) {if (!(x)) \
printf("assertion(%s) failed at line : %d\n",#x,__LINE__);}
#define CHECK_HANDLE(x) check_handle(x)
#else
#define DBGMSG(x)
#define ASSERT(x)
#define CHECK_HANDLE(x)
#endif
/*
* Globals ...protect all with a global synchronization object.
*/
static int Current_handle = 0;
static int Use_devpoll = 0;
static int Max_index = 0;
/*
* Per Poller object data.
* Must be synchronized on a per Poller object basis.
*/
typedef struct ioevent {
int inuse;
int devpollfd;
int last_index;
int total_free;
int left_events;
int max_index;
pollfd_t *pfd;
} ioevent_t;
static ioevent_t IOE_handles[MAX_HANDLES];
/*
* Exceptions to be thrown.
* Note : assuming all illegal argument and NULL pointer checks
* have already been done by the Java calling methods.
*/
static jint throwOutOfMemoryError(JNIEnv *env, const char * cause)
{
(*env)->ThrowNew(env, (*env)->FindClass(env,"java/lang/OutOfMemoryError"),
cause);
return -1;
}
static jint throwInterruptedIOException(JNIEnv *env, const char * cause)
{
(*env)->ThrowNew(env,
(*env)->FindClass(env,"java/io/InterruptedIOException"),
cause);
return -1;
}
static jint throwIllegalStateException(JNIEnv *env, const char * cause)
{
(*env)->ThrowNew(env,
(*env)->FindClass(env,"java/lang/IllegalStateException"),
cause);
return -1;
}
#define MEMORY_EXCEPTION(str) throwOutOfMemoryError(env, "Poller:" str)
#define STATE_EXCEPTION(str) throwIllegalStateException(env, "Poller:" str)
#define INTERRUPT_EXCEPTION(str) throwInterruptedIOException(env, \
"Poller:" str)
jint addfd(JNIEnv *, ioevent_t *, jint, jshort);
jint removefd(JNIEnv *, ioevent_t *, jint);
/*
* Class Poller
* Method: nativeInit
* Signature: ()I
*
* Only to be called once, right after this library is loaded,
* so no need to deal with reentrancy here.
* Could do as a pragma ini, but that isn't as portable.
*/
JNIEXPORT jint JNICALL Java_Poller_nativeInit(JNIEnv *env, jclass cls)
{
int testdevpollfd;
int i;
#ifdef DEVPOLL
/*
* See if we can use this much faster method
* Note : must have fix for BUGID # 4223353 or OS can crash!
*/
testdevpollfd = open("/dev/poll",O_RDWR);
if (testdevpollfd >= 0) {
/*
* If Solaris 7, we need a patch
* Until we know what string to search for, we'll play it
* safe and disable this for Solaris 7.
*/
if (!strcmp(name.release,"5.7"))
{
Use_devpoll = 0;
}
else
{
Use_devpoll = 1;
}
}
DBGMSG(("Use_devpoll=%d\n" ,Use_devpoll));
close(testdevpollfd);
#endif
/*
* For now, we optimize for Solaris 7 if /dev/poll isn't
* available, as it is only a small % hit for Solaris < 7.
* if ( (Use_devpoll == 0) && !strcmp(name.release,"5.6") )
* Use_sol7opt = 0;
*/
Current_handle = 0;
for (i = 0; i < MAX_HANDLES; i++) {
IOE_handles[i].devpollfd = -1;
IOE_handles[i].pfd = NULL;
}
/*
* this tells me the max number of open filedescriptors
*/
Max_index = sysconf(_SC_OPEN_MAX);
if (Max_index < 0) {
Max_index = 1024;
}
DBGMSG(("got sysconf(_SC_OPEN_MAX)=%d file desc\n",Max_index));
return 0;
}
JNIEXPORT jint JNICALL Java_Poller_getNumCPUs(JNIEnv *env, jclass cls)
{
return sysconf(_SC_NPROCESSORS_ONLN);
}
/*
* Class: Poller
* Method: nativeCreatePoller
* Signature: (I)I
* Note : in the case where /dev/poll doesn't exist,
* using more than one poll array could hurt
* Solaris 7 performance due to kernel caching.
*/
JNIEXPORT jint JNICALL Java_Poller_nativeCreatePoller
(JNIEnv *env, jobject obj, jint maximum_fds)
{
int handle, retval, i;
ioevent_t *ioeh;
if (maximum_fds == -1) {
maximum_fds = Max_index;
}
handle = Current_handle;
if (Current_handle >= MAX_HANDLES) {
for (i = 0; i < MAX_HANDLES; i++) {
if (IOE_handles[i].inuse == 0) {
handle = i;
break;
}
}
if (handle >= MAX_HANDLES) {
return MEMORY_EXCEPTION("CreatePoller - MAX_HANDLES exceeded");
}
} else {
Current_handle++;
}
ioeh = &IOE_handles[handle];
ioeh->inuse = 1;
ioeh->last_index = 0;
ioeh->total_free = 0;
ioeh->left_events = 0;
ioeh->max_index = maximum_fds;
retval = handle;
if (Use_devpoll) {
ioeh->devpollfd = open("/dev/poll",O_RDWR);
DBGMSG(("Opened /dev/poll, set devpollfd = %d\n",ioeh->devpollfd));
if (ioeh->devpollfd < 0) {
Current_handle--;
return MEMORY_EXCEPTION("CreatePoller - can\'t open /dev/poll");
}
}
ioeh->pfd = malloc(maximum_fds * sizeof(pollfd_t));
if (ioeh->pfd == NULL) {
Current_handle--;
return MEMORY_EXCEPTION("CreatePoller - malloc failure");
}
return retval;
}
/*
* Class: Poller
* Method: nativeDestroyPoller
* Signature: (I)V
*/
JNIEXPORT void JNICALL Java_Poller_nativeDestroyPoller
(JNIEnv *env, jobject obj, jint handle)
{
ioevent_t *ioeh;
if (handle < 0 || handle >= MAX_HANDLES)
{
STATE_EXCEPTION("DestroyPoller - handle out of range");
return;
}
ioeh = &IOE_handles[handle];
ioeh->inuse = 0;
if (Use_devpoll) {
close(ioeh->devpollfd);
}
free(ioeh->pfd);
}
#ifdef DEBUG
static void check_handle(ioevent_t *ioeh)
{
int i,used,unused;
used=unused=0;
for (i = 0; i < ioeh->last_index; i++)
{
if (ioeh->pfd[i].fd == -1)
unused++;
else
used++;
}
if (unused != ioeh->total_free)
printf("WARNING : found %d free, claimed %d. Used : %d\n",
unused, ioeh->total_free, used);
}
#endif
/*
* Class: Poller
* Method: nativeAddFd
* Signature: (IIS)I
*
* Currently doesn't check to make sure we aren't adding
* an fd already added (no problem for /dev/poll...just
* an array waster for poll()).
*/
JNIEXPORT jint JNICALL Java_Poller_nativeAddFd
(JNIEnv *env, jobject obj, jint handle, jint fd, jshort events)
{
int retval;
ioevent_t *ioeh;
if (handle < 0 || handle >= MAX_HANDLES)
return STATE_EXCEPTION("AddFd - handle out of range");
ioeh = &IOE_handles[handle];
CHECK_HANDLE(ioeh);
#ifdef DEVPOLL
if (Use_devpoll)
{
int i;
pollfd_t pollelt;
/*
* use /dev/poll
*/
pollelt.fd = fd;
pollelt.events = events;
if ((i = write(ioeh->devpollfd, &pollelt, sizeof(pollfd_t))) !=
sizeof(pollfd_t)) {
DBGMSG(("write to devpollfd=%d showed %d bytes out of %d\n",
ioeh->devpollfd,i,sizeof(pollfd_t)));
return STATE_EXCEPTION("AddFd - /dev/poll add failure");
}
else
{
retval = fd;
}
}
else
#endif
{ /* no /dev/poll available */
retval = addfd(env, ioeh, fd, events);
}
return retval;
}
/*
* Addfd to pollfd array...optimized for Solaris 7
*/
jint addfd(JNIEnv *env, ioevent_t *ioeh, jint fd, jshort events)
{
int idx;
if (ioeh->total_free)
{
/*
* Traversing from end because that's where we pad.
*/
ioeh->total_free--;
for (idx = ioeh->last_index - 1; idx >= 0; idx--) {
if (ioeh->pfd[idx].fd == -1)
break;
}
}
else if (ioeh->last_index >= ioeh->max_index)
{
return MEMORY_EXCEPTION("AddFd - too many fds");
}
else
{
int i;
int new_total;
/*
* For Solaris 7, want to add some growth space
* and fill extras with fd=-1. This allows for
* kernel poll() implementation to perform optimally.
*/
new_total = ioeh->last_index;
new_total += (new_total/10) + 1; /* bump size by 10% */
if (new_total > ioeh->max_index)
new_total = ioeh->max_index;
for (i = ioeh->last_index; i <= new_total; i++)
{
ioeh->pfd[i].fd = -1;
}
idx = ioeh->last_index;
ioeh->total_free = new_total - ioeh->last_index - 1;
DBGMSG(("Just grew from %d to %d in size\n",
ioeh->last_index, new_total));
ioeh->last_index = new_total;
}
ASSERT((idx >= 0) && (idx <= ioeh->max_index));
ASSERT(ioeh->pfd[idx].fd == -1);
ioeh->pfd[idx].fd = fd;
ioeh->pfd[idx].events = events;
ioeh->pfd[idx].revents = 0;
CHECK_HANDLE(ioeh);
return fd;
}
/*
* Class: Poller
* Method: nativeRemoveFd
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_Poller_nativeRemoveFd
(JNIEnv *env, jobject obj, jint handle, jint fd)
{
ioevent_t *ioeh;
if (handle < 0 || handle >= MAX_HANDLES)
return STATE_EXCEPTION("RemoveFd - handle out of range");
ioeh = &IOE_handles[handle];
#ifdef DEVPOLL
if (Use_devpoll)
{
/*
* use /dev/poll - currently no need for locking here.
*/
pollfd_t pollelt;
pollelt.fd = fd;
pollelt.events = POLLREMOVE;
if (write(ioeh->devpollfd, &pollelt,
sizeof(pollfd_t) ) != sizeof(pollfd_t))
{
return STATE_EXCEPTION("RemoveFd - /dev/poll failure");
}
}
else
#endif DEVPOLL
{
return removefd(env, ioeh,fd);
}
}
/*
* remove from pollfd array...optimize for Solaris 7
*/
jint removefd(JNIEnv *env, ioevent_t *ioeh, jint fd)
{
int i;
int found = 0;
{ /* !Use_devpoll */
for (i = 0; i < ioeh->last_index; i++)
{
if (ioeh->pfd[i].fd == fd)
{
ioeh->pfd[i].fd = -1;
found = 1;
break;
}
}
if (!found)
{
return STATE_EXCEPTION("RemoveFd - no such fd");
}
ioeh->left_events = 0; /* Have to go back to the kernel */
ioeh->total_free++;
/*
* Shrinking pool if > 33% empty. Just don't do this often!
*/
if ( (ioeh->last_index > 100) &&
(ioeh->total_free > (ioeh->last_index / 3)) )
{
int j;
/*
* we'll just bite the bullet here, since we're > 33% empty.
* walk through and eliminate -1 fd values, shrink total
* size to still have ~ 10 fd==-1 values at end.
* Start at end (since we pad here) and, when we find fd != -1,
* swap with an earlier fd == -1 until we have all -1 values
* at the end.
*/
CHECK_HANDLE(ioeh);
for (i = ioeh->last_index - 1, j = 0; i > j; i--)
{
if (ioeh->pfd[i].fd != -1)
{
while ( (j < i) && (ioeh->pfd[j].fd != -1) )
j++;
DBGMSG( ("i=%d,j=%d,ioeh->pfd[j].fd=%d\n",
i, j, ioeh->pfd[j].fd) );
if (j < i)
{
ASSERT(ioeh->pfd[j].fd == -1);
ioeh->pfd[j].fd = ioeh->pfd[i].fd;
ioeh->pfd[j].events = ioeh->pfd[i].events;
ioeh->pfd[i].fd = -1;
}
}
}
DBGMSG(("Just shrunk from %d to %d in size\n",
ioeh->last_index, j+11));
ioeh->last_index = j + 11; /* last_index always 1 greater */
ioeh->total_free = 10;
CHECK_HANDLE(ioeh);
}
} /* !Use_devpoll */
return 1;
}
/*
* Class: Poller
* Method: nativeIsMember
* Signature: (II)I
*/
JNIEXPORT jint JNICALL Java_Poller_nativeIsMember
(JNIEnv *env, jobject obj, jint handle, jint fd)
{
int found = 0;
int i;
ioevent_t *ioeh;
if (handle < 0 || handle >= MAX_HANDLES)
return STATE_EXCEPTION("IsMember - handle out of range");
ioeh = &IOE_handles[handle];
#ifdef DEVPOLL
if (Use_devpoll)
{
pollfd_t pfd;
/*
* DEVPOLL ioctl DP_ISPOLLED call to determine if fd is polled.
*/
pfd.fd = fd;
pfd.events = 0;
pfd.revents = 0;
found = ioctl(ioeh->devpollfd, DP_ISPOLLED, &pfd);
if (found == -1)
{
return STATE_EXCEPTION("IsMember - /dev/poll failure");
}
}
else
#endif
{
for (i = 0; i < ioeh->last_index; i++)
{
if (fd == ioeh->pfd[i].fd)
{
found = 1;
break;
}
}
}
return found;
}
/*
* Class: Poller
* Method: nativeWait
* Signature: (II[I[SJ)I
*/
JNIEXPORT jint JNICALL Java_Poller_nativeWait
(JNIEnv *env, jobject obj, jint handle, jint maxEvents,
jintArray jfds, jshortArray jrevents, jlong timeout)
{
int useEvents, count, idx;
short *reventp;
jint *fdp;
int retval;
ioevent_t *ioeh;
jboolean isCopy1,isCopy2;
if (handle < 0 || handle >= MAX_HANDLES)
return STATE_EXCEPTION("nativeWait - handle out of range");
ioeh = &IOE_handles[handle];
if (maxEvents == 0) /* just doing a kernel delay! */
{
useEvents = poll(NULL,0L,timeout);
return 0;
}
#ifdef DEVPOLL
if (Use_devpoll)
{
struct dvpoll dopoll;
/*
* DEVPOLL ioctl DP_POLL call, reading
*/
dopoll.dp_timeout = timeout;
dopoll.dp_nfds=maxEvents;
dopoll.dp_fds=ioeh->pfd;
useEvents = ioctl(ioeh->devpollfd, DP_POLL, &dopoll);
while ((useEvents == -1) && (errno == EAGAIN))
useEvents = ioctl(ioeh->devpollfd, DP_POLL, &dopoll);
if (useEvents == -1)
{
if (errno == EINTR)
return INTERRUPT_EXCEPTION("nativeWait - /dev/poll failure EINTR");
else
return STATE_EXCEPTION("nativeWait - /dev/poll failure");
}
reventp =(*env)->GetShortArrayElements(env,jrevents,&isCopy1);
fdp =(*env)->GetIntArrayElements(env,jfds,&isCopy2);
for (idx = 0,count = 0; idx < useEvents; idx++)
{
if (ioeh->pfd[idx].revents)
{
fdp[count] = ioeh->pfd[idx].fd;
reventp[count] = ioeh->pfd[idx].revents;
count++;
}
}
if (count < useEvents)
return STATE_EXCEPTION("Wait - Corrupted internals");
if (isCopy1 == JNI_TRUE)
(*env)->ReleaseShortArrayElements(env,jrevents,reventp,0);
if (isCopy2 == JNI_TRUE)
(*env)->ReleaseIntArrayElements(env,jfds,fdp,0);
}
else
#endif
{ /* !Use_devpoll */
/* no leftovers=>go to kernel */
if (ioeh->left_events == 0)
{
useEvents = poll(ioeh->pfd,ioeh->last_index, timeout);
while ((useEvents == -1) && (errno == EAGAIN))
useEvents = poll(ioeh->pfd,ioeh->last_index, timeout);
if (useEvents == -1)
{
if (errno == EINTR)
return INTERRUPT_EXCEPTION("Wait - poll() failure EINTR-" \
"IO interrupted.");
else if (errno == EINVAL)
return STATE_EXCEPTION("Wait - poll() failure EINVAL-" \
"invalid args (is fdlim cur < max?)");
else
return STATE_EXCEPTION("Wait - poll() failure");
}
ioeh->left_events = useEvents;
DBGMSG(("waitnative : poll returns : %d\n",useEvents));
}
else
{ /* left over from last call */
useEvents = ioeh->left_events;
}
if (useEvents > maxEvents)
{
useEvents = maxEvents;
}
ioeh->left_events -= useEvents; /* left to process */
DBGMSG(("waitnative : left %d, use %d, max %d\n",ioeh->left_events,
useEvents,maxEvents));
if (useEvents > 0)
{
reventp =(*env)->GetShortArrayElements(env,jrevents,&isCopy1);
fdp =(*env)->GetIntArrayElements(env,jfds,&isCopy2);
for (idx = 0,count = 0; (idx < ioeh->last_index) &&
(count < useEvents); idx++)
{
if (ioeh->pfd[idx].revents)
{
fdp[count] = ioeh->pfd[idx].fd;
reventp[count] = ioeh->pfd[idx].revents;
/* in case of leftover for next walk */
ioeh->pfd[idx].revents = 0;
count++;
}
}
if (count < useEvents)
{
ioeh->left_events = 0;
return STATE_EXCEPTION("Wait - Corrupted internals");
}
if (isCopy1 == JNI_TRUE)
(*env)->ReleaseShortArrayElements(env,jrevents,reventp,0);
if (isCopy2 == JNI_TRUE)
(*env)->ReleaseIntArrayElements(env,jfds,fdp,0);
}
} /* !Use_devpoll */
return useEvents;
}

View File

@ -1,335 +0,0 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
import java.lang.reflect.*;
import java.io.*;
import java.net.*;
/**
* This class is provided for access to the underlying poll(2)
* or /dev/poll kernel interfaces. This may be needed for
* multiplexing IO when an application cannot afford to have
* a thread block on each outstanding IO request.
*
* It currently supports the same basic functionality as the
* C poll(2) API, although for efficiency we needed to avoid
* passing the entire pollfd array for every call. See man
* pages for poll(2) for info on C API and event types.
*
*
* @author Bruce Chapman
* @see java.io.FileDescriptor
* @see java.net.Socket
* @see attached README.txt
* @since 1.2
*/
public class Poller {
/**
* Solaris POLL event types.
*/
public final static short POLLERR = 0x08;
public final static short POLLHUP = 0x10;
public final static short POLLNVAL = 0x20;
public final static short POLLIN = 1;
public final static short POLLPRI = 2;
public final static short POLLOUT = 4;
public final static short POLLRDNORM = 0x40;
public final static short POLLWRNORM = POLLOUT ;
public final static short POLLRDBAND = 0x80;
public final static short POLLWRBAND = 0x100;
public final static short POLLNORM = POLLRDNORM;
/*
* This global synchronization object must be used for all
* creation or destruction of Poller objects.
*/
private final static Object globalSync = new Object();
/*
* The handle for a Poller Object...is used in the JNI C code
* where all the associated data is kept.
*/
private int handle;
/**
* Constructs an instance of a <code>Poller</code> object.
* Native code uses sysconf(_SC_OPEN_MAX) to determine how
* many fd/skt objects this Poller object can contain.
*/
public Poller() throws Exception {
synchronized(globalSync) {
this.handle = nativeCreatePoller(-1);
}
}
/**
* Constructs an instance of a <code>Poller</code> object.
* @param maxFd the maximum number of FileDescriptors/Sockets
* this Poller object can contain.
*/
public Poller(int maxFd) throws Exception {
synchronized(globalSync) {
this.handle = nativeCreatePoller(maxFd);
}
}
/**
* Needed to clean up at the JNI C level when object is GCd.
*/
protected void finalize() throws Throwable {
synchronized(globalSync) {
nativeDestroyPoller(handle);
super.finalize();
}
}
/**
* Since we can't guarantee WHEN finalize is called, we may
* recycle on our own.
* @param maxFd the maximum number of FileDescriptors/Sockets
* this Poller object can contain.
*/
public void reset(int maxFd) throws Exception {
synchronized(globalSync) {
nativeDestroyPoller(handle);
this.handle = nativeCreatePoller(maxFd);
}
}
/**
* Since we can't guarantee WHEN finalize is called, we may
* recycle on our own.
*/
public void reset() throws Exception {
synchronized(globalSync) {
nativeDestroyPoller(handle);
this.handle = nativeCreatePoller(-1);
}
}
/**
* Add FileDescriptor to the set handled by this Poller object.
*
* @param fdObj the FileDescriptor, Socket, or ServerSocket to add.
* @param event the bitmask of events we are interested in.
* @return the OS level fd associated with this IO Object
* (which is what waitMultiple() stores in fds[])
*/
public synchronized int add(Object fdObj, short event) throws Exception {
return nativeAddFd(handle,findfd(fdObj), event);
}
/**
* Remove FileDescriptor from the set handled by this Poller object.
*
* Must be called before the fd/skt is closed.
* @param fdObj the FileDescriptor, Socket, or ServerSocket to remove.
* @return true if removal succeeded.
*/
public synchronized boolean remove(Object fdObj) throws Exception {
return (nativeRemoveFd(handle,findfd(fdObj)) == 1);
}
/**
* Check if fd or socket is already in the set handled by this Poller object
*
* @param fdObj the FileDescriptor or [Server]Socket to check.
* @return true if fd/skt is in the set for this Poller object.
*/
public synchronized boolean isMember(Object fdObj) throws Exception {
return (nativeIsMember(handle,findfd(fdObj)) == 1);
}
/**
* Wait on Multiple IO Objects.
*
* @param maxRet the maximum number of fds[] and revents[] to return.
* @param fds[] (return) an array of ints in which to store fds with
* available data upon a successful non-timeout return.
* fds.length must be >= maxRet
* @param revents[] (return) the actual events available on the
* same-indexed fds[] (i.e. fds[0] has events revents[0])
* revents.length must be >= maxRet
*
* Note : both above arrays are "dense," i.e. only fds[] with events
* available are returned.
*
* @param timeout the maximum number of milliseconds to wait for
* events before timing out.
* @return the number of fds with triggered events.
*
* Note : convenience methods exist for skipping the timeout parameter
* or the maxRet parameter (in the case of no maxRet, fds.length
* must equal revents.length)
*
* obj.waitMultiple(null,null,timeout) can be used for pausing the LWP
* (much more reliable and scalable than Thread.sleep() or Object.wait())
*/
public synchronized int waitMultiple(int maxRet, int[] fds,short[] revents,
long timeout) throws Exception
{
if ((revents == null) || (fds == null)) {
if (maxRet > 0) {
throw new NullPointerException("fds or revents is null");
}
} else if ( (maxRet < 0) ||
(maxRet > revents.length) || (maxRet > fds.length) ) {
throw new IllegalArgumentException("maxRet out of range");
}
int ret = nativeWait(handle, maxRet, fds, revents, timeout);
if (ret < 0) {
throw new InterruptedIOException();
}
return ret;
}
/**
* Wait on Multiple IO Objects (no timeout).
* A convenience method for waiting indefinitely on IO events
*
* @see Poller#waitMultiple
*
*/
public int waitMultiple(int maxRet, int[] fds, short[] revents)
throws Exception
{
return waitMultiple(maxRet, fds, revents,-1L); // already synchronized
}
/**
* Wait on Multiple IO Objects (no maxRet).
* A convenience method for waiting on IO events when the fds
* and revents arrays are the same length and that specifies the
* maximum number of return events.
*
* @see Poller#waitMultiple
*
*/
public synchronized int waitMultiple(int[] fds, short[] revents,
long timeout) throws Exception
{
if ((revents == null) && (fds == null)) {
return nativeWait(handle,0,null,null,timeout);
} else if ((revents == null) || (fds == null)) {
throw new NullPointerException("revents or fds is null");
} else if (fds.length == revents.length) {
return nativeWait(handle, fds.length, fds, revents, timeout);
}
throw new IllegalArgumentException("fds.length != revents.length");
}
/**
* Wait on Multiple IO Objects (no maxRet/timeout).
* A convenience method for waiting on IO events when the fds
* and revents arrays are the same length and that specifies the
* maximum number of return events, and when waiting indefinitely
* for IO events to occur.
*
* @see Poller#waitMultiple
*
*/
public int waitMultiple(int[] fds, short[] revents)
throws Exception
{
if ((revents == null) || (fds == null)) {
throw new NullPointerException("fds or revents is null");
} else if (fds.length == revents.length) {
return waitMultiple(revents.length,fds,revents,-1L); // already sync
}
throw new IllegalArgumentException("fds.length != revents.length");
}
// Utility - get (int) fd from FileDescriptor or [Server]Socket objects.
private int findfd(Object fdObj) throws Exception {
Class cl;
Field f;
Object val, implVal;
if ((fdObj instanceof java.net.Socket) ||
(fdObj instanceof java.net.ServerSocket)) {
cl = fdObj.getClass();
f = cl.getDeclaredField("impl");
f.setAccessible(true);
val = f.get(fdObj);
cl = f.getType();
f = cl.getDeclaredField("fd");
f.setAccessible(true);
implVal = f.get(val);
cl = f.getType();
f = cl.getDeclaredField("fd");
f.setAccessible(true);
return ((Integer) f.get(implVal)).intValue();
} else if ( fdObj instanceof java.io.FileDescriptor ) {
cl = fdObj.getClass();
f = cl.getDeclaredField("fd");
f.setAccessible(true);
return ((Integer) f.get(fdObj)).intValue();
}
else {
throw new IllegalArgumentException("Illegal Object type.");
}
}
// Actual NATIVE calls
private static native int nativeInit();
private native int nativeCreatePoller(int maxFd) throws Exception;
private native void nativeDestroyPoller(int handle) throws Exception;
private native int nativeAddFd(int handle, int fd, short events)
throws Exception;
private native int nativeRemoveFd(int handle, int fd) throws Exception;
private native int nativeRemoveIndex(int handle, int index)
throws Exception;
private native int nativeIsMember(int handle, int fd) throws Exception;
private native int nativeWait(int handle, int maxRet, int[] fds,
short[] events, long timeout)
throws Exception;
/**
* Get number of active CPUs in this machine
* to determine proper level of concurrency.
*/
public static native int getNumCPUs();
static {
System.loadLibrary("poller");
nativeInit();
}
}

View File

@ -1,265 +0,0 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
import java.io.*;
import java.net.*;
import java.lang.Byte;
/**
* Simple Java "server" using the Poller class
* to multiplex on incoming connections. Note
* that handoff of events, via linked Q is not
* actually be a performance booster here, since
* the processing of events is cheaper than
* the overhead in scheduling/executing them.
* Although this demo does allow for concurrency
* in handling connections, it uses a rather
* primitive "gang scheduling" policy to keep
* the code simpler.
*/
public class PollingServer
{
public final static int MAXCONN = 10000;
public final static int PORTNUM = 4444;
public final static int BYTESPEROP = 10;
/**
* This synchronization object protects access to certain
* data (bytesRead,eventsToProcess) by concurrent Consumer threads.
*/
private final static Object eventSync = new Object();
private static InputStream[] instr = new InputStream[MAXCONN];
private static int[] mapping = new int[65535];
private static LinkedQueue linkedQ = new LinkedQueue();
private static int bytesRead = 0;
private static int bytesToRead;
private static int eventsToProcess=0;
public PollingServer(int concurrency) {
Socket[] sockArr = new Socket[MAXCONN];
long timestart, timestop;
short[] revents = new short[MAXCONN];
int[] fds = new int[MAXCONN];
int bytes;
Poller Mux;
int serverFd;
int totalConn=0;
int connects=0;
System.out.println ("Serv: Initializing port " + PORTNUM);
try {
ServerSocket skMain = new ServerSocket (PORTNUM);
/*
* Create the Poller object Mux, allow for up to MAXCONN
* sockets/filedescriptors to be polled.
*/
Mux = new Poller(MAXCONN);
serverFd = Mux.add(skMain, Poller.POLLIN);
Socket ctrlSock = skMain.accept();
BufferedReader ctrlReader =
new BufferedReader(new InputStreamReader(ctrlSock.getInputStream()));
String ctrlString = ctrlReader.readLine();
bytesToRead = Integer.valueOf(ctrlString).intValue();
ctrlString = ctrlReader.readLine();
totalConn = Integer.valueOf(ctrlString).intValue();
System.out.println("Receiving " + bytesToRead + " bytes from " +
totalConn + " client connections");
timestart = System.currentTimeMillis();
/*
* Start the consumer threads to read data.
*/
for (int consumerThread = 0;
consumerThread < concurrency; consumerThread++ ) {
new Consumer(consumerThread).start();
}
/*
* Take connections, read Data
*/
int numEvents=0;
while ( bytesRead < bytesToRead ) {
int loopWaits=0;
while (eventsToProcess > 0) {
synchronized (eventSync) {
loopWaits++;
if (eventsToProcess <= 0) break;
try { eventSync.wait(); } catch (Exception e) {e.printStackTrace();};
}
}
if (loopWaits > 1)
System.out.println("Done waiting...loops = " + loopWaits +
" events " + numEvents +
" bytes read : " + bytesRead );
if (bytesRead >= bytesToRead) break; // may be done!
/*
* Wait for events
*/
numEvents = Mux.waitMultiple(100, fds, revents);
synchronized (eventSync) {
eventsToProcess = numEvents;
}
/*
* Process all the events we got from Mux.waitMultiple
*/
int cnt = 0;
while ( (cnt < numEvents) && (bytesRead < bytesToRead) ) {
int fd = fds[cnt];
if (revents[cnt] == Poller.POLLIN) {
if (fd == serverFd) {
/*
* New connection coming in on the ServerSocket
* Add the socket to the Mux, keep track of mapping
* the fdval returned by Mux.add to the connection.
*/
sockArr[connects] = skMain.accept();
instr[connects] = sockArr[connects].getInputStream();
int fdval = Mux.add(sockArr[connects], Poller.POLLIN);
mapping[fdval] = connects;
synchronized(eventSync) {
eventsToProcess--; // just processed this one!
}
connects++;
} else {
/*
* We've got data from this client connection.
* Put it on the queue for the consumer threads to process.
*/
linkedQ.put(new Integer(fd));
}
} else {
System.out.println("Got revents[" + cnt + "] == " + revents[cnt]);
}
cnt++;
}
}
timestop = System.currentTimeMillis();
System.out.println("Time for all reads (" + totalConn +
" sockets) : " + (timestop-timestart));
// Tell the client it can now go away
byte[] buff = new byte[BYTESPEROP];
ctrlSock.getOutputStream().write(buff,0,BYTESPEROP);
// Tell the cunsumer threads they can exit.
for (int cThread = 0; cThread < concurrency; cThread++ ) {
linkedQ.put(new Integer(-1));
}
} catch (Exception exc) { exc.printStackTrace(); }
}
/*
* main ... just check if a concurrency was specified
*/
public static void main (String args[])
{
int concurrency;
if (args.length == 1)
concurrency = java.lang.Integer.valueOf(args[0]).intValue();
else
concurrency = Poller.getNumCPUs() + 1;
PollingServer server = new PollingServer(concurrency);
}
/*
* This class is for handling the Client data.
* The PollingServer spawns off a number of these based upon
* the number of CPUs (or concurrency argument).
* Each just loops grabbing events off the queue and
* processing them.
*/
class Consumer extends Thread {
private int threadNumber;
public Consumer(int i) { threadNumber = i; }
public void run() {
byte[] buff = new byte[BYTESPEROP];
int bytes = 0;
InputStream instream;
while (bytesRead < bytesToRead) {
try {
Integer Fd = (Integer) linkedQ.take();
int fd = Fd.intValue();
if (fd == -1) break; /* got told we could exit */
/*
* We have to map the fd value returned from waitMultiple
* to the actual input stream associated with that fd.
* Take a look at how the Mux.add() was done to see how
* we stored that.
*/
int map = mapping[fd];
instream = instr[map];
bytes = instream.read(buff,0,BYTESPEROP);
} catch (Exception e) { System.out.println(e.toString()); }
if (bytes > 0) {
/*
* Any real server would do some synchronized and some
* unsynchronized work on behalf of the client, and
* most likely send some data back...but this is a
* gross oversimplification.
*/
synchronized(eventSync) {
bytesRead += bytes;
eventsToProcess--;
if (eventsToProcess <= 0) {
eventSync.notify();
}
}
}
}
}
}
}

View File

@ -1,174 +0,0 @@
README.txt
This Poller class demonstrates access to poll(2) functionality in Java.
Requires Solaris production (native threads) JDK 1.2 or later, currently
the C code compiles only on Solaris (SPARC and Intel).
Poller.java is the class, Poller.c is the supporting JNI code.
PollingServer.java is a sample application which uses the Poller class
to multiplex sockets.
SimpleServer.java is the functional equivalent that does not multiplex
but uses a single thread to handle each client connection.
Client.java is a sample application to drive against either server.
To build the Poller class and client/server demo :
javac PollingServer.java Client.java
javah Poller
cc -G -o libpoller.so -I ${JAVA_HOME}/include -I ${JAVA_HOME}/include/solaris\
Poller.c
You will need to set the environment variable LD_LIBRARY_PATH to search
the directory containing libpoller.so.
To use client/server, bump up your fd limit to handle the connections you
want (need root access to go beyond 1024). For info on changing your file
descriptor limit, type "man limit". If you are using Solaris 2.6
or later, a regression in loopback read() performance may hit you at low
numbers of connections, so run the client on another machine.
BASICs of Poller class usage :
run "javadoc Poller" or see Poller.java for more details.
{
Poller Mux = new Poller(65535); // allow it to contain 64K IO objects
int fd1 = Mux.add(socket1, Poller.POLLIN);
...
int fdN = Mux.add(socketN, Poller.POLLIN);
int[] fds = new int[100];
short[] revents = new revents[100];
int numEvents = Mux.waitMultiple(100, fds, revents, timeout);
for (int i = 0; i < numEvents; i++) {
/*
* Probably need more sophisticated mapping scheme than this!
*/
if (fds[i] == fd1) {
System.out.println("Got data on socket1");
socket1.getInputStream().read(byteArray);
// Do something based upon state of fd1 connection
}
...
}
}
Poller class implementation notes :
Currently all add(),remove(),isMember(), and waitMultiple() methods
are synchronized for each Poller object. If one thread is blocked in
pObj.waitMultiple(), another thread calling pObj.add(fd) will block
until waitMultiple() returns. There is no provided mechanism to
interrupt waitMultiple(), as one might expect a ServerSocket to be in
the list waited on (see PollingServer.java).
One might also need to interrupt waitMultiple() to remove()
fds/sockets, in which case one could create a Pipe or loopback localhost
connection (at the level of PollingServer) and use a write() to that
connection to interrupt. Or, better, one could queue up deletions
until the next return of waitMultiple(). Or one could implement an
interrupt mechanism in the JNI C code using a pipe(), and expose that
at the Java level.
If frequent deletions/re-additions of socks/fds is to be done with
very large sets of monitored fds, the Solaris 7 kernel cache will
likely perform poorly without some tuning. One could differentiate
between deleted (no longer cared for) fds/socks and those that are
merely being disabled while data is processed on their behalf. In
that case, re-enabling a disabled fd/sock could put it in it's
original position in the poll array, thereby increasing the kernel
cache performance. This would best be done in Poller.c. Of course
this is not necessary for optimal /dev/poll performance.
Caution...the next paragraph gets a little technical for the
benefit of those who already understand poll()ing fairly well. Others
may choose to skip over it to read notes on the demo server.
An optimal solution for frequent enabling/disabling of socks/fds
could involve a separately synchronized structure of "async"
operations. Using a simple array (0..64k) containing the action
(ADD,ENABLE,DISABLE, NONE), the events, and the index into the poll
array, and having nativeWait() wake up in the poll() call periodically
to process these async operations, I was able to speed up performance
of the PollingServer by a factor of 2x at 8000 connections. Of course
much of that gain was from the fact that I could (with the advent of
an asyncAdd() method) move the accept() loop into a separate thread
from the main poll() loop, and avoid the overhead of calling poll()
with up to 7999 fds just for an accept. In implementing the async
Disable/Enable, a further large optimization was to auto-disable fds
with events available (before return from nativeWait()), so I could
just call asyncEnable(fd) after processing (read()ing) the available
data. This removed the need for inefficient gang-scheduling the
attached PollingServer uses. In order to separately synchronize the
async structure, yet still be able to operate on it from within
nativeWait(), synchronization had to be done at the C level here. Due
to the new complexities this introduced, as well as the fact that it
was tuned specifically for Solaris 7 poll() improvements (not
/dev/poll), this extra logic was left out of this demo.
Client/Server Demo Notes :
Do not run the sample client/server with high numbers of connections
unless you have a lot of free memory on your machine, as it can saturate
CPU and lock you out of CDE just by its very resource intensive nature
(much more so the SimpleServer than PollingServer).
Different OS versions will behave very differently as far as poll()
performance (or /dev/poll existence) but, generally, real world applications
"hit the wall" much earlier when a separate thread is used to handle
each client connection. Issues of thread synchronization and locking
granularity become performance killers. There is some overhead associated
with multiplexing, such as keeping track of the state of each connection; as
the number of connections gets very large, however, this overhead is more
than made up for by the reduced synchronization overhead.
As an example, running the servers on a Solaris 7 PC (Pentium II-350 x
2 CPUS) with 1 GB RAM, and the client on an Ultra-2, I got the following
times (shorter is better) :
1000 connections :
PollingServer took 11 seconds
SimpleServer took 12 seconds
4000 connections :
PollingServer took 20 seconds
SimpleServer took 37 seconds
8000 connections :
PollingServer took 39 seconds
SimpleServer took 1:48 seconds
This demo is not, however, meant to be considered some form of proof
that multiplexing with the Poller class will gain you performance; this
code is actually very heavily biased towards the non-polling server as
very little synchronization is done, and most of the overhead is in the
kernel IO for both servers. Use of multiplexing may be helpful in
many, but certainly not all, circumstances.
Benchmarking a major Java server application which can run
in a single-thread-per-client mode or using the new Poller class showed
Poller provided a 253% improvement in throughput at a moderate load, as
well as a 300% improvement in peak capacity. It also yielded a 21%
smaller memory footprint at the lower load level.
Finally, there is code in Poller.c to take advantage of /dev/poll
on OS versions that have that device; however, DEVPOLL must be defined
in compiling Poller.c (and it must be compiled on a machine with
/usr/include/sys/devpoll.h) to use it. Code compiled with DEVPOLL
turned on will work on machines that don't have kernel support for
the device, as it will fall back to using poll() in those cases.
Currently /dev/poll does not correctly return an error if you attempt
to remove() an object that was never added, but this should be fixed
in an upcoming /dev/poll patch. The binary as shipped is not built with
/dev/poll support as our build machine does not have devpoll.h.

View File

@ -1,158 +0,0 @@
/*
* Copyright (c) 1999, 2011, Oracle and/or its affiliates. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* - Neither the name of Oracle nor the names of its
* contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
* IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
/*
* This source code is provided to illustrate the usage of a given feature
* or technique and has been deliberately simplified. Additional steps
* required for a production-quality application, such as security checks,
* input validation and proper error handling, might not be present in
* this sample code.
*/
import java.io.*;
import java.net.*;
import java.lang.Byte;
/**
* Simple Java "server" using a single thread to handle each connection.
*/
public class SimpleServer
{
private final static int BYTESPEROP= PollingServer.BYTESPEROP;
private final static int PORTNUM = PollingServer.PORTNUM;
private final static int MAXCONN = PollingServer.MAXCONN;
/*
* This synchronization object protects access to certain
* data (bytesRead,eventsToProcess) by concurrent Consumer threads.
*/
private final static Object eventSync = new Object();
private static InputStream[] instr = new InputStream[MAXCONN];
private static int bytesRead;
private static int bytesToRead;
public SimpleServer() {
Socket[] sockArr = new Socket[MAXCONN];
long timestart, timestop;
int bytes;
int totalConn=0;
System.out.println ("Serv: Initializing port " + PORTNUM);
try {
ServerSocket skMain = new ServerSocket (PORTNUM);
bytesRead = 0;
Socket ctrlSock = skMain.accept();
BufferedReader ctrlReader =
new BufferedReader(new InputStreamReader(ctrlSock.getInputStream()));
String ctrlString = ctrlReader.readLine();
bytesToRead = Integer.valueOf(ctrlString).intValue();
ctrlString = ctrlReader.readLine();
totalConn = Integer.valueOf(ctrlString).intValue();
System.out.println("Receiving " + bytesToRead + " bytes from " +
totalConn + " client connections");
timestart = System.currentTimeMillis();
/*
* Take connections, spawn off connection handling threads
*/
ConnHandler[] connHA = new ConnHandler[MAXCONN];
int conn = 0;
while ( conn < totalConn ) {
Socket sock = skMain.accept();
connHA[conn] = new ConnHandler(sock.getInputStream());
connHA[conn].start();
conn++;
}
while ( bytesRead < bytesToRead ) {
java.lang.Thread.sleep(500);
}
timestop = System.currentTimeMillis();
System.out.println("Time for all reads (" + totalConn +
" sockets) : " + (timestop-timestart));
// Tell the client it can now go away
byte[] buff = new byte[BYTESPEROP];
ctrlSock.getOutputStream().write(buff,0,BYTESPEROP);
} catch (Exception exc) { exc.printStackTrace(); }
}
/*
* main ... just create invoke the SimpleServer constructor.
*/
public static void main (String args[])
{
SimpleServer server = new SimpleServer();
}
/*
* Connection Handler inner class...one of these per client connection.
*/
class ConnHandler extends Thread {
private InputStream instr;
public ConnHandler(InputStream inputStr) { instr = inputStr; }
public void run() {
try {
int bytes;
byte[] buff = new byte[BYTESPEROP];
while ( bytesRead < bytesToRead ) {
bytes = instr.read (buff, 0, BYTESPEROP);
if (bytes > 0 ) {
synchronized(eventSync) {
bytesRead += bytes;
}
/*
* Any real server would do some synchronized and some
* unsynchronized work on behalf of the client, and
* most likely send some data back...but this is a
* gross oversimplification.
*/
}
else {
if (bytesRead < bytesToRead)
System.out.println("instr.read returned : " + bytes);
}
}
}
catch (Exception e) {e.printStackTrace();}
}
}
}

View File

@ -7,7 +7,7 @@
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>OpenJDK 7 Command</string>
<string>OpenJDK Command</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2016, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2017, 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
@ -1797,12 +1797,19 @@ public class ObjectInputStream
} catch (ClassNotFoundException ex) {
resolveEx = ex;
}
// Call filterCheck on the class before reading anything else
filterCheck(cl, -1);
skipCustomData();
desc.initProxy(cl, resolveEx, readClassDesc(false));
// Call filterCheck on the definition
filterCheck(desc.forClass(), -1);
try {
totalObjectRefs++;
depth++;
desc.initProxy(cl, resolveEx, readClassDesc(false));
} finally {
depth--;
}
handles.finish(descHandle);
passHandle = descHandle;
@ -1847,12 +1854,19 @@ public class ObjectInputStream
} catch (ClassNotFoundException ex) {
resolveEx = ex;
}
// Call filterCheck on the class before reading anything else
filterCheck(cl, -1);
skipCustomData();
desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
// Call filterCheck on the definition
filterCheck(desc.forClass(), -1);
try {
totalObjectRefs++;
depth++;
desc.initNonProxy(readDesc, cl, resolveEx, readClassDesc(false));
} finally {
depth--;
}
handles.finish(descHandle);
passHandle = descHandle;

View File

@ -84,7 +84,7 @@ import java.util.*;
* {(x, y) such that x.equals(y)}. </pre><p>
*
* This interface is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <T> the type of objects that this object may be compared to

View File

@ -29,7 +29,7 @@ package java.lang;
* Thrown to indicate that the requested operation is not supported.<p>
*
* This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch

View File

@ -143,8 +143,10 @@ public abstract class Reference<T> {
/*
* system property to disable clearing before enqueuing.
*/
private static final boolean disableClearBeforeEnqueue
= Boolean.getBoolean("jdk.lang.ref.disableClearBeforeEnqueue");
private static final class ClearBeforeEnqueue {
static final boolean DISABLE =
Boolean.getBoolean("jdk.lang.ref.disableClearBeforeEnqueue");
}
/*
* Atomically get and clear (set to null) the VM's pending list.
@ -297,7 +299,7 @@ public abstract class Reference<T> {
* it was not registered with a queue when it was created
*/
public boolean enqueue() {
if (!disableClearBeforeEnqueue)
if (!ClearBeforeEnqueue.DISABLE)
this.referent = null;
return this.queue.enqueue(this);
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2017, 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
@ -44,8 +44,8 @@ import java.util.StringJoiner;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentSkipListMap;
import sun.net.util.IPAddressUtil;
import sun.net.RegisteredDomain;
import sun.net.PortConfig;
import sun.security.util.RegisteredDomain;
import sun.security.util.SecurityConstants;
import sun.security.util.Debug;
@ -678,13 +678,18 @@ public final class SocketPermission extends Permission
String a = cname.toLowerCase();
String b = hname.toLowerCase();
if (a.startsWith(b) &&
((a.length() == b.length()) || (a.charAt(b.length()) == '.')))
((a.length() == b.length()) || (a.charAt(b.length()) == '.'))) {
return true;
}
if (cdomain == null) {
cdomain = RegisteredDomain.getRegisteredDomain(a);
cdomain = RegisteredDomain.from(a)
.map(RegisteredDomain::name)
.orElse(a);
}
if (hdomain == null) {
hdomain = RegisteredDomain.getRegisteredDomain(b);
hdomain = RegisteredDomain.from(b)
.map(RegisteredDomain::name)
.orElse(b);
}
return cdomain.length() != 0 && hdomain.length() != 0

View File

@ -49,7 +49,7 @@ package java.util;
* the collection being implemented admits a more efficient implementation.<p>
*
* This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch

View File

@ -62,7 +62,7 @@ import java.util.function.Consumer;
* collection being implemented admits a more efficient implementation.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch

View File

@ -52,7 +52,7 @@ import java.util.Map.Entry;
* map being implemented admits a more efficient implementation.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <K> the type of keys maintained by this map

View File

@ -54,7 +54,7 @@ package java.util;
* instead subclassing {@link AbstractCollection}.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @since 1.5

View File

@ -54,7 +54,7 @@ package java.util;
* specification.<p>
*
* This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch

View File

@ -42,7 +42,7 @@ package java.util;
* for {@code equals} and {@code hashCode}.<p>
*
* This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <E> the type of elements maintained by this set

View File

@ -79,7 +79,7 @@ import java.util.function.UnaryOperator;
* Iterator} interfaces.
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch and Doug Lea

View File

@ -91,7 +91,7 @@ import java.util.function.UnaryOperator;
* should be used only to detect bugs.</i>
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @param <E> the type of elements in this list

View File

@ -62,7 +62,7 @@ import java.util.stream.StreamSupport;
* a MergeSort, but it does have to be <i>stable</i>.)
*
* <p>This class is a member of the
* <a href="{@docRoot}/../technotes/guides/collections/index.html">
* <a href="{@docRoot}/java/util/package-summary.html#CollectionsFramework">
* Java Collections Framework</a>.
*
* @author Josh Bloch
@ -8899,4 +8899,4 @@ public class Arrays {
return aLength != bLength ? length : -1;
}
}
}

Some files were not shown because too many files have changed in this diff Show More