This commit is contained in:
Jon Masamitsu 2014-09-10 23:14:13 +00:00
commit 25727c12c2
38 changed files with 799 additions and 578 deletions

View File

@ -112,7 +112,9 @@ static jmethodID setThreadIntegerRegisterSet_ID = 0;
return;}
static void throwNewDebuggerException(JNIEnv* env, const char* errMsg) {
env->ThrowNew(env->FindClass("sun/jvm/hotspot/debugger/DebuggerException"), errMsg);
jclass clazz = env->FindClass("sun/jvm/hotspot/debugger/DebuggerException");
CHECK_EXCEPTION;
env->ThrowNew(clazz, errMsg);
}
/*
@ -310,15 +312,18 @@ static bool getWindbgInterfaces(JNIEnv* env, jobject obj) {
static bool setImageAndSymbolPath(JNIEnv* env, jobject obj) {
jboolean isCopy;
jclass clazz = env->GetObjectClass(obj);
CHECK_EXCEPTION_(false);
jstring path;
const char* buf;
path = (jstring) env->GetStaticObjectField(clazz, imagePath_ID);
CHECK_EXCEPTION_(false);
buf = env->GetStringUTFChars(path, &isCopy);
CHECK_EXCEPTION_(false);
AutoJavaString imagePath(env, path, buf);
path = (jstring) env->GetStaticObjectField(clazz, symbolPath_ID);
CHECK_EXCEPTION_(false);
buf = env->GetStringUTFChars(path, &isCopy);
CHECK_EXCEPTION_(false);
AutoJavaString symbolPath(env, path, buf);

View File

@ -890,3 +890,5 @@ include $(GAMMADIR)/make/jprt.gmk
create_jdk copy_jdk update_jdk test_jdk \
copy_product_jdk copy_fastdebug_jdk copy_debug_jdk \
$(HS_ALT_MAKE)/Makefile.make remove_old_debuginfo
.NOTPARALLEL:

View File

@ -256,36 +256,36 @@ check_j2se_version:
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=tiered
+$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=compiler2
+$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=compiler1
+$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=core
+$(BUILDTREE) VARIANT=core
$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
+$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
+$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_MINIMAL1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=minimal1
+$(BUILDTREE) VARIANT=minimal1
platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
@ -379,3 +379,5 @@ include $(GAMMADIR)/make/cscope.make
.PHONY: all compiler1 compiler2 core zero shark
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
.PHONY: checks check_os_version check_j2se_version
.NOTPARALLEL:

View File

@ -173,7 +173,7 @@ all: $(SUBMAKE_DIRS)
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@ -364,3 +364,5 @@ sa.make: $(BUILDTREE_MAKE)
FORCE:
.PHONY: all FORCE
.NOTPARALLEL:

View File

@ -69,7 +69,13 @@ AD_Files_If_Required = $(AD_Files_If_Required/$(TYPE))
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
# If SPEC is set, it's from configure and it's already controlling concurrency
# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
ifeq ($(SPEC), )
MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
else
MFLAGS-adjusted = -r $(MFLAGS)
endif
# default target: update lists, make vm
@ -116,7 +122,7 @@ $(adjust-mflags): $(GAMMADIR)/make/$(Platform_os_family)/makefiles/adjust-mflags
@+mv $@+ $@
the_vm: vm_build_preliminaries $(adjust-mflags)
@$(UpdatePCH)
+@$(UpdatePCH)
@$(MAKE) -f vm.make $(MFLAGS-adjusted)
install gamma: the_vm
@ -125,7 +131,7 @@ install gamma: the_vm
# next rules support "make foo.[ois]"
%.o %.i %.s:
$(UpdatePCH)
+$(UpdatePCH)
$(MAKE) -f vm.make $(MFLAGS) $@
#$(MAKE) -f vm.make $@
@ -142,3 +148,5 @@ realclean:
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
.NOTPARALLEL:

View File

@ -250,36 +250,36 @@ check_j2se_version:
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=tiered
+$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=compiler2
+$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=compiler1
+$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=core
+$(BUILDTREE) VARIANT=core
$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
+$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
+$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_MINIMAL1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=minimal1
+$(BUILDTREE) VARIANT=minimal1
platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
$(SED) 's/@ZERO_ARCHDEF@/$(ZERO_ARCHDEF)/g;s/@ZERO_LIBARCH@/$(ZERO_LIBARCH)/g;' < $< > $@
@ -392,3 +392,5 @@ include $(GAMMADIR)/make/cscope.make
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
.PHONY: checks check_os_version check_j2se_version
.PHONY: $(HS_ALT_MAKE)/$(OSNAME)/Makefile.make
.NOTPARALLEL:

View File

@ -178,7 +178,7 @@ all: $(SUBMAKE_DIRS)
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@ -378,3 +378,5 @@ dtrace.make: $(BUILDTREE_MAKE)
FORCE:
.PHONY: all FORCE
.NOTPARALLEL:

View File

@ -69,7 +69,13 @@ AD_Files_If_Required = $(AD_Files_If_Required/$(TYPE))
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
# If SPEC is set, it's from configure and it's already controlling concurrency
# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
ifeq ($(SPEC), )
MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
else
MFLAGS-adjusted = -r $(MFLAGS)
endif
# default target: update lists, make vm
@ -125,7 +131,7 @@ $(adjust-mflags): $(GAMMADIR)/make/$(Platform_os_family)/makefiles/adjust-mflags
@+mv $@+ $@
the_vm: vm_build_preliminaries $(adjust-mflags)
@$(UpdatePCH)
+@$(UpdatePCH)
@$(MAKE) -f vm.make $(MFLAGS-adjusted)
install : the_vm
@ -134,7 +140,7 @@ install : the_vm
# next rules support "make foo.[ois]"
%.o %.i %.s:
$(UpdatePCH)
+$(UpdatePCH)
$(MAKE) -f vm.make $(MFLAGS) $@
#$(MAKE) -f vm.make $@
@ -151,3 +157,5 @@ realclean:
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
.NOTPARALLEL:

View File

@ -256,36 +256,36 @@ check_j2se_version:
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=tiered
+$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=compiler2
+$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=compiler1
+$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=core
+$(BUILDTREE) VARIANT=core
$(SUBDIRS_ZERO): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
+$(BUILDTREE) VARIANT=zero VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_SHARK): $(BUILDTREE_MAKE) platform_zero
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
+$(BUILDTREE) VARIANT=shark VARIANTARCH=$(VARIANTARCH)
$(SUBDIRS_MINIMAL1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=minimal1
+$(BUILDTREE) VARIANT=minimal1
platform_zero: $(GAMMADIR)/make/$(OSNAME)/platform_zero.in
@ -399,3 +399,5 @@ include $(GAMMADIR)/make/cscope.make
.PHONY: clean clean_compiler1 clean_compiler2 clean_core clean_zero clean_shark docs clean_docs
.PHONY: checks check_os_version check_j2se_version
.PHONY: $(HS_ALT_MAKE)/$(OSNAME)/Makefile.make
.NOTPARALLEL:

View File

@ -172,7 +172,7 @@ all: $(SUBMAKE_DIRS)
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@ -377,3 +377,5 @@ dtrace.make: $(BUILDTREE_MAKE)
FORCE:
.PHONY: all FORCE
.NOTPARALLEL:

View File

@ -69,7 +69,13 @@ AD_Files_If_Required = $(AD_Files_If_Required/$(TYPE))
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
# If SPEC is set, it's from configure and it's already controlling concurrency
# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
ifeq ($(SPEC), )
MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
else
MFLAGS-adjusted = -r $(MFLAGS)
endif
# default target: update lists, make vm
@ -119,7 +125,7 @@ $(adjust-mflags): $(GAMMADIR)/make/$(Platform_os_family)/makefiles/adjust-mflags
@+mv $@+ $@
the_vm: vm_build_preliminaries $(adjust-mflags)
@$(UpdatePCH)
+@$(UpdatePCH)
@$(MAKE) -f vm.make $(MFLAGS-adjusted)
install: the_vm
@ -128,7 +134,7 @@ install: the_vm
# next rules support "make foo.[ois]"
%.o %.i %.s:
$(UpdatePCH)
+$(UpdatePCH)
$(MAKE) -f vm.make $(MFLAGS) $@
#$(MAKE) -f vm.make $@
@ -145,3 +151,5 @@ realclean:
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
.NOTPARALLEL:

View File

@ -200,24 +200,24 @@ check_j2se_version:
$(SUBDIRS_TIERED): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=tiered
+$(BUILDTREE) VARIANT=tiered
$(SUBDIRS_C2): $(BUILDTREE_MAKE)
ifeq ($(FORCE_TIERED),1)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
+$(BUILDTREE) VARIANT=tiered FORCE_TIERED=1
else
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=compiler2
+$(BUILDTREE) VARIANT=compiler2
endif
$(SUBDIRS_C1): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=compiler1
+$(BUILDTREE) VARIANT=compiler1
$(SUBDIRS_CORE): $(BUILDTREE_MAKE)
$(QUIETLY) $(MAKE) -f $(GAMMADIR)/make/$(OSNAME)/Makefile checks
$(BUILDTREE) VARIANT=core
+$(BUILDTREE) VARIANT=core
# Define INSTALL=y at command line to automatically copy JVM into JAVA_HOME
@ -292,3 +292,5 @@ include $(GAMMADIR)/make/cscope.make
.PHONY: all compiler1 compiler2 core
.PHONY: clean clean_compiler1 clean_compiler2 clean_core docs clean_docs
.PHONY: checks check_os_version check_j2se_version
.NOTPARALLEL:

View File

@ -165,7 +165,7 @@ all: $(SUBMAKE_DIRS)
# Run make in each subdirectory recursively.
$(SUBMAKE_DIRS): $(SIMPLE_DIRS) FORCE
$(QUIETLY) [ -d $@ ] || { mkdir -p $@; }
$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
+$(QUIETLY) cd $@ && $(BUILDTREE) TARGET=$(@F)
$(QUIETLY) touch $@
$(SIMPLE_DIRS):
@ -364,3 +364,5 @@ dtrace.make: $(BUILDTREE_MAKE)
FORCE:
.PHONY: all FORCE
.NOTPARALLEL:

View File

@ -62,7 +62,13 @@ AD_Files_If_Required = $(AD_Files_If_Required/$(TYPE))
# Wierd argument adjustment for "gnumake -j..."
adjust-mflags = $(GENERATED)/adjust-mflags
MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
# If SPEC is set, it's from configure and it's already controlling concurrency
# for us. Skip setting -j with HOTSPOT_BUILD_JOBS.
ifeq ($(SPEC), )
MFLAGS-adjusted = -r `$(adjust-mflags) "$(MFLAGS)" "$(HOTSPOT_BUILD_JOBS)"`
else
MFLAGS-adjusted = -r $(MFLAGS)
endif
# default target: update lists, make vm
@ -136,3 +142,5 @@ realclean:
.PHONY: default vm_build_preliminaries
.PHONY: lists ad_stuff jvmti_stuff trace_stuff sa_stuff the_vm clean realclean
.PHONY: checks check_os_version install
.NOTPARALLEL:

View File

@ -820,14 +820,10 @@ address InterpreterGenerator::generate_Reference_get_entry(void) {
}
address InterpreterGenerator::generate_native_entry(bool synchronized) {
assert(synchronized == false, "should be");
return generate_entry((address) CppInterpreter::native_entry);
}
address InterpreterGenerator::generate_normal_entry(bool synchronized) {
assert(synchronized == false, "should be");
return generate_entry((address) CppInterpreter::normal_entry);
}

View File

@ -1644,8 +1644,20 @@ static bool _print_ascii_file(const char* filename, outputStream* st) {
return true;
}
int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
outputStream * out = (outputStream *) param;
out->print_cr(PTR_FORMAT " \t%s", base_address, name);
return 0;
}
void os::print_dll_info(outputStream *st) {
st->print_cr("Dynamic libraries:");
if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
st->print_cr("Error: Cannot print dynamic libraries.");
}
}
int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
#ifdef RTLD_DI_LINKMAP
Dl_info dli;
void *handle;
@ -1654,36 +1666,41 @@ void os::print_dll_info(outputStream *st) {
if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 ||
dli.dli_fname == NULL) {
st->print_cr("Error: Cannot print dynamic libraries.");
return;
return 1;
}
handle = dlopen(dli.dli_fname, RTLD_LAZY);
if (handle == NULL) {
st->print_cr("Error: Cannot print dynamic libraries.");
return;
return 1;
}
dlinfo(handle, RTLD_DI_LINKMAP, &map);
if (map == NULL) {
st->print_cr("Error: Cannot print dynamic libraries.");
return;
dlclose(handle);
return 1;
}
while (map->l_prev != NULL)
map = map->l_prev;
while (map != NULL) {
st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
// Value for top_address is returned as 0 since we don't have any information about module size
if (callback(map->l_name, (address)map->l_addr, (address)0, param)) {
dlclose(handle);
return 1;
}
map = map->l_next;
}
dlclose(handle);
#elif defined(__APPLE__)
for (uint32_t i = 1; i < _dyld_image_count(); i++) {
st->print_cr(PTR_FORMAT " \t%s", _dyld_get_image_header(i),
_dyld_get_image_name(i));
// Value for top_address is returned as 0 since we don't have any information about module size
if (callback(_dyld_get_image_name(i), (address)_dyld_get_image_header(i), (address)0, param)) {
return 1;
}
}
return 0;
#else
st->print_cr("Error: Cannot print dynamic libraries.");
return 1;
#endif
}

View File

@ -2120,6 +2120,40 @@ void os::print_dll_info(outputStream *st) {
}
}
int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
FILE *procmapsFile = NULL;
// Open the procfs maps file for the current process
if ((procmapsFile = fopen("/proc/self/maps", "r")) != NULL) {
// Allocate PATH_MAX for file name plus a reasonable size for other fields.
char line[PATH_MAX + 100];
// Read line by line from 'file'
while (fgets(line, sizeof(line), procmapsFile) != NULL) {
u8 base, top, offset, inode;
char permissions[5];
char device[6];
char name[PATH_MAX + 1];
// Parse fields from line
sscanf(line, "%lx-%lx %4s %lx %5s %ld %s", &base, &top, permissions, &offset, device, &inode, name);
// Filter by device id '00:00' so that we only get file system mapped files.
if (strcmp(device, "00:00") != 0) {
// Call callback with the fields of interest
if(callback(name, (address)base, (address)top, param)) {
// Oops abort, callback aborted
fclose(procmapsFile);
return 1;
}
}
}
fclose(procmapsFile);
}
return 0;
}
void os::print_os_info_brief(outputStream* st) {
os::Linux::print_distro_info(st);

View File

@ -215,6 +215,9 @@ void os::Posix::print_uname_info(outputStream* st) {
struct utsname name;
uname(&name);
st->print("%s ", name.sysname);
#ifdef ASSERT
st->print("%s ", name.nodename);
#endif
st->print("%s ", name.release);
st->print("%s ", name.version);
st->print("%s", name.machine);

View File

@ -1722,41 +1722,54 @@ bool os::dll_address_to_library_name(address addr, char* buf,
return false;
}
// Prints the names and full paths of all opened dynamic libraries
// for current process
void os::print_dll_info(outputStream * st) {
int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
Dl_info dli;
void *handle;
Link_map *map;
Link_map *p;
st->print_cr("Dynamic libraries:"); st->flush();
if (dladdr(CAST_FROM_FN_PTR(void *, os::print_dll_info), &dli) == 0 ||
// Sanity check?
if (dladdr(CAST_FROM_FN_PTR(void *, os::get_loaded_modules_info), &dli) == 0 ||
dli.dli_fname == NULL) {
st->print_cr("Error: Cannot print dynamic libraries.");
return;
return 1;
}
handle = dlopen(dli.dli_fname, RTLD_LAZY);
void * handle = dlopen(dli.dli_fname, RTLD_LAZY);
if (handle == NULL) {
st->print_cr("Error: Cannot print dynamic libraries.");
return;
return 1;
}
Link_map *map;
dlinfo(handle, RTLD_DI_LINKMAP, &map);
if (map == NULL) {
st->print_cr("Error: Cannot print dynamic libraries.");
return;
dlclose(handle);
return 1;
}
while (map->l_prev != NULL)
while (map->l_prev != NULL) {
map = map->l_prev;
}
while (map != NULL) {
st->print_cr(PTR_FORMAT " \t%s", map->l_addr, map->l_name);
// Iterate through all map entries and call callback with fields of interest
if(callback(map->l_name, (address)map->l_addr, (address)0, param)) {
dlclose(handle);
return 1;
}
map = map->l_next;
}
dlclose(handle);
return 0;
}
int _print_dll_info_cb(const char * name, address base_address, address top_address, void * param) {
outputStream * out = (outputStream *) param;
out->print_cr(PTR_FORMAT " \t%s", base_address, name);
return 0;
}
void os::print_dll_info(outputStream * st) {
st->print_cr("Dynamic libraries:"); st->flush();
if (get_loaded_modules_info(_print_dll_info_cb, (void *)st)) {
st->print_cr("Error: Cannot print dynamic libraries.");
}
}
// Loads .dll/.so and

View File

@ -1301,120 +1301,6 @@ static bool _addr_in_ntdll( address addr )
}
#endif
// Enumerate all modules for a given process ID
//
// Notice that Windows 95/98/Me and Windows NT/2000/XP have
// different API for doing this. We use PSAPI.DLL on NT based
// Windows and ToolHelp on 95/98/Me.
// Callback function that is called by enumerate_modules() on
// every DLL module.
// Input parameters:
// int pid,
// char* module_file_name,
// address module_base_addr,
// unsigned module_size,
// void* param
typedef int (*EnumModulesCallbackFunc)(int, char *, address, unsigned, void *);
// enumerate_modules for Windows NT, using PSAPI
static int _enumerate_modules_winnt( int pid, EnumModulesCallbackFunc func, void * param)
{
HANDLE hProcess;
# define MAX_NUM_MODULES 128
HMODULE modules[MAX_NUM_MODULES];
static char filename[MAX_PATH];
int result = 0;
if (!os::PSApiDll::PSApiAvailable()) {
return 0;
}
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pid);
if (hProcess == NULL) return 0;
DWORD size_needed;
if (!os::PSApiDll::EnumProcessModules(hProcess, modules,
sizeof(modules), &size_needed)) {
CloseHandle(hProcess);
return 0;
}
// number of modules that are currently loaded
int num_modules = size_needed / sizeof(HMODULE);
for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) {
// Get Full pathname:
if (!os::PSApiDll::GetModuleFileNameEx(hProcess, modules[i],
filename, sizeof(filename))) {
filename[0] = '\0';
}
MODULEINFO modinfo;
if (!os::PSApiDll::GetModuleInformation(hProcess, modules[i],
&modinfo, sizeof(modinfo))) {
modinfo.lpBaseOfDll = NULL;
modinfo.SizeOfImage = 0;
}
// Invoke callback function
result = func(pid, filename, (address)modinfo.lpBaseOfDll,
modinfo.SizeOfImage, param);
if (result) break;
}
CloseHandle(hProcess);
return result;
}
// enumerate_modules for Windows 95/98/ME, using TOOLHELP
static int _enumerate_modules_windows( int pid, EnumModulesCallbackFunc func, void *param)
{
HANDLE hSnapShot;
static MODULEENTRY32 modentry;
int result = 0;
if (!os::Kernel32Dll::HelpToolsAvailable()) {
return 0;
}
// Get a handle to a Toolhelp snapshot of the system
hSnapShot = os::Kernel32Dll::CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pid);
if (hSnapShot == INVALID_HANDLE_VALUE) {
return FALSE;
}
// iterate through all modules
modentry.dwSize = sizeof(MODULEENTRY32);
bool not_done = os::Kernel32Dll::Module32First( hSnapShot, &modentry ) != 0;
while (not_done) {
// invoke the callback
result=func(pid, modentry.szExePath, (address)modentry.modBaseAddr,
modentry.modBaseSize, param);
if (result) break;
modentry.dwSize = sizeof(MODULEENTRY32);
not_done = os::Kernel32Dll::Module32Next( hSnapShot, &modentry ) != 0;
}
CloseHandle(hSnapShot);
return result;
}
int enumerate_modules( int pid, EnumModulesCallbackFunc func, void * param )
{
// Get current process ID if caller doesn't provide it.
if (!pid) pid = os::current_process_id();
if (os::win32::is_nt()) return _enumerate_modules_winnt (pid, func, param);
else return _enumerate_modules_windows(pid, func, param);
}
struct _modinfo {
address addr;
char* full_path; // point to a char buffer
@ -1422,13 +1308,13 @@ struct _modinfo {
address base_addr;
};
static int _locate_module_by_addr(int pid, char * mod_fname, address base_addr,
unsigned size, void * param) {
static int _locate_module_by_addr(const char * mod_fname, address base_addr,
address top_address, void * param) {
struct _modinfo *pmod = (struct _modinfo *)param;
if (!pmod) return -1;
if (base_addr <= pmod->addr &&
base_addr+size > pmod->addr) {
if (base_addr <= pmod->addr &&
top_address > pmod->addr) {
// if a buffer is provided, copy path name to the buffer
if (pmod->full_path) {
jio_snprintf(pmod->full_path, pmod->buflen, "%s", mod_fname);
@ -1453,8 +1339,7 @@ bool os::dll_address_to_library_name(address addr, char* buf,
mi.addr = addr;
mi.full_path = buf;
mi.buflen = buflen;
int pid = os::current_process_id();
if (enumerate_modules(pid, _locate_module_by_addr, (void *)&mi)) {
if (get_loaded_modules_info(_locate_module_by_addr, (void *)&mi)) {
// buf already contains path name
if (offset) *offset = addr - mi.base_addr;
return true;
@ -1479,14 +1364,14 @@ bool os::dll_address_to_function_name(address addr, char *buf,
}
// save the start and end address of jvm.dll into param[0] and param[1]
static int _locate_jvm_dll(int pid, char* mod_fname, address base_addr,
unsigned size, void * param) {
static int _locate_jvm_dll(const char* mod_fname, address base_addr,
address top_address, void * param) {
if (!param) return -1;
if (base_addr <= (address)_locate_jvm_dll &&
base_addr+size > (address)_locate_jvm_dll) {
if (base_addr <= (address)_locate_jvm_dll &&
top_address > (address)_locate_jvm_dll) {
((address*)param)[0] = base_addr;
((address*)param)[1] = base_addr + size;
((address*)param)[1] = top_address;
return 1;
}
return 0;
@ -1497,8 +1382,7 @@ address vm_lib_location[2]; // start and end address of jvm.dll
// check if addr is inside jvm.dll
bool os::address_is_in_vm(address addr) {
if (!vm_lib_location[0] || !vm_lib_location[1]) {
int pid = os::current_process_id();
if (!enumerate_modules(pid, _locate_jvm_dll, (void *)vm_lib_location)) {
if (!get_loaded_modules_info(_locate_jvm_dll, (void *)vm_lib_location)) {
assert(false, "Can't find jvm module.");
return false;
}
@ -1508,14 +1392,13 @@ bool os::address_is_in_vm(address addr) {
}
// print module info; param is outputStream*
static int _print_module(int pid, char* fname, address base,
unsigned size, void* param) {
static int _print_module(const char* fname, address base_address,
address top_address, void* param) {
if (!param) return -1;
outputStream* st = (outputStream*)param;
address end_addr = base + size;
st->print(PTR_FORMAT " - " PTR_FORMAT " \t%s\n", base, end_addr, fname);
st->print(PTR_FORMAT " - " PTR_FORMAT " \t%s\n", base_address, top_address, fname);
return 0;
}
@ -1644,11 +1527,60 @@ void * os::dll_load(const char *name, char *ebuf, int ebuflen)
return NULL;
}
void os::print_dll_info(outputStream *st) {
int pid = os::current_process_id();
st->print_cr("Dynamic libraries:");
enumerate_modules(pid, _print_module, (void *)st);
get_loaded_modules_info(_print_module, (void *)st);
}
int os::get_loaded_modules_info(os::LoadedModulesCallbackFunc callback, void *param) {
HANDLE hProcess;
# define MAX_NUM_MODULES 128
HMODULE modules[MAX_NUM_MODULES];
static char filename[MAX_PATH];
int result = 0;
if (!os::PSApiDll::PSApiAvailable()) {
return 0;
}
int pid = os::current_process_id();
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ,
FALSE, pid);
if (hProcess == NULL) return 0;
DWORD size_needed;
if (!os::PSApiDll::EnumProcessModules(hProcess, modules,
sizeof(modules), &size_needed)) {
CloseHandle(hProcess);
return 0;
}
// number of modules that are currently loaded
int num_modules = size_needed / sizeof(HMODULE);
for (int i = 0; i < MIN2(num_modules, MAX_NUM_MODULES); i++) {
// Get Full pathname:
if (!os::PSApiDll::GetModuleFileNameEx(hProcess, modules[i],
filename, sizeof(filename))) {
filename[0] = '\0';
}
MODULEINFO modinfo;
if (!os::PSApiDll::GetModuleInformation(hProcess, modules[i],
&modinfo, sizeof(modinfo))) {
modinfo.lpBaseOfDll = NULL;
modinfo.SizeOfImage = 0;
}
// Invoke callback function
result = callback(filename, (address)modinfo.lpBaseOfDll,
(address)((u8)modinfo.lpBaseOfDll + (u8)modinfo.SizeOfImage), param);
if (result) break;
}
CloseHandle(hProcess);
return result;
}
void os::print_os_info_brief(outputStream* st) {
@ -1656,8 +1588,17 @@ void os::print_os_info_brief(outputStream* st) {
}
void os::print_os_info(outputStream* st) {
st->print("OS:");
#ifdef ASSERT
char buffer[1024];
DWORD size = sizeof(buffer);
st->print(" HostName: ");
if (GetComputerNameEx(ComputerNameDnsHostname, buffer, &size)) {
st->print("%s", buffer);
} else {
st->print("N/A");
}
#endif
st->print(" OS:");
os::win32::print_windows_version(st);
}

View File

@ -746,7 +746,7 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure) {
// mark metadata seen on the stack and code cache so we can delete
// unneeded entries.
bool has_redefined_a_class = JvmtiExport::has_redefined_a_class();
MetadataOnStackMark md_on_stack;
MetadataOnStackMark md_on_stack(has_redefined_a_class);
if (has_redefined_a_class) {
// purge_previous_versions also cleans weak method links. Because
// one method's MDO can reference another method from another

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -41,7 +41,7 @@ NOT_PRODUCT(bool MetadataOnStackMark::_is_active = false;)
// Walk metadata on the stack and mark it so that redefinition doesn't delete
// it. Class unloading also walks the previous versions and might try to
// delete it, so this class is used by class unloading also.
MetadataOnStackMark::MetadataOnStackMark() {
MetadataOnStackMark::MetadataOnStackMark(bool has_redefined_a_class) {
assert(SafepointSynchronize::is_at_safepoint(), "sanity check");
NOT_PRODUCT(_is_active = true;)
if (_marked_objects == NULL) {
@ -49,7 +49,7 @@ MetadataOnStackMark::MetadataOnStackMark() {
}
Threads::metadata_do(Metadata::mark_on_stack);
if (JvmtiExport::has_redefined_a_class()) {
if (has_redefined_a_class) {
CodeCache::alive_nmethods_do(nmethod::mark_on_stack);
}
CompileBroker::mark_on_stack();

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -37,7 +37,7 @@ class Metadata;
class MetadataOnStackMark : public StackObj {
NOT_PRODUCT(static bool _is_active;)
public:
MetadataOnStackMark();
MetadataOnStackMark(bool has_redefined_a_class);
~MetadataOnStackMark();
static void record(Metadata* m);
};

View File

@ -2062,7 +2062,7 @@ void nmethod::metadata_do(void f(Metadata*)) {
"metadata must be found in exactly one place");
if (r->metadata_is_immediate() && r->metadata_value() != NULL) {
Metadata* md = r->metadata_value();
f(md);
if (md != _method) f(md);
}
} else if (iter.type() == relocInfo::virtual_call_type) {
// Check compiledIC holders associated with this nmethod

View File

@ -460,6 +460,8 @@ objArrayOop InstanceKlass::signers() const {
oop InstanceKlass::init_lock() const {
// return the init lock from the mirror
oop lock = java_lang_Class::init_lock(java_mirror());
// Prevent reordering with any access of initialization state
OrderAccess::loadload();
assert((oop)lock != NULL || !is_not_initialized(), // initialized or in_error state
"only fully initialized state can have a null lock");
return lock;
@ -2437,16 +2439,6 @@ void InstanceKlass::release_C_heap_structures() {
assert(breakpoints() == 0x0, "should have cleared breakpoints");
}
// deallocate information about previous versions
if (_previous_versions != NULL) {
for (int i = _previous_versions->length() - 1; i >= 0; i--) {
PreviousVersionNode * pv_node = _previous_versions->at(i);
delete pv_node;
}
delete _previous_versions;
_previous_versions = NULL;
}
// deallocate the cached class file
if (_cached_class_file != NULL) {
os::free(_cached_class_file, mtClass);
@ -3020,16 +3012,17 @@ void InstanceKlass::print_on(outputStream* st) const {
st->print(BULLET"field type annotations: "); fields_type_annotations()->print_value_on(st); st->cr();
{
bool have_pv = false;
PreviousVersionWalker pvw(Thread::current(), (InstanceKlass*)this);
for (PreviousVersionNode * pv_node = pvw.next_previous_version();
pv_node != NULL; pv_node = pvw.next_previous_version()) {
// previous versions are linked together through the InstanceKlass
for (InstanceKlass* pv_node = _previous_versions;
pv_node != NULL;
pv_node = pv_node->previous_versions()) {
if (!have_pv)
st->print(BULLET"previous version: ");
have_pv = true;
pv_node->prev_constant_pool()->print_value_on(st);
pv_node->constants()->print_value_on(st);
}
if (have_pv) st->cr();
} // pvw is cleaned up
}
if (generic_signature() != NULL) {
st->print(BULLET"generic signature: ");
@ -3443,92 +3436,92 @@ void InstanceKlass::set_init_state(ClassState state) {
// RedefineClasses() support for previous versions:
// Purge previous versions
static void purge_previous_versions_internal(InstanceKlass* ik, int emcp_method_count) {
void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
if (ik->previous_versions() != NULL) {
// This klass has previous versions so see what we can cleanup
// while it is safe to do so.
int deleted_count = 0; // leave debugging breadcrumbs
int live_count = 0;
ClassLoaderData* loader_data = ik->class_loader_data() == NULL ?
ClassLoaderData::the_null_class_loader_data() :
ik->class_loader_data();
ClassLoaderData* loader_data = ik->class_loader_data();
assert(loader_data != NULL, "should never be null");
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE(0x00000200, ("purge: %s: previous version length=%d",
ik->external_name(), ik->previous_versions()->length()));
RC_TRACE(0x00000200, ("purge: %s: previous versions", ik->external_name()));
for (int i = ik->previous_versions()->length() - 1; i >= 0; i--) {
// check the previous versions array
PreviousVersionNode * pv_node = ik->previous_versions()->at(i);
ConstantPool* cp_ref = pv_node->prev_constant_pool();
assert(cp_ref != NULL, "cp ref was unexpectedly cleared");
// previous versions are linked together through the InstanceKlass
InstanceKlass* pv_node = ik->previous_versions();
InstanceKlass* last = ik;
int version = 0;
// check the previous versions list
for (; pv_node != NULL; ) {
ConstantPool* pvcp = pv_node->constants();
assert(pvcp != NULL, "cp ref was unexpectedly cleared");
ConstantPool* pvcp = cp_ref;
if (!pvcp->on_stack()) {
// If the constant pool isn't on stack, none of the methods
// are executing. Delete all the methods, the constant pool and
// and this previous version node.
GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
if (method_refs != NULL) {
for (int j = method_refs->length() - 1; j >= 0; j--) {
Method* method = method_refs->at(j);
assert(method != NULL, "method ref was unexpectedly cleared");
method_refs->remove_at(j);
// method will be freed with associated class.
}
}
// Remove the constant pool
delete pv_node;
// Since we are traversing the array backwards, we don't have to
// do anything special with the index.
ik->previous_versions()->remove_at(i);
// are executing. Unlink this previous_version.
// The previous version InstanceKlass is on the ClassLoaderData deallocate list
// so will be deallocated during the next phase of class unloading.
pv_node = pv_node->previous_versions();
last->link_previous_versions(pv_node);
deleted_count++;
version++;
continue;
} else {
RC_TRACE(0x00000200, ("purge: previous version @%d is alive", i));
RC_TRACE(0x00000200, ("purge: previous version " INTPTR_FORMAT " is alive",
pv_node));
assert(pvcp->pool_holder() != NULL, "Constant pool with no holder");
guarantee (!loader_data->is_unloading(), "unloaded classes can't be on the stack");
live_count++;
}
// At least one method is live in this previous version, clean out
// the others or mark them as obsolete.
GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
// At least one method is live in this previous version so clean its MethodData.
// Reset dead EMCP methods not to get breakpoints.
// All methods are deallocated when all of the methods for this class are no
// longer running.
Array<Method*>* method_refs = pv_node->methods();
if (method_refs != NULL) {
RC_TRACE(0x00000200, ("purge: previous methods length=%d",
method_refs->length()));
for (int j = method_refs->length() - 1; j >= 0; j--) {
for (int j = 0; j < method_refs->length(); j++) {
Method* method = method_refs->at(j);
assert(method != NULL, "method ref was unexpectedly cleared");
// Remove the emcp method if it's not executing
// If it's been made obsolete by a redefinition of a non-emcp
// method, mark it as obsolete but leave it to clean up later.
if (!method->on_stack()) {
method_refs->remove_at(j);
} else if (emcp_method_count == 0) {
method->set_is_obsolete();
// no breakpoints for non-running methods
if (method->is_running_emcp()) {
method->set_running_emcp(false);
}
} else {
assert (method->is_obsolete() || method->is_running_emcp(),
"emcp method cannot run after emcp bit is cleared");
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE(0x00000200,
("purge: %s(%s): prev method @%d in version @%d is alive",
method->name()->as_C_string(),
method->signature()->as_C_string(), j, i));
method->signature()->as_C_string(), j, version));
if (method->method_data() != NULL) {
// Clean out any weak method links
// Clean out any weak method links for running methods
// (also should include not EMCP methods)
method->method_data()->clean_weak_method_links();
}
}
}
}
// next previous version
last = pv_node;
pv_node = pv_node->previous_versions();
version++;
}
assert(ik->previous_versions()->length() == live_count, "sanity check");
RC_TRACE(0x00000200,
("purge: previous version stats: live=%d, deleted=%d", live_count,
deleted_count));
}
// Clean MethodData of this class's methods so they don't refer to
// old methods that are no longer running.
Array<Method*>* methods = ik->methods();
int num_methods = methods->length();
for (int index2 = 0; index2 < num_methods; ++index2) {
@ -3538,122 +3531,30 @@ static void purge_previous_versions_internal(InstanceKlass* ik, int emcp_method_
}
}
// External interface for use during class unloading.
void InstanceKlass::purge_previous_versions(InstanceKlass* ik) {
// Call with >0 emcp methods since they are not currently being redefined.
purge_previous_versions_internal(ik, 1);
}
// Potentially add an information node that contains pointers to the
// interesting parts of the previous version of the_class.
// This is also where we clean out any unused references.
// Note that while we delete nodes from the _previous_versions
// array, we never delete the array itself until the klass is
// unloaded. The has_been_redefined() query depends on that fact.
//
void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
BitMap* emcp_methods, int emcp_method_count) {
assert(Thread::current()->is_VM_thread(),
"only VMThread can add previous versions");
if (_previous_versions == NULL) {
// This is the first previous version so make some space.
// Start with 2 elements under the assumption that the class
// won't be redefined much.
_previous_versions = new (ResourceObj::C_HEAP, mtClass)
GrowableArray<PreviousVersionNode *>(2, true);
}
ConstantPool* cp_ref = ikh->constants();
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE(0x00000400, ("adding previous version ref for %s @%d, EMCP_cnt=%d "
"on_stack=%d",
ikh->external_name(), _previous_versions->length(), emcp_method_count,
cp_ref->on_stack()));
// If the constant pool for this previous version of the class
// is not marked as being on the stack, then none of the methods
// in this previous version of the class are on the stack so
// we don't need to create a new PreviousVersionNode. However,
// we still need to examine older previous versions below.
Array<Method*>* old_methods = ikh->methods();
if (cp_ref->on_stack()) {
PreviousVersionNode * pv_node = NULL;
if (emcp_method_count == 0) {
// non-shared ConstantPool gets a reference
pv_node = new PreviousVersionNode(cp_ref, NULL);
RC_TRACE(0x00000400,
("add: all methods are obsolete; flushing any EMCP refs"));
} else {
int local_count = 0;
GrowableArray<Method*>* method_refs = new (ResourceObj::C_HEAP, mtClass)
GrowableArray<Method*>(emcp_method_count, true);
for (int i = 0; i < old_methods->length(); i++) {
if (emcp_methods->at(i)) {
// this old method is EMCP. Save it only if it's on the stack
Method* old_method = old_methods->at(i);
if (old_method->on_stack()) {
method_refs->append(old_method);
}
if (++local_count >= emcp_method_count) {
// no more EMCP methods so bail out now
break;
}
}
}
// non-shared ConstantPool gets a reference
pv_node = new PreviousVersionNode(cp_ref, method_refs);
}
// append new previous version.
_previous_versions->append(pv_node);
}
// Since the caller is the VMThread and we are at a safepoint, this
// is a good time to clear out unused references.
RC_TRACE(0x00000400, ("add: previous version length=%d",
_previous_versions->length()));
// Purge previous versions not executing on the stack
purge_previous_versions_internal(this, emcp_method_count);
void InstanceKlass::mark_newly_obsolete_methods(Array<Method*>* old_methods,
int emcp_method_count) {
int obsolete_method_count = old_methods->length() - emcp_method_count;
if (emcp_method_count != 0 && obsolete_method_count != 0 &&
_previous_versions->length() > 0) {
_previous_versions != NULL) {
// We have a mix of obsolete and EMCP methods so we have to
// clear out any matching EMCP method entries the hard way.
int local_count = 0;
for (int i = 0; i < old_methods->length(); i++) {
if (!emcp_methods->at(i)) {
Method* old_method = old_methods->at(i);
if (old_method->is_obsolete()) {
// only obsolete methods are interesting
Method* old_method = old_methods->at(i);
Symbol* m_name = old_method->name();
Symbol* m_signature = old_method->signature();
// we might not have added the last entry
for (int j = _previous_versions->length() - 1; j >= 0; j--) {
// check the previous versions array for non executing obsolete methods
PreviousVersionNode * pv_node = _previous_versions->at(j);
// previous versions are linked together through the InstanceKlass
int j = 0;
for (InstanceKlass* prev_version = _previous_versions;
prev_version != NULL;
prev_version = prev_version->previous_versions(), j++) {
GrowableArray<Method*>* method_refs = pv_node->prev_EMCP_methods();
if (method_refs == NULL) {
// We have run into a PreviousVersion generation where
// all methods were made obsolete during that generation's
// RedefineClasses() operation. At the time of that
// operation, all EMCP methods were flushed so we don't
// have to go back any further.
//
// A NULL method_refs is different than an empty method_refs.
// We cannot infer any optimizations about older generations
// from an empty method_refs for the current generation.
break;
}
for (int k = method_refs->length() - 1; k >= 0; k--) {
Array<Method*>* method_refs = prev_version->methods();
for (int k = 0; k < method_refs->length(); k++) {
Method* method = method_refs->at(k);
if (!method->is_obsolete() &&
@ -3661,14 +3562,11 @@ void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
method->signature() == m_signature) {
// The current RedefineClasses() call has made all EMCP
// versions of this method obsolete so mark it as obsolete
// and remove the reference.
RC_TRACE(0x00000400,
("add: %s(%s): flush obsolete method @%d in version @%d",
m_name->as_C_string(), m_signature->as_C_string(), k, j));
method->set_is_obsolete();
// Leave obsolete methods on the previous version list to
// clean up later.
break;
}
}
@ -3676,9 +3574,9 @@ void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
// The previous loop may not find a matching EMCP method, but
// that doesn't mean that we can optimize and not go any
// further back in the PreviousVersion generations. The EMCP
// method for this generation could have already been deleted,
// method for this generation could have already been made obsolete,
// but there still may be an older EMCP method that has not
// been deleted.
// been made obsolete.
}
if (++local_count >= obsolete_method_count) {
@ -3688,15 +3586,69 @@ void InstanceKlass::add_previous_version(instanceKlassHandle ikh,
}
}
}
}
// Save the scratch_class as the previous version if any of the methods are running.
// The previous_versions are used to set breakpoints in EMCP methods and they are
// also used to clean MethodData links to redefined methods that are no longer running.
void InstanceKlass::add_previous_version(instanceKlassHandle scratch_class,
int emcp_method_count) {
assert(Thread::current()->is_VM_thread(),
"only VMThread can add previous versions");
// RC_TRACE macro has an embedded ResourceMark
RC_TRACE(0x00000400, ("adding previous version ref for %s, EMCP_cnt=%d",
scratch_class->external_name(), emcp_method_count));
// Clean out old previous versions
purge_previous_versions(this);
// Mark newly obsolete methods in remaining previous versions. An EMCP method from
// a previous redefinition may be made obsolete by this redefinition.
Array<Method*>* old_methods = scratch_class->methods();
mark_newly_obsolete_methods(old_methods, emcp_method_count);
// If the constant pool for this previous version of the class
// is not marked as being on the stack, then none of the methods
// in this previous version of the class are on the stack so
// we don't need to add this as a previous version.
ConstantPool* cp_ref = scratch_class->constants();
if (!cp_ref->on_stack()) {
RC_TRACE(0x00000400, ("add: scratch class not added; no methods are running"));
return;
}
if (emcp_method_count != 0) {
// At least one method is still running, check for EMCP methods
for (int i = 0; i < old_methods->length(); i++) {
Method* old_method = old_methods->at(i);
if (!old_method->is_obsolete() && old_method->on_stack()) {
// if EMCP method (not obsolete) is on the stack, mark as EMCP so that
// we can add breakpoints for it.
// We set the method->on_stack bit during safepoints for class redefinition and
// class unloading and use this bit to set the is_running_emcp bit.
// After the safepoint, the on_stack bit is cleared and the running emcp
// method may exit. If so, we would set a breakpoint in a method that
// is never reached, but this won't be noticeable to the programmer.
old_method->set_running_emcp(true);
RC_TRACE(0x00000400, ("add: EMCP method %s is on_stack " INTPTR_FORMAT,
old_method->name_and_sig_as_C_string(), old_method));
} else if (!old_method->is_obsolete()) {
RC_TRACE(0x00000400, ("add: EMCP method %s is NOT on_stack " INTPTR_FORMAT,
old_method->name_and_sig_as_C_string(), old_method));
}
}
}
// Add previous version if any methods are still running.
RC_TRACE(0x00000400, ("add: scratch class added; one of its methods is on_stack"));
assert(scratch_class->previous_versions() == NULL, "shouldn't have a previous version");
scratch_class->link_previous_versions(previous_versions());
link_previous_versions(scratch_class());
} // end add_previous_version()
// Determine if InstanceKlass has a previous version.
bool InstanceKlass::has_previous_version() const {
return (_previous_versions != NULL && _previous_versions->length() > 0);
} // end has_previous_version()
Method* InstanceKlass::method_with_idnum(int idnum) {
Method* m = NULL;
if (idnum < methods()->length()) {
@ -3722,61 +3674,3 @@ jint InstanceKlass::get_cached_class_file_len() {
unsigned char * InstanceKlass::get_cached_class_file_bytes() {
return VM_RedefineClasses::get_cached_class_file_bytes(_cached_class_file);
}
// Construct a PreviousVersionNode entry for the array hung off
// the InstanceKlass.
PreviousVersionNode::PreviousVersionNode(ConstantPool* prev_constant_pool,
GrowableArray<Method*>* prev_EMCP_methods) {
_prev_constant_pool = prev_constant_pool;
_prev_EMCP_methods = prev_EMCP_methods;
}
// Destroy a PreviousVersionNode
PreviousVersionNode::~PreviousVersionNode() {
if (_prev_constant_pool != NULL) {
_prev_constant_pool = NULL;
}
if (_prev_EMCP_methods != NULL) {
delete _prev_EMCP_methods;
}
}
// Construct a helper for walking the previous versions array
PreviousVersionWalker::PreviousVersionWalker(Thread* thread, InstanceKlass *ik) {
_thread = thread;
_previous_versions = ik->previous_versions();
_current_index = 0;
_current_p = NULL;
_current_constant_pool_handle = constantPoolHandle(thread, ik->constants());
}
// Return the interesting information for the next previous version
// of the klass. Returns NULL if there are no more previous versions.
PreviousVersionNode* PreviousVersionWalker::next_previous_version() {
if (_previous_versions == NULL) {
// no previous versions so nothing to return
return NULL;
}
_current_p = NULL; // reset to NULL
_current_constant_pool_handle = NULL;
int length = _previous_versions->length();
while (_current_index < length) {
PreviousVersionNode * pv_node = _previous_versions->at(_current_index++);
// Save a handle to the constant pool for this previous version,
// which keeps all the methods from being deallocated.
_current_constant_pool_handle = constantPoolHandle(_thread, pv_node->prev_constant_pool());
_current_p = pv_node;
return pv_node;
}
return NULL;
} // end next_previous_version()

View File

@ -59,7 +59,6 @@ class BreakpointInfo;
class fieldDescriptor;
class DepChange;
class nmethodBucket;
class PreviousVersionNode;
class JvmtiCachedClassFieldMap;
class MemberNameTable;
@ -205,7 +204,8 @@ class InstanceKlass: public Klass {
_misc_should_verify_class = 1 << 2, // allow caching of preverification
_misc_is_anonymous = 1 << 3, // has embedded _host_klass field
_misc_is_contended = 1 << 4, // marked with contended annotation
_misc_has_default_methods = 1 << 5 // class/superclass/implemented interfaces has default methods
_misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods
_misc_has_been_redefined = 1 << 6 // class has been redefined
};
u2 _misc_flags;
u2 _minor_version; // minor version number of class file
@ -220,9 +220,8 @@ class InstanceKlass: public Klass {
nmethodBucket* _dependencies; // list of dependent nmethods
nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class
BreakpointInfo* _breakpoints; // bpt lists, managed by Method*
// Array of interesting part(s) of the previous version(s) of this
// InstanceKlass. See PreviousVersionWalker below.
GrowableArray<PreviousVersionNode *>* _previous_versions;
// Linked instanceKlasses of previous versions
InstanceKlass* _previous_versions;
// JVMTI fields can be moved to their own structure - see 6315920
// JVMTI: cached class file, before retransformable agent modified it in CFLH
JvmtiCachedClassFileData* _cached_class_file;
@ -608,19 +607,20 @@ class InstanceKlass: public Klass {
}
// RedefineClasses() support for previous versions:
void add_previous_version(instanceKlassHandle ikh, BitMap *emcp_methods,
int emcp_method_count);
// If the _previous_versions array is non-NULL, then this klass
// has been redefined at least once even if we aren't currently
// tracking a previous version.
bool has_been_redefined() const { return _previous_versions != NULL; }
bool has_previous_version() const;
void add_previous_version(instanceKlassHandle ikh, int emcp_method_count);
InstanceKlass* previous_versions() const { return _previous_versions; }
bool has_been_redefined() const {
return (_misc_flags & _misc_has_been_redefined) != 0;
}
void set_has_been_redefined() {
_misc_flags |= _misc_has_been_redefined;
}
void init_previous_versions() {
_previous_versions = NULL;
}
GrowableArray<PreviousVersionNode *>* previous_versions() const {
return _previous_versions;
}
static void purge_previous_versions(InstanceKlass* ik);
@ -1042,6 +1042,10 @@ private:
// Free CHeap allocated fields.
void release_C_heap_structures();
// RedefineClasses support
void link_previous_versions(InstanceKlass* pv) { _previous_versions = pv; }
void mark_newly_obsolete_methods(Array<Method*>* old_methods, int emcp_method_count);
public:
// CDS support - remove and restore oops from metadata. Oops are not shared.
virtual void remove_unshareable_info();
@ -1141,62 +1145,6 @@ class JNIid: public CHeapObj<mtClass> {
};
// If breakpoints are more numerous than just JVMTI breakpoints,
// consider compressing this data structure.
// It is currently a simple linked list defined in method.hpp.
class BreakpointInfo;
// A collection point for interesting information about the previous
// version(s) of an InstanceKlass. A GrowableArray of PreviousVersionNodes
// is attached to the InstanceKlass as needed. See PreviousVersionWalker below.
class PreviousVersionNode : public CHeapObj<mtClass> {
private:
ConstantPool* _prev_constant_pool;
// If the previous version of the InstanceKlass doesn't have any
// EMCP methods, then _prev_EMCP_methods will be NULL. If all the
// EMCP methods have been collected, then _prev_EMCP_methods can
// have a length of zero.
GrowableArray<Method*>* _prev_EMCP_methods;
public:
PreviousVersionNode(ConstantPool* prev_constant_pool,
GrowableArray<Method*>* prev_EMCP_methods);
~PreviousVersionNode();
ConstantPool* prev_constant_pool() const {
return _prev_constant_pool;
}
GrowableArray<Method*>* prev_EMCP_methods() const {
return _prev_EMCP_methods;
}
};
// Helper object for walking previous versions.
class PreviousVersionWalker : public StackObj {
private:
Thread* _thread;
GrowableArray<PreviousVersionNode *>* _previous_versions;
int _current_index;
// A pointer to the current node object so we can handle the deletes.
PreviousVersionNode* _current_p;
// The constant pool handle keeps all the methods in this class from being
// deallocated from the metaspace during class unloading.
constantPoolHandle _current_constant_pool_handle;
public:
PreviousVersionWalker(Thread* thread, InstanceKlass *ik);
// Return the interesting information for the next previous version
// of the klass. Returns NULL if there are no more previous versions.
PreviousVersionNode* next_previous_version();
};
//
// nmethodBucket is used to record dependent nmethods for
// deoptimization. nmethod dependencies are actually <klass, method>

View File

@ -80,7 +80,8 @@ class Method : public Metadata {
_caller_sensitive = 1 << 1,
_force_inline = 1 << 2,
_dont_inline = 1 << 3,
_hidden = 1 << 4
_hidden = 1 << 4,
_running_emcp = 1 << 5
};
u1 _flags;
@ -688,6 +689,21 @@ class Method : public Metadata {
void set_is_obsolete() { _access_flags.set_is_obsolete(); }
bool is_deleted() const { return access_flags().is_deleted(); }
void set_is_deleted() { _access_flags.set_is_deleted(); }
bool is_running_emcp() const {
// EMCP methods are old but not obsolete or deleted. Equivalent
// Modulo Constant Pool means the method is equivalent except
// the constant pool and instructions that access the constant
// pool might be different.
// If a breakpoint is set in a redefined method, its EMCP methods that are
// still running must have a breakpoint also.
return (_flags & _running_emcp) != 0;
}
void set_running_emcp(bool x) {
_flags = x ? (_flags | _running_emcp) : (_flags & ~_running_emcp);
}
bool on_stack() const { return access_flags().on_stack(); }
void set_on_stack(const bool value);

View File

@ -282,39 +282,22 @@ address JvmtiBreakpoint::getBcp() {
void JvmtiBreakpoint::each_method_version_do(method_action meth_act) {
((Method*)_method->*meth_act)(_bci);
// add/remove breakpoint to/from versions of the method that
// are EMCP. Directly or transitively obsolete methods are
// not saved in the PreviousVersionNodes.
// add/remove breakpoint to/from versions of the method that are EMCP.
Thread *thread = Thread::current();
instanceKlassHandle ikh = instanceKlassHandle(thread, _method->method_holder());
Symbol* m_name = _method->name();
Symbol* m_signature = _method->signature();
// search previous versions if they exist
PreviousVersionWalker pvw(thread, (InstanceKlass *)ikh());
for (PreviousVersionNode * pv_node = pvw.next_previous_version();
pv_node != NULL; pv_node = pvw.next_previous_version()) {
GrowableArray<Method*>* methods = pv_node->prev_EMCP_methods();
if (methods == NULL) {
// We have run into a PreviousVersion generation where
// all methods were made obsolete during that generation's
// RedefineClasses() operation. At the time of that
// operation, all EMCP methods were flushed so we don't
// have to go back any further.
//
// A NULL methods array is different than an empty methods
// array. We cannot infer any optimizations about older
// generations from an empty methods array for the current
// generation.
break;
}
for (InstanceKlass* pv_node = ikh->previous_versions();
pv_node != NULL;
pv_node = pv_node->previous_versions()) {
Array<Method*>* methods = pv_node->methods();
for (int i = methods->length() - 1; i >= 0; i--) {
Method* method = methods->at(i);
// obsolete methods that are running are not deleted from
// previous version array, but they are skipped here.
if (!method->is_obsolete() &&
// Only set breakpoints in running EMCP methods.
if (method->is_running_emcp() &&
method->name() == m_name &&
method->signature() == m_signature) {
RC_TRACE(0x00000800, ("%sing breakpoint in %s(%s)",

View File

@ -135,7 +135,7 @@ void VM_RedefineClasses::doit() {
// Mark methods seen on stack and everywhere else so old methods are not
// cleaned up if they're on the stack.
MetadataOnStackMark md_on_stack;
MetadataOnStackMark md_on_stack(true);
HandleMark hm(thread); // make sure any handles created are deleted
// before the stack walk again.
@ -2826,11 +2826,10 @@ void VM_RedefineClasses::AdjustCpoolCacheAndVtable::do_klass(Klass* k) {
}
// the previous versions' constant pool caches may need adjustment
PreviousVersionWalker pvw(_thread, ik);
for (PreviousVersionNode * pv_node = pvw.next_previous_version();
pv_node != NULL; pv_node = pvw.next_previous_version()) {
other_cp = pv_node->prev_constant_pool();
cp_cache = other_cp->cache();
for (InstanceKlass* pv_node = ik->previous_versions();
pv_node != NULL;
pv_node = pv_node->previous_versions()) {
cp_cache = pv_node->constants()->cache();
if (cp_cache != NULL) {
cp_cache->adjust_method_entries(_matching_old_methods,
_matching_new_methods,
@ -2855,9 +2854,8 @@ void VM_RedefineClasses::update_jmethod_ids() {
}
}
void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
BitMap *emcp_methods, int * emcp_method_count_p) {
*emcp_method_count_p = 0;
int VM_RedefineClasses::check_methods_and_mark_as_obsolete() {
int emcp_method_count = 0;
int obsolete_count = 0;
int old_index = 0;
for (int j = 0; j < _matching_methods_length; ++j, ++old_index) {
@ -2931,9 +2929,9 @@ void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
// that we get from effectively overwriting the old methods
// when the new methods are attached to the_class.
// track which methods are EMCP for add_previous_version() call
emcp_methods->set_bit(old_index);
(*emcp_method_count_p)++;
// Count number of methods that are EMCP. The method will be marked
// old but not obsolete if it is EMCP.
emcp_method_count++;
// An EMCP method is _not_ obsolete. An obsolete method has a
// different jmethodID than the current method. An EMCP method
@ -2982,10 +2980,11 @@ void VM_RedefineClasses::check_methods_and_mark_as_obsolete(
old_method->name()->as_C_string(),
old_method->signature()->as_C_string()));
}
assert((*emcp_method_count_p + obsolete_count) == _old_methods->length(),
assert((emcp_method_count + obsolete_count) == _old_methods->length(),
"sanity check");
RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", *emcp_method_count_p,
RC_TRACE(0x00000100, ("EMCP_cnt=%d, obsolete_cnt=%d", emcp_method_count,
obsolete_count));
return emcp_method_count;
}
// This internal class transfers the native function registration from old methods
@ -3379,11 +3378,8 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
old_constants->set_pool_holder(scratch_class());
#endif
// track which methods are EMCP for add_previous_version() call below
BitMap emcp_methods(_old_methods->length());
int emcp_method_count = 0;
emcp_methods.clear(); // clears 0..(length() - 1)
check_methods_and_mark_as_obsolete(&emcp_methods, &emcp_method_count);
// track number of methods that are EMCP for add_previous_version() call below
int emcp_method_count = check_methods_and_mark_as_obsolete();
transfer_old_native_function_registrations(the_class);
// The class file bytes from before any retransformable agents mucked
@ -3471,9 +3467,10 @@ void VM_RedefineClasses::redefine_single_class(jclass the_jclass,
scratch_class->enclosing_method_method_index());
scratch_class->set_enclosing_method_indices(old_class_idx, old_method_idx);
the_class->set_has_been_redefined();
// keep track of previous versions of this class
the_class->add_previous_version(scratch_class, &emcp_methods,
emcp_method_count);
the_class->add_previous_version(scratch_class, emcp_method_count);
RC_TIMER_STOP(_timer_rsc_phase1);
RC_TIMER_START(_timer_rsc_phase2);

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2014, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -403,14 +403,9 @@ class VM_RedefineClasses: public VM_Operation {
// Change jmethodIDs to point to the new methods
void update_jmethod_ids();
// In addition to marking methods as obsolete, this routine
// records which methods are EMCP (Equivalent Module Constant
// Pool) in the emcp_methods BitMap and returns the number of
// EMCP methods via emcp_method_count_p. This information is
// used when information about the previous version of the_class
// is squirreled away.
void check_methods_and_mark_as_obsolete(BitMap *emcp_methods,
int * emcp_method_count_p);
// In addition to marking methods as old and/or obsolete, this routine
// counts the number of methods that are EMCP (Equivalent Module Constant Pool).
int check_methods_and_mark_as_obsolete();
void transfer_old_native_function_registrations(instanceKlassHandle the_class);
// Install the redefinition of a class

View File

@ -53,6 +53,7 @@
#include "runtime/vm_version.hpp"
#include "services/attachListener.hpp"
#include "services/nmtCommon.hpp"
#include "services/mallocTracker.hpp"
#include "services/memTracker.hpp"
#include "services/threadService.hpp"
#include "utilities/defaultStream.hpp"
@ -570,6 +571,17 @@ void* os::malloc(size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));
#if INCLUDE_NMT
// NMT can not track malloc allocation size > MAX_MALLOC_SIZE, which is
// (1GB - 1) on 32-bit system. It is not an issue on 64-bit system, where
// MAX_MALLOC_SIZE = ((1 << 62) - 1).
// VM code does not have such large malloc allocation. However, it can come
// Unsafe call.
if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) {
return NULL;
}
#endif
#ifdef ASSERT
// checking for the WatcherThread and crash_protection first
// since os::malloc can be called when the libjvm.{dll,so} is
@ -640,6 +652,13 @@ void* os::realloc(void *memblock, size_t size, MEMFLAGS flags) {
}
void* os::realloc(void *memblock, size_t size, MEMFLAGS memflags, const NativeCallStack& stack) {
#if INCLUDE_NMT
// See comments in os::malloc() above
if (MemTracker::tracking_level() >= NMT_summary && size > MAX_MALLOC_SIZE) {
return NULL;
}
#endif
#ifndef ASSERT
NOT_PRODUCT(inc_stat_counter(&num_mallocs, 1));
NOT_PRODUCT(inc_stat_counter(&alloc_bytes, size));

View File

@ -557,6 +557,16 @@ class os: AllStatic {
// Unload library
static void dll_unload(void *lib);
// Callback for loaded module information
// Input parameters:
// char* module_file_name,
// address module_base_addr,
// address module_top_addr,
// void* param
typedef int (*LoadedModulesCallbackFunc)(const char *, address, address, void *);
static int get_loaded_modules_info(LoadedModulesCallbackFunc callback, void *param);
// Return the handle of this process
static void* get_default_process_handle();

View File

@ -80,6 +80,7 @@ needs_jdk = \
runtime/NMT/MallocSiteHashOverflow.java \
runtime/NMT/MallocStressTest.java \
runtime/NMT/MallocTestType.java \
runtime/NMT/MallocTrackingVerify.java \
runtime/NMT/ReleaseCommittedMemory.java \
runtime/NMT/ReleaseNoCommit.java \
runtime/NMT/ShutdownTwice.java \
@ -87,6 +88,7 @@ needs_jdk = \
runtime/NMT/SummarySanityCheck.java \
runtime/NMT/ThreadedMallocTestType.java \
runtime/NMT/ThreadedVirtualAllocTestType.java \
runtime/NMT/UnsafeMallocLimit.java \
runtime/NMT/VirtualAllocCommitUncommitRecommit.java \
runtime/NMT/VirtualAllocTestType.java \
runtime/RedefineObject/TestRedefineObject.java \

View File

@ -0,0 +1,105 @@
/*
* Copyright (c) 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.
*
* 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.
*/
/*
* @test
* @bug 8054836
* @summary Test to verify correctness of malloc tracking
* @key nmt jcmd
* @library /testlibrary /testlibrary/whitebox
* @build MallocTrackingVerify
* @run main ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:NativeMemoryTracking=detail MallocTrackingVerify
*
*/
import java.util.ArrayList;
import java.util.Random;
import com.oracle.java.testlibrary.*;
import sun.hotspot.WhiteBox;
public class MallocTrackingVerify {
private static int MAX_ALLOC = 4 * 1024;
static ArrayList<MallocMemory> mallocd_memory = new ArrayList<MallocMemory>();
static long mallocd_total = 0;
public static WhiteBox wb = WhiteBox.getWhiteBox();
public static void main(String args[]) throws Exception {
OutputAnalyzer output;
// Grab my own PID
String pid = Integer.toString(ProcessTools.getProcessId());
ProcessBuilder pb = new ProcessBuilder();
Random random = new Random();
// Allocate small amounts of memory with random pseudo call stack
while (mallocd_total < MAX_ALLOC) {
int size = random.nextInt(31) + 1;
long addr = wb.NMTMallocWithPseudoStack(size, random.nextInt());
if (addr != 0) {
MallocMemory mem = new MallocMemory(addr, size);
mallocd_memory.add(mem);
mallocd_total += size;
} else {
System.out.println("Out of malloc memory");
break;
}
}
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid, "VM.native_memory", "summary" });
output = new OutputAnalyzer(pb.start());
output.shouldContain("Test (reserved=4KB, committed=4KB)");
// Free
for (MallocMemory mem : mallocd_memory) {
wb.NMTFree(mem.addr());
}
// Run 'jcmd <pid> VM.native_memory summary', check for expected output
pb.command(new String[] { JDKToolFinder.getJDKTool("jcmd"), pid,
"VM.native_memory", "summary" });
output = new OutputAnalyzer(pb.start());
output.shouldNotContain("Test (reserved=");
}
static class MallocMemory {
private long addr;
private int size;
MallocMemory(long addr, int size) {
this.addr = addr;
this.size = size;
}
long addr() {
return this.addr;
}
int size() {
return this.size;
}
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 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.
*
* 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.
*/
/*
* @test
* @bug 8055289
* @library /testlibrary
* @build UnsafeMallocLimit
* @run main/othervm -Xmx32m -XX:NativeMemoryTracking=summary UnsafeMallocLimit
*/
import com.oracle.java.testlibrary.*;
import sun.misc.Unsafe;
public class UnsafeMallocLimit {
public static void main(String args[]) throws Exception {
if (Platform.is32bit()) {
Unsafe unsafe = Utils.getUnsafe();
try {
unsafe.allocateMemory(1 << 30);
throw new RuntimeException("Did not get expected OOME");
} catch (OutOfMemoryError e) {
// Expected exception
}
} else {
System.out.println("Test only valid on 32-bit platforms");
}
}
}

View File

@ -0,0 +1,143 @@
/*
* Copyright (c) 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.
*
* 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.
*/
/*
* @test
* @bug 8055008
* @summary Redefine EMCP and non-EMCP methods that are running in an infinite loop
* @library /testlibrary
* @build RedefineClassHelper
* @run main RedefineClassHelper
* @run main/othervm -javaagent:redefineagent.jar -XX:TraceRedefineClasses=0x600 RedefineRunningMethods
*/
public class RedefineRunningMethods {
public static String newB =
"class RedefineRunningMethods$B {" +
" static int count1 = 0;" +
" static int count2 = 0;" +
" public static volatile boolean stop = false;" +
" static void localSleep() { " +
" try{ " +
" Thread.currentThread().sleep(10);" +
" } catch(InterruptedException ie) { " +
" } " +
" } " +
" public static void infinite() { " +
" System.out.println(\"infinite called\");" +
" }" +
" public static void infinite_emcp() { " +
" while (!stop) { count2++; localSleep(); }" +
" }" +
"}";
public static String evenNewerB =
"class RedefineRunningMethods$B {" +
" static int count1 = 0;" +
" static int count2 = 0;" +
" public static volatile boolean stop = false;" +
" static void localSleep() { " +
" try{ " +
" Thread.currentThread().sleep(1);" +
" } catch(InterruptedException ie) { " +
" } " +
" } " +
" public static void infinite() { }" +
" public static void infinite_emcp() { " +
" System.out.println(\"infinite_emcp now obsolete called\");" +
" }" +
"}";
static class B {
static int count1 = 0;
static int count2 = 0;
public static volatile boolean stop = false;
static void localSleep() {
try{
Thread.currentThread().sleep(10);//sleep for 10 ms
} catch(InterruptedException ie) {
}
}
public static void infinite() {
while (!stop) { count1++; localSleep(); }
}
public static void infinite_emcp() {
while (!stop) { count2++; localSleep(); }
}
}
public static void main(String[] args) throws Exception {
new Thread() {
public void run() {
B.infinite();
}
}.start();
new Thread() {
public void run() {
B.infinite_emcp();
}
}.start();
RedefineClassHelper.redefineClass(B.class, newB);
System.gc();
B.infinite();
// Start a thread with the second version of infinite_emcp running
new Thread() {
public void run() {
B.infinite_emcp();
}
}.start();
for (int i = 0; i < 20 ; i++) {
String s = new String("some garbage");
System.gc();
}
RedefineClassHelper.redefineClass(B.class, evenNewerB);
System.gc();
for (int i = 0; i < 20 ; i++) {
B.infinite();
String s = new String("some garbage");
System.gc();
}
B.infinite_emcp();
// purge should clean everything up.
B.stop = true;
for (int i = 0; i < 20 ; i++) {
B.infinite();
String s = new String("some garbage");
System.gc();
}
}
}

View File

@ -61,7 +61,7 @@ public class ArchiveDoesNotExist {
"-version");
output = new OutputAnalyzer(pb.start());
output.shouldContain("java version");
output.shouldMatch("(java|openjdk) version");
output.shouldNotContain("sharing");
output.shouldHaveExitValue(0);
}