--- a/hotspot/make/gensrc/GensrcJvmti.gmk Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/make/gensrc/GensrcJvmti.gmk Mon Sep 26 14:21:21 2016 -0400
@@ -67,7 +67,8 @@
$$($1_OUTPUT_DIR)/$1: $$($1_XML_FILE) $$($1_XSL_FILE) $$($1_DEPS) $$(BUILD_JVMTI_TOOLS)
$$(call LogInfo, Generating $$(@F))
$$(call MakeDir, $$(@D))
- $$(call ExecuteWithLog, $$@, $$(TOOL_JVMTI_GEN) -IN $$($1_XML_FILE) -XSL $$($1_XSL_FILE) -OUT $$@ $$($1_ARGS))
+ $$(call ExecuteWithLog, $$@, $$(TOOL_JVMTI_GEN) -IN $$($1_XML_FILE) \
+ -XSL $$($1_XSL_FILE) -OUT $$@ $$($1_ARGS))
# jvmtiGen does not return error code properly on fail.
# NOTE: We should really fix jvmtiGen.java instead.
test -f $$@
@@ -134,8 +135,8 @@
TRACE_OUTPUTDIR := $(JVM_VARIANT_OUTPUTDIR)/gensrc/tracefiles
TRACE_SRCDIR := $(HOTSPOT_TOPDIR)/src/share/vm/trace
-# Append directories to search (might have been set by custom extensions)
-TRACE_SEARCH_DIRS += $(TRACE_SRCDIR)
+# Append list of XSL files to search (might have been set by custom extensions)
+TRACE_XSL_FILES += $(wildcard $(TRACE_SRCDIR)/*.xsl)
TRACE_XML ?= $(TRACE_SRCDIR)/trace.xml
@@ -155,7 +156,7 @@
define SetupTraceGeneration
$$(eval $$(call SetupXslTransform, $1, \
XML_FILE := $$(TRACE_XML), \
- XSL_FILE := $$(firstword $$(wildcard $$(addsuffix /$$(basename $1).xsl, $$(TRACE_SEARCH_DIRS)))), \
+ XSL_FILE := $$(firstword $$(filter %/$$(basename $1).xsl, $$(TRACE_XSL_FILES))), \
OUTPUT_DIR := $$(TRACE_OUTPUTDIR), \
DEPS := $$(TRACE_DEPS), \
))
--- a/hotspot/make/test/JtregNative.gmk Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/make/test/JtregNative.gmk Mon Sep 26 14:21:21 2016 -0400
@@ -55,6 +55,9 @@
$(HOTSPOT_TOPDIR)/test/testlibrary/jvmti \
$(HOTSPOT_TOPDIR)/test/compiler/jvmci/jdk.vm.ci.code.test \
$(HOTSPOT_TOPDIR)/test/serviceability/jvmti/GetModulesInfo \
+ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook \
+ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare \
+ $(HOTSPOT_TOPDIR)/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart \
#
# Add conditional directories here when needed.
@@ -75,6 +78,9 @@
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_liboverflow := -lc
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libSimpleClassFileLoadHook := -lc
BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libGetNamedModuleTest := -lc
+ BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAClassFileLoadHook := -lc
+ BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAClassLoadPrepare := -lc
+ BUILD_HOTSPOT_JTREG_LIBRARIES_LIBS_libMAAThreadStart := -lc
endif
ifeq ($(OPENJDK_TARGET_OS), linux)
--- a/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/cpu/aarch64/vm/interp_masm_aarch64.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -327,7 +327,7 @@
void InterpreterMacroAssembler::push_l(Register r) {
str(zr, pre(esp, -wordSize));
- str(r, pre(esp, -wordsize));
+ str(r, pre(esp, - wordSize));
}
void InterpreterMacroAssembler::pop_f(FloatRegister r) {
--- a/hotspot/src/share/vm/classfile/classLoader.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/classfile/classLoader.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -85,6 +85,7 @@
typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n);
typedef jboolean (JNICALL *ZipInflateFully_t)(void *inBuf, jlong inLen, void *outBuf, jlong outLen, char **pmsg);
typedef jint (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len);
+typedef void (JNICALL *FreeEntry_t)(jzfile *zip, jzentry *entry);
static ZipOpen_t ZipOpen = NULL;
static ZipClose_t ZipClose = NULL;
@@ -95,6 +96,7 @@
static canonicalize_fn_t CanonicalizeEntry = NULL;
static ZipInflateFully_t ZipInflateFully = NULL;
static Crc32_t Crc32 = NULL;
+static FreeEntry_t FreeEntry = NULL;
// Entry points for jimage.dll for loading jimage file entries
@@ -150,6 +152,7 @@
GrowableArray<char*>* ClassLoader::_boot_modules_array = NULL;
GrowableArray<char*>* ClassLoader::_platform_modules_array = NULL;
SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
+int ClassLoader::_num_patch_mod_prefixes = 0;
#endif
// helper routines
@@ -319,6 +322,20 @@
FREE_C_HEAP_ARRAY(char, _zip_name);
}
+bool ClassPathZipEntry::stream_exists(const char* name) {
+ // enable call to C land
+ JavaThread* thread = JavaThread::current();
+ ThreadToNativeFromVM ttn(thread);
+ // check whether zip archive contains name
+ jint name_len, filesize;
+ jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len);
+ if (entry != NULL) {
+ (*FreeEntry)(_zip, entry);
+ return true;
+ }
+ return false;
+}
+
u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) {
// enable call to C land
JavaThread* thread = JavaThread::current();
@@ -640,7 +657,7 @@
struct stat st;
if (os::stat(path, &st) == 0) {
- if ((st.st_mode & S_IFREG) != S_IFREG) { // is directory
+ if ((st.st_mode & S_IFMT) != S_IFREG) { // is not a regular file
if (!os::dir_is_empty(path)) {
tty->print_cr("Error: non-empty directory '%s'", path);
exit_with_path_failure("CDS allows only empty directories in archived classpaths", NULL);
@@ -693,8 +710,6 @@
GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
int num_of_entries = patch_mod_args->length();
- assert(!DumpSharedSpaces, "DumpSharedSpaces not supported with --patch-module");
- assert(!UseSharedSpaces, "UseSharedSpaces not supported with --patch-module");
// Set up the boot loader's _patch_mod_entries list
_patch_mod_entries = new (ResourceObj::C_HEAP, mtModule) GrowableArray<ModuleClassPathList*>(num_of_entries, true);
@@ -851,7 +866,7 @@
bool is_boot_append, TRAPS) {
JavaThread* thread = JavaThread::current();
ClassPathEntry* new_entry = NULL;
- if ((st->st_mode & S_IFREG) == S_IFREG) {
+ if ((st->st_mode & S_IFMT) == S_IFREG) {
ResourceMark rm(thread);
// Regular file, should be a zip or jimage file
// Canonicalized filename
@@ -914,7 +929,7 @@
// check for a regular file
struct stat st;
if (os::stat(path, &st) == 0) {
- if ((st.st_mode & S_IFREG) == S_IFREG) {
+ if ((st.st_mode & S_IFMT) == S_IFREG) {
char canonical_path[JVM_MAXPATHLEN];
if (get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
char* error_msg = NULL;
@@ -1068,6 +1083,7 @@
GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry"));
ZipInflateFully = CAST_TO_FN_PTR(ZipInflateFully_t, os::dll_lookup(handle, "ZIP_InflateFully"));
Crc32 = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32"));
+ FreeEntry = CAST_TO_FN_PTR(FreeEntry_t, os::dll_lookup(handle, "ZIP_FreeEntry"));
// ZIP_Close is not exported on Windows in JDK5.0 so don't abort if ZIP_Close is NULL
if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL ||
@@ -1395,6 +1411,57 @@
return NULL;
}
+#if INCLUDE_CDS
+// The following function is only used during CDS dump time.
+// It checks if a class can be found in the jar entries of the _patch_mod_entries.
+// It does not support non-jar entries.
+bool ClassLoader::is_in_patch_module(const char* const file_name) {
+ assert(DumpSharedSpaces, "dump time only");
+ if (_patch_mod_entries == NULL) {
+ return false;
+ }
+
+ int num_of_entries = _patch_mod_entries->length();
+ char* class_module_name = NULL;
+ ResourceMark rm;
+ const char *pkg_name = package_from_name(file_name);
+ // Using the jimage to obtain the class' module name.
+ // The ModuleEntryTable cannot be used at this point during dump time
+ // because the module system hasn't been initialized yet.
+ if (pkg_name != NULL) {
+ JImageFile *jimage = _jrt_entry->jimage();
+ class_module_name = (char*)(*JImagePackageToModule)(jimage, pkg_name);
+ }
+
+ if (class_module_name == NULL) {
+ return false;
+ }
+
+ // Loop through all the patch module entries looking for module
+ for (int i = 0; i < num_of_entries; i++) {
+ ModuleClassPathList* module_cpl = _patch_mod_entries->at(i);
+ Symbol* module_cpl_name = module_cpl->module_name();
+
+ if (strcmp(module_cpl_name->as_C_string(), class_module_name) == 0) {
+ // Class' module has been located, attempt to locate
+ // the class from the module's ClassPathEntry list.
+ ClassPathEntry* e = module_cpl->module_first_entry();
+ while (e != NULL) {
+ if (e->is_jar_file()) {
+ if (e->stream_exists(file_name)) {
+ return true;
+ } else {
+ e = e->next();
+ }
+ }
+ }
+ }
+ }
+
+ return false;
+}
+#endif // INCLUDE_CDS
+
instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_only, TRAPS) {
assert(name != NULL, "invariant");
assert(THREAD->is_Java_thread(), "must be a JavaThread");
@@ -1420,8 +1487,8 @@
// If DumpSharedSpaces is true boot loader visibility boundaries are set to:
// - [jimage] + [_first_append_entry to _last_append_entry] (all path entries).
- // No --patch-module entries or exploded module builds are included since CDS
- // is not supported if --patch-module or exploded module builds are used.
+ // If a class is found in the --patch-module entries, the class will not be included in the
+ // CDS archive. Also, CDS is not supported if exploded module builds are used.
//
// If search_append_only is true, boot loader visibility boundaries are
// set to be _first_append_entry to the end. This includes:
@@ -1444,8 +1511,17 @@
// found within its module specification, the search should continue to Load Attempt #2.
// Note: The --patch-module entries are never searched if the boot loader's
// visibility boundary is limited to only searching the append entries.
- if (_patch_mod_entries != NULL && !search_append_only && !DumpSharedSpaces) {
- stream = search_module_entries(_patch_mod_entries, class_name, file_name, CHECK_NULL);
+ if (_patch_mod_entries != NULL && !search_append_only) {
+ if (!DumpSharedSpaces) {
+ stream = search_module_entries(_patch_mod_entries, class_name, file_name, CHECK_NULL);
+ } else {
+#if INCLUDE_CDS
+ if (is_in_patch_module(file_name)) {
+ tty->print_cr("Preload Warning: Skip archiving class %s found in --patch-module entry", class_name);
+ return NULL;
+ }
+#endif
+ }
}
// Load Attempt #2: [jimage | exploded build]
@@ -1596,8 +1672,57 @@
}
#if INCLUDE_CDS
+// Capture all the --patch-module entries specified during CDS dump time.
+// It also captures the non-existing path(s) and the required file(s) during inspecting
+// the entries.
+void ClassLoader::setup_patch_mod_path() {
+ assert(DumpSharedSpaces, "only used with -Xshare:dump");
+ ResourceMark rm;
+ GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
+ if (patch_mod_args != NULL) {
+ int num_of_entries = patch_mod_args->length();
+ for (int i = 0; i < num_of_entries; i++) {
+ const char* module_name = (patch_mod_args->at(i))->module_name();
+ const char* module_path = (patch_mod_args->at(i))->path_string();
+ int path_len = (int)strlen(module_path);
+ int name_len = (int)strlen(module_name);
+ int buf_len = name_len + path_len + 2; // add 2 for the '=' and NULL terminator
+ int end = 0;
+ char* buf = NEW_C_HEAP_ARRAY(char, buf_len, mtInternal);
+ // Iterate over the module's class path entries
+ for (int start = 0; start < path_len; start = end) {
+ while (module_path[end] && module_path[end] != os::path_separator()[0]) {
+ end++;
+ }
+ strncpy(buf, &module_path[start], end - start);
+ buf[end - start] = '\0';
+ struct stat st;
+ if (os::stat(buf, &st) != 0) {
+ // File not found
+ _shared_paths_misc_info->add_nonexist_path(buf);
+ } else {
+ if ((st.st_mode & S_IFMT) != S_IFREG) { // is not a regular file
+ vm_exit_during_initialization(
+ "--patch-module requires a regular file during dumping", buf);
+ } else {
+ _shared_paths_misc_info->add_required_file(buf);
+ }
+ }
+ while (module_path[end] == os::path_separator()[0]) {
+ end++;
+ }
+ };
+ jio_snprintf(buf, buf_len, "%s=%s", module_name, module_path);
+ _shared_paths_misc_info->add_patch_mod_classpath((const char*)buf);
+ _num_patch_mod_prefixes++;
+ FREE_C_HEAP_ARRAY(char, buf);
+ }
+ }
+}
+
void ClassLoader::initialize_shared_path() {
if (DumpSharedSpaces) {
+ setup_patch_mod_path();
ClassLoaderExt::setup_search_paths();
_shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
}
--- a/hotspot/src/share/vm/classfile/classLoader.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/classfile/classLoader.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -69,6 +69,7 @@
// Attempt to locate file_name through this class path entry.
// Returns a class file parsing stream if successfull.
virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
+ virtual bool stream_exists(const char* name) = 0;
// Debugging
NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
};
@@ -83,6 +84,7 @@
JImageFile* jimage() const { return NULL; }
ClassPathDirEntry(const char* dir);
ClassFileStream* open_stream(const char* name, TRAPS);
+ bool stream_exists(const char* name) { return false; }
// Debugging
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
};
@@ -126,6 +128,7 @@
ClassFileStream* open_stream(const char* name, TRAPS);
void contents_do(void f(const char* name, void* context), void* context);
bool is_multiple_versioned(TRAPS) NOT_CDS_RETURN_(false);
+ bool stream_exists(const char* name);
// Debugging
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
};
@@ -145,6 +148,7 @@
ClassPathImageEntry(JImageFile* jimage, const char* name);
~ClassPathImageEntry();
ClassFileStream* open_stream(const char* name, TRAPS);
+ bool stream_exists(const char* name) { return false; }
// Debugging
NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
@@ -255,6 +259,7 @@
// Info used by CDS
CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
+ CDS_ONLY(static int _num_patch_mod_prefixes;)
// Initialization:
// - setup the boot loader's system class path
@@ -427,6 +432,9 @@
static void initialize_module_loader_map(JImageFile* jimage);
static s2 classloader_type(Symbol* class_name, ClassPathEntry* e,
int classpath_index, TRAPS);
+ static bool is_in_patch_module(const char* const file_name);
+ static void setup_patch_mod_path(); // Only when -Xshare:dump
+ static int num_patch_mod_prefixes() { return _num_patch_mod_prefixes; }
#endif
static void trace_class_path(const char* msg, const char* name = NULL);
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -86,6 +86,9 @@
case REQUIRED:
out->print("Expecting that file %s must exist and is not altered", path);
break;
+ case PATCH_MOD:
+ out->print("Expecting --patch-module=%s", path);
+ break;
default:
ShouldNotReachHere();
}
@@ -146,6 +149,9 @@
// But we want it to not exist -> fail
return fail("File must not exist");
}
+ if ((st.st_mode & S_IFMT) != S_IFREG) {
+ return fail("Did not get a regular file as expected.");
+ }
time_t timestamp;
long filesize;
@@ -161,7 +167,26 @@
}
}
break;
-
+ case PATCH_MOD:
+ {
+ GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
+ if (patch_mod_args != NULL) {
+ int num_of_entries = patch_mod_args->length();
+ for (int i = 0; i < num_of_entries; i++) {
+ const char* module_name = (patch_mod_args->at(i))->module_name();
+ const char* path_string = (patch_mod_args->at(i))->path_string();
+ size_t n = strlen(module_name);
+ // path contains the module name, followed by '=', and one or more entries.
+ // E.g.: "java.base=foo" or "java.naming=dir1:dir2:dir3"
+ if ((strncmp(module_name, path, n) != 0) ||
+ (path[n] != '=') ||
+ (strcmp(path + n + 1, path_string) != 0)) {
+ return fail("--patch-module mismatch, path not found in run time: ", path);
+ }
+ }
+ }
+ }
+ break;
default:
return fail("Corrupted archive file header");
}
--- a/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -104,10 +104,28 @@
add_path(path, NON_EXIST);
}
+ // The path must exist and have required size and modification time
+ void add_required_file(const char* path) {
+ add_path(path, REQUIRED);
+
+ struct stat st;
+ if (os::stat(path, &st) != 0) {
+ assert(0, "sanity");
+#if INCLUDE_CDS
+ ClassLoader::exit_with_path_failure("failed to os::stat(%s)", path); // should not happen
+#endif
+ }
+ write_time(st.st_mtime);
+ write_long(st.st_size);
+ }
+
// The path must exist, and must contain exactly <num_entries> files/dirs
void add_boot_classpath(const char* path) {
add_path(path, BOOT);
}
+ void add_patch_mod_classpath(const char* path) {
+ add_path(path, PATCH_MOD);
+ }
int write_jint(jint num) {
write(&num, sizeof(num));
return 0;
@@ -129,7 +147,8 @@
enum {
BOOT = 1,
NON_EXIST = 2,
- REQUIRED = 3
+ REQUIRED = 3,
+ PATCH_MOD = 4
};
virtual const char* type_name(int type) {
@@ -137,6 +156,7 @@
case BOOT: return "BOOT";
case NON_EXIST: return "NON_EXIST";
case REQUIRED: return "REQUIRED";
+ case PATCH_MOD: return "PATCH_MOD";
default: ShouldNotReachHere(); return "?";
}
}
--- a/hotspot/src/share/vm/classfile/symbolTable.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/classfile/symbolTable.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -710,53 +710,3 @@
return 0;
}
}
-
-#ifndef PRODUCT
-// Internal test of TempNewSymbol
-void Test_TempNewSymbol() {
- // Assert messages assume these symbols are unique, and the refcounts start at
- // one, but code does not rely on this.
- Thread* THREAD = Thread::current();
- Symbol* abc = SymbolTable::new_symbol("abc", CATCH);
- int abccount = abc->refcount();
- TempNewSymbol ss = abc;
- assert(ss->refcount() == abccount, "only one abc");
- assert(ss->refcount() == abc->refcount(), "should match TempNewSymbol");
-
- Symbol* efg = SymbolTable::new_symbol("efg", CATCH);
- Symbol* hij = SymbolTable::new_symbol("hij", CATCH);
- int efgcount = efg->refcount();
- int hijcount = hij->refcount();
-
- TempNewSymbol s1 = efg;
- TempNewSymbol s2 = hij;
- assert(s1->refcount() == efgcount, "one efg");
- assert(s2->refcount() == hijcount, "one hij");
-
- // Assignment operator
- s1 = s2;
- assert(hij->refcount() == hijcount + 1, "should be two hij");
- assert(efg->refcount() == efgcount - 1, "should be no efg");
-
- s1 = ss; // s1 is abc
- assert(s1->refcount() == abccount + 1, "should be two abc (s1 and ss)");
- assert(hij->refcount() == hijcount, "should only have one hij now (s2)");
-
- s1 = s1; // self assignment
- assert(s1->refcount() == abccount + 1, "should still be two abc (s1 and ss)");
-
- TempNewSymbol s3;
- Symbol* klm = SymbolTable::new_symbol("klm", CATCH);
- int klmcount = klm->refcount();
- s3 = klm; // assignment
- assert(s3->refcount() == klmcount, "only one klm now");
-
- Symbol* xyz = SymbolTable::new_symbol("xyz", CATCH);
- int xyzcount = xyz->refcount();
- { // inner scope
- TempNewSymbol s_inner = xyz;
- }
- assert(xyz->refcount() == (xyzcount - 1),
- "Should have been decremented by dtor in inner scope");
-}
-#endif // PRODUCT
--- a/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/cms/cmsOopClosures.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -258,16 +258,15 @@
// the closure ParMarkFromRootsClosure.
class ParPushOrMarkClosure: public MetadataAwareOopClosure {
private:
- CMSCollector* _collector;
- MemRegion _whole_span;
- MemRegion _span; // local chunk
- CMSBitMap* _bit_map;
- OopTaskQueue* _work_queue;
- CMSMarkStack* _overflow_stack;
- HeapWord* const _finger;
- HeapWord** const _global_finger_addr;
- ParMarkFromRootsClosure* const
- _parent;
+ CMSCollector* _collector;
+ MemRegion _whole_span;
+ MemRegion _span; // local chunk
+ CMSBitMap* _bit_map;
+ OopTaskQueue* _work_queue;
+ CMSMarkStack* _overflow_stack;
+ HeapWord* const _finger;
+ HeapWord* volatile* const _global_finger_addr;
+ ParMarkFromRootsClosure* const _parent;
protected:
DO_OOP_WORK_DEFN
public:
@@ -277,7 +276,7 @@
OopTaskQueue* work_queue,
CMSMarkStack* mark_stack,
HeapWord* finger,
- HeapWord** global_finger_addr,
+ HeapWord* volatile* global_finger_addr,
ParMarkFromRootsClosure* parent);
virtual void do_oop(oop* p);
virtual void do_oop(narrowOop* p);
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -3025,14 +3025,14 @@
// MT Concurrent Marking Task
class CMSConcMarkingTask: public YieldingFlexibleGangTask {
- CMSCollector* _collector;
- uint _n_workers; // requested/desired # workers
- bool _result;
- CompactibleFreeListSpace* _cms_space;
- char _pad_front[64]; // padding to ...
- HeapWord* _global_finger; // ... avoid sharing cache line
- char _pad_back[64];
- HeapWord* _restart_addr;
+ CMSCollector* _collector;
+ uint _n_workers; // requested/desired # workers
+ bool _result;
+ CompactibleFreeListSpace* _cms_space;
+ char _pad_front[64]; // padding to ...
+ HeapWord* volatile _global_finger; // ... avoid sharing cache line
+ char _pad_back[64];
+ HeapWord* _restart_addr;
// Exposed here for yielding support
Mutex* const _bit_map_lock;
@@ -3068,7 +3068,7 @@
OopTaskQueue* work_queue(int i) { return task_queues()->queue(i); }
- HeapWord** global_finger_addr() { return &_global_finger; }
+ HeapWord* volatile* global_finger_addr() { return &_global_finger; }
CMSConcMarkingTerminator* terminator() { return &_term; }
@@ -6554,7 +6554,7 @@
// Note: the local finger doesn't advance while we drain
// the stack below, but the global finger sure can and will.
- HeapWord** gfa = _task->global_finger_addr();
+ HeapWord* volatile* gfa = _task->global_finger_addr();
ParPushOrMarkClosure pushOrMarkClosure(_collector,
_span, _bit_map,
_work_queue,
@@ -6721,7 +6721,7 @@
OopTaskQueue* work_queue,
CMSMarkStack* overflow_stack,
HeapWord* finger,
- HeapWord** global_finger_addr,
+ HeapWord* volatile* global_finger_addr,
ParMarkFromRootsClosure* parent) :
MetadataAwareOopClosure(collector->ref_processor()),
_collector(collector),
--- a/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/cms/concurrentMarkSweepGeneration.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -724,12 +724,12 @@
// Support for parallelizing young gen rescan in CMS remark phase
ParNewGeneration* _young_gen;
- HeapWord** _top_addr; // ... Top of Eden
- HeapWord** _end_addr; // ... End of Eden
- Mutex* _eden_chunk_lock;
- HeapWord** _eden_chunk_array; // ... Eden partitioning array
- size_t _eden_chunk_index; // ... top (exclusive) of array
- size_t _eden_chunk_capacity; // ... max entries in array
+ HeapWord* volatile* _top_addr; // ... Top of Eden
+ HeapWord** _end_addr; // ... End of Eden
+ Mutex* _eden_chunk_lock;
+ HeapWord** _eden_chunk_array; // ... Eden partitioning array
+ size_t _eden_chunk_index; // ... top (exclusive) of array
+ size_t _eden_chunk_capacity; // ... max entries in array
// Support for parallelizing survivor space rescan
HeapWord** _survivor_chunk_array;
--- a/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1CollectedHeap.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -2474,8 +2474,16 @@
}
jlong G1CollectedHeap::millis_since_last_gc() {
- // assert(false, "NYI");
- return 0;
+ // See the notes in GenCollectedHeap::millis_since_last_gc()
+ // for more information about the implementation.
+ jlong ret_val = (os::javaTimeNanos() / NANOSECS_PER_MILLISEC) -
+ _g1_policy->collection_pause_end_millis();
+ if (ret_val < 0) {
+ log_warning(gc)("millis_since_last_gc() would return : " JLONG_FORMAT
+ ". returning zero instead.", ret_val);
+ return 0;
+ }
+ return ret_val;
}
void G1CollectedHeap::prepare_for_verify() {
--- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -66,7 +66,8 @@
_phase_times(new G1GCPhaseTimes(ParallelGCThreads)),
_tenuring_threshold(MaxTenuringThreshold),
_max_survivor_regions(0),
- _survivors_age_table(true) { }
+ _survivors_age_table(true),
+ _collection_pause_end_millis(os::javaTimeNanos() / NANOSECS_PER_MILLISEC) { }
G1DefaultPolicy::~G1DefaultPolicy() {
delete _ihop_control;
@@ -575,6 +576,8 @@
record_pause(young_gc_pause_kind(), end_time_sec - pause_time_ms / 1000.0, end_time_sec);
+ _collection_pause_end_millis = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
+
last_pause_included_initial_mark = collector_state()->during_initial_mark_pause();
if (last_pause_included_initial_mark) {
record_concurrent_mark_init_end(0.0);
--- a/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1DefaultPolicy.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -64,6 +64,8 @@
double _full_collection_start_sec;
+ jlong _collection_pause_end_millis;
+
uint _young_list_target_length;
uint _young_list_fixed_length;
@@ -237,6 +239,8 @@
double reclaimable_bytes_perc(size_t reclaimable_bytes) const;
+ jlong collection_pause_end_millis() { return _collection_pause_end_millis; }
+
private:
// Sets up marking if proper conditions are met.
void maybe_start_marking();
--- a/hotspot/src/share/vm/gc/g1/g1Policy.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/g1Policy.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -119,6 +119,8 @@
virtual void record_full_collection_start() = 0;
virtual void record_full_collection_end() = 0;
+ virtual jlong collection_pause_end_millis() = 0;
+
// Must currently be called while the world is stopped.
virtual void record_concurrent_mark_init_end(double mark_init_elapsed_time_ms) = 0;
--- a/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/heapRegionRemSet.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -56,7 +56,7 @@
PerRegionTable * _collision_list_next;
// Global free list of PRTs
- static PerRegionTable* _free_list;
+ static PerRegionTable* volatile _free_list;
protected:
// We need access in order to union things into the base table.
@@ -249,7 +249,7 @@
static void test_fl_mem_size();
};
-PerRegionTable* PerRegionTable::_free_list = NULL;
+PerRegionTable* volatile PerRegionTable::_free_list = NULL;
size_t OtherRegionsTable::_max_fine_entries = 0;
size_t OtherRegionsTable::_mod_max_fine_entries_mask = 0;
--- a/hotspot/src/share/vm/gc/g1/sparsePRT.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/sparsePRT.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -283,7 +283,7 @@
// ----------------------------------------------------------------------
-SparsePRT* SparsePRT::_head_expanded_list = NULL;
+SparsePRT* volatile SparsePRT::_head_expanded_list = NULL;
void SparsePRT::add_to_expanded_list(SparsePRT* sprt) {
// We could expand multiple times in a pause -- only put on list once.
--- a/hotspot/src/share/vm/gc/g1/sparsePRT.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/g1/sparsePRT.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -250,7 +250,7 @@
bool should_be_on_expanded_list();
- static SparsePRT* _head_expanded_list;
+ static SparsePRT* volatile _head_expanded_list;
public:
SparsePRT(HeapRegion* hr);
--- a/hotspot/src/share/vm/gc/parallel/mutableSpace.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/mutableSpace.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -51,7 +51,7 @@
MemRegion _last_setup_region;
size_t _alignment;
protected:
- HeapWord* _top;
+ HeapWord* volatile _top;
MutableSpaceMangler* mangler() { return _mangler; }
@@ -69,7 +69,7 @@
HeapWord* top() const { return _top; }
virtual void set_top(HeapWord* value) { _top = value; }
- HeapWord** top_addr() { return &_top; }
+ HeapWord* volatile* top_addr() { return &_top; }
HeapWord** end_addr() { return &_end; }
virtual void set_bottom(HeapWord* value) { _bottom = value; }
--- a/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/parallelScavengeHeap.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -175,7 +175,7 @@
bool supports_inline_contig_alloc() const { return !UseNUMA; }
- HeapWord** top_addr() const { return !UseNUMA ? young_gen()->top_addr() : (HeapWord**)-1; }
+ HeapWord* volatile* top_addr() const { return !UseNUMA ? young_gen()->top_addr() : (HeapWord* volatile*)-1; }
HeapWord** end_addr() const { return !UseNUMA ? young_gen()->end_addr() : (HeapWord**)-1; }
void ensure_parsability(bool retire_tlabs);
--- a/hotspot/src/share/vm/gc/parallel/psYoungGen.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/psYoungGen.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -162,7 +162,7 @@
return result;
}
- HeapWord** top_addr() const { return eden_space()->top_addr(); }
+ HeapWord* volatile* top_addr() const { return eden_space()->top_addr(); }
HeapWord** end_addr() const { return eden_space()->end_addr(); }
// Iteration.
--- a/hotspot/src/share/vm/gc/parallel/vmStructs_parallelgc.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/parallel/vmStructs_parallelgc.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2007, 2016, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@@ -26,7 +26,8 @@
#define SHARE_VM_GC_PARALLEL_VMSTRUCTS_PARALLELGC_HPP
#define VM_STRUCTS_PARALLELGC(nonstatic_field, \
- static_field) \
+ volatile_nonstatic_field, \
+ static_field) \
\
/**********************/ \
/* Parallel GC fields */ \
@@ -40,7 +41,7 @@
nonstatic_field(ImmutableSpace, _bottom, HeapWord*) \
nonstatic_field(ImmutableSpace, _end, HeapWord*) \
\
- nonstatic_field(MutableSpace, _top, HeapWord*) \
+ volatile_nonstatic_field(MutableSpace, _top, HeapWord*) \
\
nonstatic_field(PSYoungGen, _reserved, MemRegion) \
nonstatic_field(PSYoungGen, _virtual_space, PSVirtualSpace*) \
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -512,7 +512,7 @@
}
-HeapWord** DefNewGeneration::top_addr() const { return eden()->top_addr(); }
+HeapWord* volatile* DefNewGeneration::top_addr() const { return eden()->top_addr(); }
HeapWord** DefNewGeneration::end_addr() const { return eden()->end_addr(); }
void DefNewGeneration::object_iterate(ObjectClosure* blk) {
--- a/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/serial/defNewGeneration.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2001, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2001, 2016, 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
@@ -225,7 +225,7 @@
size_t max_survivor_size() const { return _max_survivor_size; }
bool supports_inline_contig_alloc() const { return true; }
- HeapWord** top_addr() const;
+ HeapWord* volatile* top_addr() const;
HeapWord** end_addr() const;
// Thread-local allocation buffers
--- a/hotspot/src/share/vm/gc/shared/collectedHeap.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/shared/collectedHeap.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -350,7 +350,7 @@
// These functions return the addresses of the fields that define the
// boundaries of the contiguous allocation area. (These fields should be
// physically near to one another.)
- virtual HeapWord** top_addr() const {
+ virtual HeapWord* volatile* top_addr() const {
guarantee(false, "inline contiguous allocation not supported");
return NULL;
}
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -721,7 +721,7 @@
return _young_gen->supports_inline_contig_alloc();
}
-HeapWord** GenCollectedHeap::top_addr() const {
+HeapWord* volatile* GenCollectedHeap::top_addr() const {
return _young_gen->top_addr();
}
@@ -1256,21 +1256,20 @@
};
jlong GenCollectedHeap::millis_since_last_gc() {
- // We need a monotonically non-decreasing time in ms but
- // os::javaTimeMillis() does not guarantee monotonicity.
+ // javaTimeNanos() is guaranteed to be monotonically non-decreasing
+ // provided the underlying platform provides such a time source
+ // (and it is bug free). So we still have to guard against getting
+ // back a time later than 'now'.
jlong now = os::javaTimeNanos() / NANOSECS_PER_MILLISEC;
GenTimeOfLastGCClosure tolgc_cl(now);
// iterate over generations getting the oldest
// time that a generation was collected
generation_iterate(&tolgc_cl, false);
- // javaTimeNanos() is guaranteed to be monotonically non-decreasing
- // provided the underlying platform provides such a time source
- // (and it is bug free). So we still have to guard against getting
- // back a time later than 'now'.
jlong retVal = now - tolgc_cl.time();
if (retVal < 0) {
- NOT_PRODUCT(log_warning(gc)("time warp: " JLONG_FORMAT, retVal);)
+ log_warning(gc)("millis_since_last_gc() would return : " JLONG_FORMAT
+ ". returning zero instead.", retVal);
return 0;
}
return retVal;
--- a/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/shared/genCollectedHeap.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -184,7 +184,7 @@
// We may support a shared contiguous allocation area, if the youngest
// generation does.
bool supports_inline_contig_alloc() const;
- HeapWord** top_addr() const;
+ HeapWord* volatile* top_addr() const;
HeapWord** end_addr() const;
// Perform a full collection of the heap; intended for use in implementing
--- a/hotspot/src/share/vm/gc/shared/generation.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/shared/generation.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -263,7 +263,7 @@
// These functions return the addresses of the fields that define the
// boundaries of the contiguous allocation area. (These fields should be
// physically near to one another.)
- virtual HeapWord** top_addr() const { return NULL; }
+ virtual HeapWord* volatile* top_addr() const { return NULL; }
virtual HeapWord** end_addr() const { return NULL; }
// Thread-local allocation buffers
--- a/hotspot/src/share/vm/gc/shared/workgroup.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/shared/workgroup.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -472,23 +472,21 @@
}
bool SequentialSubTasksDone::is_task_claimed(uint& t) {
- uint* n_claimed_ptr = &_n_claimed;
- t = *n_claimed_ptr;
+ t = _n_claimed;
while (t < _n_tasks) {
- jint res = Atomic::cmpxchg(t+1, n_claimed_ptr, t);
+ jint res = Atomic::cmpxchg(t+1, &_n_claimed, t);
if (res == (jint)t) {
return false;
}
- t = *n_claimed_ptr;
+ t = res;
}
return true;
}
bool SequentialSubTasksDone::all_tasks_completed() {
- uint* n_completed_ptr = &_n_completed;
- uint complete = *n_completed_ptr;
+ uint complete = _n_completed;
while (true) {
- uint res = Atomic::cmpxchg(complete+1, n_completed_ptr, complete);
+ uint res = Atomic::cmpxchg(complete+1, &_n_completed, complete);
if (res == complete) {
break;
}
--- a/hotspot/src/share/vm/gc/shared/workgroup.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/gc/shared/workgroup.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -318,9 +318,9 @@
// enumeration type.
class SubTasksDone: public CHeapObj<mtInternal> {
- uint* _tasks;
+ volatile uint* _tasks;
uint _n_tasks;
- uint _threads_completed;
+ volatile uint _threads_completed;
#ifdef ASSERT
volatile uint _claimed;
#endif
@@ -363,11 +363,11 @@
class SequentialSubTasksDone : public StackObj {
protected:
uint _n_tasks; // Total number of tasks available.
- uint _n_claimed; // Number of tasks claimed.
+ volatile uint _n_claimed; // Number of tasks claimed.
// _n_threads is used to determine when a sub task is done.
// See comments on SubTasksDone::_n_threads
uint _n_threads; // Total number of parallel threads.
- uint _n_completed; // Number of completed threads.
+ volatile uint _n_completed; // Number of completed threads.
void clear();
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -112,7 +112,7 @@
bool CompilerToVM::Data::_supports_inline_contig_alloc;
HeapWord** CompilerToVM::Data::_heap_end_addr;
-HeapWord** CompilerToVM::Data::_heap_top_addr;
+HeapWord* volatile* CompilerToVM::Data::_heap_top_addr;
int CompilerToVM::Data::_max_oop_map_stack_offset;
jbyte* CompilerToVM::Data::cardtable_start_address;
@@ -153,7 +153,7 @@
_supports_inline_contig_alloc = Universe::heap()->supports_inline_contig_alloc();
_heap_end_addr = _supports_inline_contig_alloc ? Universe::heap()->end_addr() : (HeapWord**) -1;
- _heap_top_addr = _supports_inline_contig_alloc ? Universe::heap()->top_addr() : (HeapWord**) -1;
+ _heap_top_addr = _supports_inline_contig_alloc ? Universe::heap()->top_addr() : (HeapWord* volatile*) -1;
_max_oop_map_stack_offset = (OopMapValue::register_mask - VMRegImpl::stack2reg(0)->value()) * VMRegImpl::stack_slot_size;
int max_oop_map_stack_index = _max_oop_map_stack_offset / VMRegImpl::stack_slot_size;
@@ -1628,4 +1628,3 @@
int CompilerToVM::methods_count() {
return sizeof(methods) / sizeof(JNINativeMethod);
}
-
--- a/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/jvmci/jvmciCompilerToVM.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -58,7 +58,7 @@
static bool _supports_inline_contig_alloc;
static HeapWord** _heap_end_addr;
- static HeapWord** _heap_top_addr;
+ static HeapWord* volatile* _heap_top_addr;
static int _max_oop_map_stack_offset;
static jbyte* cardtable_start_address;
--- a/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/jvmci/vmStructs_jvmci.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -69,7 +69,7 @@
\
static_field(CompilerToVM::Data, _supports_inline_contig_alloc, bool) \
static_field(CompilerToVM::Data, _heap_end_addr, HeapWord**) \
- static_field(CompilerToVM::Data, _heap_top_addr, HeapWord**) \
+ static_field(CompilerToVM::Data, _heap_top_addr, HeapWord* volatile*) \
\
static_field(CompilerToVM::Data, _max_oop_map_stack_offset, int) \
\
--- a/hotspot/src/share/vm/memory/filemap.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/memory/filemap.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -179,6 +179,7 @@
_classpath_entry_table_size = mapinfo->_classpath_entry_table_size;
_classpath_entry_table = mapinfo->_classpath_entry_table;
_classpath_entry_size = mapinfo->_classpath_entry_size;
+ _num_patch_mod_prefixes = ClassLoader::num_patch_mod_prefixes();
// The following fields are for sanity checks for whether this archive
// will function correctly with this JVM and the bootclasspath it's
@@ -911,11 +912,6 @@
return false;
}
- if (Arguments::get_patch_mod_prefix() != NULL) {
- FileMapInfo::fail_continue("The shared archive file cannot be used with --patch-module.");
- return false;
- }
-
if (!Arguments::has_jimage()) {
FileMapInfo::fail_continue("The shared archive file cannot be used with an exploded module build.");
return false;
@@ -952,6 +948,23 @@
return false;
}
+ // Check if there is a mismatch in --patch-module entry counts between dump time and run time.
+ // More checks will be performed on individual --patch-module entry in the
+ // SharedPathsMiscInfo::check() function.
+ GrowableArray<ModulePatchPath*>* patch_mod_args = Arguments::get_patch_mod_prefix();
+ if (patch_mod_args != NULL) {
+ if (_num_patch_mod_prefixes == 0) {
+ FileMapInfo::fail_stop("--patch-module found in run time but none was specified in dump time");
+ }
+ if (patch_mod_args->length() != _num_patch_mod_prefixes) {
+ FileMapInfo::fail_stop("mismatched --patch-module entry counts between dump time and run time");
+ }
+ } else {
+ if (_num_patch_mod_prefixes > 0) {
+ FileMapInfo::fail_stop("--patch-module specified in dump time but none was specified in run time");
+ }
+ }
+
return true;
}
--- a/hotspot/src/share/vm/memory/filemap.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/memory/filemap.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -155,6 +155,7 @@
// loading failures during runtime.
int _classpath_entry_table_size;
size_t _classpath_entry_size;
+ int _num_patch_mod_prefixes; // number of --patch-module entries
SharedClassPathEntry* _classpath_entry_table;
char* region_addr(int idx);
--- a/hotspot/src/share/vm/oops/arrayOop.cpp Mon Sep 19 15:08:03 2016 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,62 +0,0 @@
-/*
- * Copyright (c) 1997, 2012, 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.
- *
- */
-
-#include "precompiled.hpp"
-
-/////////////// Unit tests ///////////////
-
-#ifndef PRODUCT
-
-#include "oops/arrayOop.hpp"
-#include "oops/oop.inline.hpp"
-#include "utilities/globalDefinitions.hpp"
-
-bool arrayOopDesc::check_max_length_overflow(BasicType type) {
- julong length = max_array_length(type);
- julong bytes_per_element = type2aelembytes(type);
- julong bytes = length * bytes_per_element + header_size_in_bytes();
- return (julong)(size_t)bytes == bytes;
-}
-
-static void test_max_array_length() {
- assert(arrayOopDesc::check_max_length_overflow(T_BOOLEAN), "size_t overflow for boolean array");
- assert(arrayOopDesc::check_max_length_overflow(T_CHAR), "size_t overflow for char array");
- assert(arrayOopDesc::check_max_length_overflow(T_FLOAT), "size_t overflow for float array");
- assert(arrayOopDesc::check_max_length_overflow(T_DOUBLE), "size_t overflow for double array");
- assert(arrayOopDesc::check_max_length_overflow(T_BYTE), "size_t overflow for byte array");
- assert(arrayOopDesc::check_max_length_overflow(T_SHORT), "size_t overflow for short array");
- assert(arrayOopDesc::check_max_length_overflow(T_INT), "size_t overflow for int array");
- assert(arrayOopDesc::check_max_length_overflow(T_LONG), "size_t overflow for long array");
- assert(arrayOopDesc::check_max_length_overflow(T_OBJECT), "size_t overflow for object array");
- assert(arrayOopDesc::check_max_length_overflow(T_ARRAY), "size_t overflow for array array");
- assert(arrayOopDesc::check_max_length_overflow(T_NARROWOOP), "size_t overflow for narrowOop array");
-
- // T_VOID and T_ADDRESS are not supported by max_array_length()
-}
-
-void arrayOopDesc_test() {
- test_max_array_length();
-}
-
-#endif //PRODUCT
--- a/hotspot/src/share/vm/oops/arrayOop.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/oops/arrayOop.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2016, 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,6 +41,7 @@
class arrayOopDesc : public oopDesc {
friend class VMStructs;
+ friend class arrayOopDescTest;
// Interpreter/Compiler offsets
@@ -124,10 +125,6 @@
return (int32_t)max_elements_per_size_t;
}
-// for unit testing
-#ifndef PRODUCT
- static bool check_max_length_overflow(BasicType type);
-#endif
};
#endif // SHARE_VM_OOPS_ARRAYOOP_HPP
--- a/hotspot/src/share/vm/oops/instanceKlass.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -517,7 +517,11 @@
bool InstanceKlass::link_class_impl(
instanceKlassHandle this_k, bool throw_verifyerror, TRAPS) {
- // check for error state
+ // check for error state.
+ // This is checking for the wrong state. If the state is initialization_error,
+ // then this class *was* linked. The CDS code does a try_link_class and uses
+ // initialization_error to mark classes to not include in the archive during
+ // DumpSharedSpaces. This should be removed when the CDS bug is fixed.
if (this_k->is_in_error_state()) {
ResourceMark rm(THREAD);
THROW_MSG_(vmSymbols::java_lang_NoClassDefFoundError(),
@@ -670,36 +674,21 @@
// Eagerly initialize superinterfaces that declare default methods (concrete instance: any access)
void InstanceKlass::initialize_super_interfaces(instanceKlassHandle this_k, TRAPS) {
- if (this_k->has_default_methods()) {
- for (int i = 0; i < this_k->local_interfaces()->length(); ++i) {
- Klass* iface = this_k->local_interfaces()->at(i);
- InstanceKlass* ik = InstanceKlass::cast(iface);
- if (ik->should_be_initialized()) {
- if (ik->has_default_methods()) {
- ik->initialize_super_interfaces(ik, THREAD);
- }
- // Only initialize() interfaces that "declare" concrete methods.
- // has_default_methods drives searching superinterfaces since it
- // means has_default_methods in its superinterface hierarchy
- if (!HAS_PENDING_EXCEPTION && ik->declares_default_methods()) {
- ik->initialize(THREAD);
- }
- if (HAS_PENDING_EXCEPTION) {
- Handle e(THREAD, PENDING_EXCEPTION);
- CLEAR_PENDING_EXCEPTION;
- {
- EXCEPTION_MARK;
- // Locks object, set state, and notify all waiting threads
- this_k->set_initialization_state_and_notify(
- initialization_error, THREAD);
-
- // ignore any exception thrown, superclass initialization error is
- // thrown below
- CLEAR_PENDING_EXCEPTION;
- }
- THROW_OOP(e());
- }
- }
+ assert (this_k->has_default_methods(), "caller should have checked this");
+ for (int i = 0; i < this_k->local_interfaces()->length(); ++i) {
+ Klass* iface = this_k->local_interfaces()->at(i);
+ InstanceKlass* ik = InstanceKlass::cast(iface);
+
+ // Initialization is depth first search ie. we start with top of the inheritance tree
+ // has_default_methods drives searching superinterfaces since it
+ // means has_default_methods in its superinterface hierarchy
+ if (ik->has_default_methods()) {
+ ik->initialize_super_interfaces(ik, CHECK);
+ }
+
+ // Only initialize() interfaces that "declare" concrete methods.
+ if (ik->should_be_initialized() && ik->declares_default_methods()) {
+ ik->initialize(CHECK);
}
}
}
@@ -765,32 +754,36 @@
}
// Step 7
- Klass* super_klass = this_k->super();
- if (super_klass != NULL && !this_k->is_interface() && super_klass->should_be_initialized()) {
- super_klass->initialize(THREAD);
-
+ // Next, if C is a class rather than an interface, initialize it's super class and super
+ // interfaces.
+ if (!this_k->is_interface()) {
+ Klass* super_klass = this_k->super();
+ if (super_klass != NULL && super_klass->should_be_initialized()) {
+ super_klass->initialize(THREAD);
+ }
+ // If C implements any interfaces that declares a non-abstract, non-static method,
+ // the initialization of C triggers initialization of its super interfaces.
+ // Only need to recurse if has_default_methods which includes declaring and
+ // inheriting default methods
+ if (!HAS_PENDING_EXCEPTION && this_k->has_default_methods()) {
+ this_k->initialize_super_interfaces(this_k, THREAD);
+ }
+
+ // If any exceptions, complete abruptly, throwing the same exception as above.
if (HAS_PENDING_EXCEPTION) {
Handle e(THREAD, PENDING_EXCEPTION);
CLEAR_PENDING_EXCEPTION;
{
EXCEPTION_MARK;
- this_k->set_initialization_state_and_notify(initialization_error, THREAD); // Locks object, set state, and notify all waiting threads
- CLEAR_PENDING_EXCEPTION; // ignore any exception thrown, superclass initialization error is thrown below
+ // Locks object, set state, and notify all waiting threads
+ this_k->set_initialization_state_and_notify(initialization_error, THREAD);
+ CLEAR_PENDING_EXCEPTION;
}
DTRACE_CLASSINIT_PROBE_WAIT(super__failed, this_k(), -1,wait);
THROW_OOP(e());
}
}
- // If C is an interface that declares a non-abstract, non-static method,
- // the initialization of a class (not an interface) that implements C directly or
- // indirectly.
- // Recursively initialize any superinterfaces that declare default methods
- // Only need to recurse if has_default_methods which includes declaring and
- // inheriting default methods
- if (!this_k->is_interface() && this_k->has_default_methods()) {
- this_k->initialize_super_interfaces(this_k, CHECK);
- }
// Step 8
{
@@ -852,10 +845,15 @@
void InstanceKlass::set_initialization_state_and_notify_impl(instanceKlassHandle this_k, ClassState state, TRAPS) {
oop init_lock = this_k->init_lock();
- ObjectLocker ol(init_lock, THREAD, init_lock != NULL);
- this_k->set_init_state(state);
- this_k->fence_and_clear_init_lock();
- ol.notify_all(CHECK);
+ if (init_lock != NULL) {
+ ObjectLocker ol(init_lock, THREAD);
+ this_k->set_init_state(state);
+ this_k->fence_and_clear_init_lock();
+ ol.notify_all(CHECK);
+ } else {
+ assert(init_lock != NULL, "The initialization state should never be set twice");
+ this_k->set_init_state(state);
+ }
}
// The embedded _implementor field can only record one implementor.
--- a/hotspot/src/share/vm/oops/klass.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/oops/klass.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -734,27 +734,3 @@
}
#endif
-
-/////////////// Unit tests ///////////////
-
-#ifndef PRODUCT
-
-class TestKlass {
- public:
- static void test_oop_is_instanceClassLoader() {
- Klass* klass = SystemDictionary::ClassLoader_klass();
- guarantee(klass->is_instance_klass(), "assert");
- guarantee(InstanceKlass::cast(klass)->is_class_loader_instance_klass(), "test failed");
-
- klass = SystemDictionary::String_klass();
- guarantee(!klass->is_instance_klass() ||
- !InstanceKlass::cast(klass)->is_class_loader_instance_klass(),
- "test failed");
- }
-};
-
-void TestKlass_test() {
- TestKlass::test_oop_is_instanceClassLoader();
-}
-
-#endif // PRODUCT
--- a/hotspot/src/share/vm/prims/jvm.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/prims/jvm.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -562,8 +562,8 @@
}
Handle stackStream_h(THREAD, JNIHandles::resolve_non_null(stackStream));
- return StackWalk::moreFrames(stackStream_h, mode, anchor, frame_count,
- start_index, frames_array_h, THREAD);
+ return StackWalk::fetchNextBatch(stackStream_h, mode, anchor, frame_count,
+ start_index, frames_array_h, THREAD);
JVM_END
JVM_ENTRY(void, JVM_ToStackTraceElement(JNIEnv *env, jobject frame, jobject stack))
--- a/hotspot/src/share/vm/prims/jvmti.xml Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/prims/jvmti.xml Mon Sep 26 14:21:21 2016 -0400
@@ -21,7 +21,6 @@
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.
-
-->
<!DOCTYPE specification [
--- a/hotspot/src/share/vm/prims/jvmtiEnter.xsl Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiEnter.xsl Mon Sep 26 14:21:21 2016 -0400
@@ -487,8 +487,8 @@
</xsl:text>
<xsl:if test="$trace='Trace'">
<xsl:text> if (trace_flags) {
- log_trace(jvmti)("[-] %s %s", func_name,
- JvmtiUtil::error_name(JVMTI_ERROR_WRONG_PHASE));
+ log_trace(jvmti)("[-] %s %s(%d)", func_name,
+ JvmtiUtil::error_name(JVMTI_ERROR_WRONG_PHASE), JvmtiEnv::get_phase());
}
</xsl:text>
</xsl:if>
--- a/hotspot/src/share/vm/prims/jvmtiH.xsl Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiH.xsl Mon Sep 26 14:21:21 2016 -0400
@@ -95,7 +95,7 @@
</xsl:template>
<xsl:template name="intro">
- <xsl:call-template name="includeHeader"/>
+ <xsl:call-template name="include_GPL_CP_Header"/>
<xsl:text>
/* Include file for the Java(tm) Virtual Machine Tool Interface */
--- a/hotspot/src/share/vm/prims/jvmtiLib.xsl Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/prims/jvmtiLib.xsl Mon Sep 26 14:21:21 2016 -0400
@@ -43,13 +43,56 @@
<xsl:call-template name="microversion"/>
</xsl:template>
+ <xsl:variable name="GPL_header">
+ <!-- The Copyright comment from jvmti.xml -->
+ <xsl:value-of select="/comment()[position()=1]"/>
+ </xsl:variable>
+
+ <xsl:variable name="GPL_CP_header_body">
+ <xsl:text> * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
</xsl:text>
+ <xsl:text> *
</xsl:text>
+ <xsl:text> * This code is free software; you can redistribute it and/or modify it
</xsl:text>
+ <xsl:text> * under the terms of the GNU General Public License version 2 only, as
</xsl:text>
+ <xsl:text> * published by the Free Software Foundation. Oracle designates this
</xsl:text>
+ <xsl:text> * particular file as subject to the "Classpath" exception as provided
</xsl:text>
+ <xsl:text> * by Oracle in the LICENSE file that accompanied this code.
</xsl:text>
+ <xsl:text> *
</xsl:text>
+ <xsl:text> * This code is distributed in the hope that it will be useful, but WITHOUT
</xsl:text>
+ <xsl:text> * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
</xsl:text>
+ <xsl:text> * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
</xsl:text>
+ <xsl:text> * version 2 for more details (a copy is included in the LICENSE file that
</xsl:text>
+ <xsl:text> * accompanied this code).
</xsl:text>
+ <xsl:text> *
</xsl:text>
+ <xsl:text> * You should have received a copy of the GNU General Public License version
</xsl:text>
+ <xsl:text> * 2 along with this work; if not, write to the Free Software Foundation,
</xsl:text>
+ <xsl:text> * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
</xsl:text>
+ <xsl:text> *
</xsl:text>
+ <xsl:text> * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
</xsl:text>
+ <xsl:text> * or visit www.oracle.com if you need additional information or have any
</xsl:text>
+ <xsl:text> * questions.
</xsl:text>
+ </xsl:variable>
+
<xsl:template name="copyrightComment">
<xsl:text>/*</xsl:text>
- <!-- Copy the Copyright comment from jvmti.xml -->
- <xsl:value-of select="/comment()[position()=1]"/>
+ <!-- The Copyright comment from jvmti.xml -->
+ <xsl:value-of select="$GPL_header"/>
<xsl:text> */

</xsl:text>
</xsl:template>
+ <xsl:template name="GPL_CP_copyrightComment">
+ <xsl:text>/*
 *</xsl:text>
+ <!-- The Copyright year from jvmti.xml -->
+ <xsl:value-of select="substring-after(substring-before($GPL_header, ' DO NOT ALTER'), '
')"/>
+ <!-- The GPL+CP Copyright header body -->
+ <xsl:value-of select="$GPL_CP_header_body"/>
+ <xsl:text> */

</xsl:text>
+ </xsl:template>
+
+ <xsl:template name="include_GPL_CP_Header">
+ <xsl:call-template name="GPL_CP_copyrightComment"/>
+ <xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
</xsl:text>
+ </xsl:template>
+
<xsl:template name="includeHeader">
<xsl:call-template name="copyrightComment"/>
<xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
</xsl:text>
--- a/hotspot/src/share/vm/prims/stackwalk.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/prims/stackwalk.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -37,42 +37,47 @@
#include "utilities/globalDefinitions.hpp"
// setup and cleanup actions
-void JavaFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
+void BaseFrameStream::setup_magic_on_entry(objArrayHandle frames_array) {
frames_array->obj_at_put(magic_pos, _thread->threadObj());
_anchor = address_value();
assert(check_magic(frames_array), "invalid magic");
}
-bool JavaFrameStream::check_magic(objArrayHandle frames_array) {
+bool BaseFrameStream::check_magic(objArrayHandle frames_array) {
oop m1 = frames_array->obj_at(magic_pos);
jlong m2 = _anchor;
if (m1 == _thread->threadObj() && m2 == address_value()) return true;
return false;
}
-bool JavaFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) {
+bool BaseFrameStream::cleanup_magic_on_exit(objArrayHandle frames_array) {
bool ok = check_magic(frames_array);
frames_array->obj_at_put(magic_pos, NULL);
_anchor = 0L;
return ok;
}
-// Returns JavaFrameStream for the current stack being traversed.
+JavaFrameStream::JavaFrameStream(JavaThread* thread, int mode)
+ : BaseFrameStream(thread), _vfst(thread) {
+ _need_method_info = StackWalk::need_method_info(mode);
+}
+
+// Returns the BaseFrameStream for the current stack being traversed.
//
// Parameters:
// thread Current Java thread.
// magic Magic value used for each stack walking
// frames_array User-supplied buffers. The 0th element is reserved
-// to this JavaFrameStream to use
+// for this BaseFrameStream to use
//
-JavaFrameStream* JavaFrameStream::from_current(JavaThread* thread, jlong magic,
+BaseFrameStream* BaseFrameStream::from_current(JavaThread* thread, jlong magic,
objArrayHandle frames_array)
{
assert(thread != NULL && thread->is_Java_thread(), "");
oop m1 = frames_array->obj_at(magic_pos);
if (m1 != thread->threadObj()) return NULL;
if (magic == 0L) return NULL;
- JavaFrameStream* stream = (JavaFrameStream*) (intptr_t) magic;
+ BaseFrameStream* stream = (BaseFrameStream*) (intptr_t) magic;
if (!stream->is_valid_in(thread, frames_array)) return NULL;
return stream;
}
@@ -85,7 +90,7 @@
//
// Parameters:
// mode Restrict which frames to be decoded.
-// JavaFrameStream stream of javaVFrames
+// BaseFrameStream stream of frames
// max_nframes Maximum number of frames to be filled.
// start_index Start index to the user-supplied buffers.
// frames_array Buffer to store Class or StackFrame in, starting at start_index.
@@ -96,7 +101,7 @@
//
// Returns the number of frames whose information was transferred into the buffers.
//
-int StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream,
+int StackWalk::fill_in_frames(jlong mode, BaseFrameStream& stream,
int max_nframes, int start_index,
objArrayHandle frames_array,
int& end_index, TRAPS) {
@@ -110,7 +115,6 @@
int frames_decoded = 0;
for (; !stream.at_end(); stream.next()) {
Method* method = stream.method();
- int bci = stream.bci();
if (method == NULL) continue;
@@ -129,35 +133,42 @@
int index = end_index++;
if (TraceStackWalk) {
tty->print(" %d: frame method: ", index); method->print_short_name();
- tty->print_cr(" bci=%d", bci);
+ tty->print_cr(" bci=%d", stream.bci());
}
+ if (!need_method_info(mode) && get_caller_class(mode) &&
+ index == start_index && method->caller_sensitive()) {
+ ResourceMark rm(THREAD);
+ THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),
+ err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method",
+ method->name_and_sig_as_C_string()));
+ }
// fill in StackFrameInfo and initialize MemberName
- if (live_frame_info(mode)) {
- assert (use_frames_array(mode), "Bad mode for get live frame");
- Handle stackFrame(frames_array->obj_at(index));
- fill_live_stackframe(stackFrame, method, bci, stream.java_frame(), CHECK_0);
- } else if (need_method_info(mode)) {
- assert (use_frames_array(mode), "Bad mode for get stack frame");
- Handle stackFrame(frames_array->obj_at(index));
- fill_stackframe(stackFrame, method, bci);
- } else {
- assert (use_frames_array(mode) == false, "Bad mode for filling in Class object");
- if (get_caller_class(mode) && index == start_index && method->caller_sensitive()) {
- ResourceMark rm(THREAD);
- THROW_MSG_0(vmSymbols::java_lang_UnsupportedOperationException(),
- err_msg("StackWalker::getCallerClass called from @CallerSensitive %s method",
- method->name_and_sig_as_C_string()));
- }
-
- frames_array->obj_at_put(index, method->method_holder()->java_mirror());
- }
+ stream.fill_frame(index, frames_array, method, CHECK_0);
if (++frames_decoded >= max_nframes) break;
}
return frames_decoded;
}
-static oop create_primitive_value_instance(StackValueCollection* values, int i, TRAPS) {
+// Fill in the LiveStackFrameInfo at the given index in frames_array
+void LiveFrameStream::fill_frame(int index, objArrayHandle frames_array,
+ const methodHandle& method, TRAPS) {
+ Handle stackFrame(THREAD, frames_array->obj_at(index));
+ fill_live_stackframe(stackFrame, method, CHECK);
+}
+
+// Fill in the StackFrameInfo at the given index in frames_array
+void JavaFrameStream::fill_frame(int index, objArrayHandle frames_array,
+ const methodHandle& method, TRAPS) {
+ if (_need_method_info) {
+ Handle stackFrame(THREAD, frames_array->obj_at(index));
+ fill_stackframe(stackFrame, method);
+ } else {
+ frames_array->obj_at_put(index, method->method_holder()->java_mirror());
+ }
+}
+
+oop LiveFrameStream::create_primitive_value_instance(StackValueCollection* values, int i, TRAPS) {
Klass* k = SystemDictionary::resolve_or_null(vmSymbols::java_lang_LiveStackFrameInfo(), CHECK_NULL);
instanceKlassHandle ik (THREAD, k);
@@ -228,7 +239,7 @@
return (instanceOop) result.get_jobject();
}
-static objArrayHandle values_to_object_array(StackValueCollection* values, TRAPS) {
+objArrayHandle LiveFrameStream::values_to_object_array(StackValueCollection* values, TRAPS) {
objArrayHandle empty;
int length = values->size();
objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(),
@@ -243,7 +254,7 @@
return array_h;
}
-static objArrayHandle monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors, TRAPS) {
+objArrayHandle LiveFrameStream::monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors, TRAPS) {
int length = monitors->length();
objArrayOop array_oop = oopFactory::new_objArray(SystemDictionary::Object_klass(),
length, CHECK_(objArrayHandle()));
@@ -256,19 +267,19 @@
}
// Fill StackFrameInfo with declaringClass and bci and initialize memberName
-void StackWalk::fill_stackframe(Handle stackFrame, const methodHandle& method, int bci) {
+void BaseFrameStream::fill_stackframe(Handle stackFrame, const methodHandle& method) {
java_lang_StackFrameInfo::set_declaringClass(stackFrame(), method->method_holder()->java_mirror());
- java_lang_StackFrameInfo::set_method_and_bci(stackFrame(), method, bci);
+ java_lang_StackFrameInfo::set_method_and_bci(stackFrame(), method, bci());
}
// Fill LiveStackFrameInfo with locals, monitors, and expressions
-void StackWalk::fill_live_stackframe(Handle stackFrame, const methodHandle& method,
- int bci, javaVFrame* jvf, TRAPS) {
- fill_stackframe(stackFrame, method, bci);
- if (jvf != NULL) {
- StackValueCollection* locals = jvf->locals();
- StackValueCollection* expressions = jvf->expressions();
- GrowableArray<MonitorInfo*>* monitors = jvf->monitors();
+void LiveFrameStream::fill_live_stackframe(Handle stackFrame,
+ const methodHandle& method, TRAPS) {
+ fill_stackframe(stackFrame, method);
+ if (_jvf != NULL) {
+ StackValueCollection* locals = _jvf->locals();
+ StackValueCollection* expressions = _jvf->expressions();
+ GrowableArray<MonitorInfo*>* monitors = _jvf->monitors();
if (!locals->is_empty()) {
objArrayHandle locals_h = values_to_object_array(locals, CHECK);
@@ -315,15 +326,28 @@
THROW_MSG_(vmSymbols::java_lang_NullPointerException(), "frames_array is NULL", NULL);
}
- Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
- Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
+ // Setup traversal onto my stack.
+ if (live_frame_info(mode)) {
+ assert (use_frames_array(mode), "Bad mode for get live frame");
+ RegisterMap regMap(jt, true);
+ LiveFrameStream stream(jt, ®Map);
+ return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
+ start_index, frames_array, THREAD);
+ } else {
+ JavaFrameStream stream(jt, mode);
+ return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
+ start_index, frames_array, THREAD);
+ }
+}
+oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
+ jlong mode, int skip_frames, int frame_count,
+ int start_index, objArrayHandle frames_array, TRAPS) {
methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
- // Setup traversal onto my stack.
- RegisterMap regMap(jt, true);
- JavaFrameStream stream(jt, ®Map);
{
+ Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
+ Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
while (!stream.at_end()) {
InstanceKlass* ik = stream.method()->method_holder();
if (ik != stackWalker_klass &&
@@ -341,10 +365,7 @@
// from the stack frame at depth == skip_frames.
for (int n=0; n < skip_frames && !stream.at_end(); stream.next(), n++) {
if (TraceStackWalk) {
- tty->print(" skip "); stream.method()->print_short_name();
- tty->print_cr(" frame id: " PTR_FORMAT " pc: " PTR_FORMAT,
- p2i(stream.java_frame()->fr().id()),
- p2i(stream.java_frame()->fr().pc()));
+ tty->print(" skip "); stream.method()->print_short_name(); tty->cr();
}
}
}
@@ -402,13 +423,13 @@
//
// Returns the end index of frame filled in the buffer.
//
-jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
- int frame_count, int start_index,
- objArrayHandle frames_array,
- TRAPS)
+jint StackWalk::fetchNextBatch(Handle stackStream, jlong mode, jlong magic,
+ int frame_count, int start_index,
+ objArrayHandle frames_array,
+ TRAPS)
{
JavaThread* jt = (JavaThread*)THREAD;
- JavaFrameStream* existing_stream = JavaFrameStream::from_current(jt, magic, frames_array);
+ BaseFrameStream* existing_stream = BaseFrameStream::from_current(jt, magic, frames_array);
if (existing_stream == NULL) {
THROW_MSG_(vmSymbols::java_lang_InternalError(), "doStackWalk: corrupted buffers", 0L);
}
@@ -418,7 +439,7 @@
}
if (TraceStackWalk) {
- tty->print_cr("StackWalk::moreFrames frame_count %d existing_stream " PTR_FORMAT " start %d frames %d",
+ tty->print_cr("StackWalk::fetchNextBatch frame_count %d existing_stream " PTR_FORMAT " start %d frames %d",
frame_count, p2i(existing_stream), start_index, frames_array->length());
}
int end_index = start_index;
@@ -429,7 +450,7 @@
int count = frame_count + start_index;
assert (frames_array->length() >= count, "not enough space in buffers");
- JavaFrameStream& stream = (*existing_stream);
+ BaseFrameStream& stream = (*existing_stream);
if (!stream.at_end()) {
stream.next(); // advance past the last frame decoded in previous batch
if (!stream.at_end()) {
--- a/hotspot/src/share/vm/prims/stackwalk.hpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/prims/stackwalk.hpp Mon Sep 26 14:21:21 2016 -0400
@@ -29,31 +29,34 @@
#include "oops/oop.hpp"
#include "runtime/vframe.hpp"
-//
-// JavaFrameStream is used by StackWalker to iterate through Java stack frames
-// on the given JavaThread.
-//
-class JavaFrameStream : public StackObj {
+// BaseFrameStream is an abstract base class for encapsulating the VM-side
+// implementation of the StackWalker API. There are two concrete subclasses:
+// - JavaFrameStream:
+// -based on vframeStream; used in most instances
+// - LiveFrameStream:
+// -based on javaVFrame; used for retrieving locals/monitors/operands for
+// LiveStackFrame
+class BaseFrameStream : public StackObj {
private:
enum {
magic_pos = 0
};
JavaThread* _thread;
- javaVFrame* _jvf;
jlong _anchor;
+protected:
+ void fill_stackframe(Handle stackFrame, const methodHandle& method);
public:
- JavaFrameStream(JavaThread* thread, RegisterMap* rm)
- : _thread(thread), _anchor(0L) {
- _jvf = _thread->last_java_vframe(rm);
- }
+ BaseFrameStream(JavaThread* thread) : _thread(thread), _anchor(0L) {}
+
+ virtual void next()=0;
+ virtual bool at_end()=0;
- javaVFrame* java_frame() { return _jvf; }
- void next() { _jvf = _jvf->java_sender(); }
- bool at_end() { return _jvf == NULL; }
+ virtual Method* method()=0;
+ virtual int bci()=0;
- Method* method() { return _jvf->method(); }
- int bci() { return _jvf->bci(); }
+ virtual void fill_frame(int index, objArrayHandle frames_array,
+ const methodHandle& method, TRAPS)=0;
void setup_magic_on_entry(objArrayHandle frames_array);
bool check_magic(objArrayHandle frames_array);
@@ -67,35 +70,72 @@
return (jlong) castable_address(this);
}
- static JavaFrameStream* from_current(JavaThread* thread, jlong magic, objArrayHandle frames_array);
+ static BaseFrameStream* from_current(JavaThread* thread, jlong magic, objArrayHandle frames_array);
+};
+
+class JavaFrameStream : public BaseFrameStream {
+private:
+ vframeStream _vfst;
+ bool _need_method_info;
+public:
+ JavaFrameStream(JavaThread* thread, int mode);
+
+ void next() { _vfst.next();}
+ bool at_end() { return _vfst.at_end(); }
+
+ Method* method() { return _vfst.method(); }
+ int bci() { return _vfst.bci(); }
+
+ void fill_frame(int index, objArrayHandle frames_array,
+ const methodHandle& method, TRAPS);
+};
+
+class LiveFrameStream : public BaseFrameStream {
+private:
+ javaVFrame* _jvf;
+
+ void fill_live_stackframe(Handle stackFrame, const methodHandle& method, TRAPS);
+ static oop create_primitive_value_instance(StackValueCollection* values,
+ int i, TRAPS);
+ static objArrayHandle monitors_to_object_array(GrowableArray<MonitorInfo*>* monitors,
+ TRAPS);
+ static objArrayHandle values_to_object_array(StackValueCollection* values, TRAPS);
+public:
+ LiveFrameStream(JavaThread* thread, RegisterMap* rm) : BaseFrameStream(thread) {
+ _jvf = thread->last_java_vframe(rm);
+ }
+
+ void next() { _jvf = _jvf->java_sender(); }
+ bool at_end() { return _jvf == NULL; }
+
+ Method* method() { return _jvf->method(); }
+ int bci() { return _jvf->bci(); }
+
+ void fill_frame(int index, objArrayHandle frames_array,
+ const methodHandle& method, TRAPS);
};
class StackWalk : public AllStatic {
private:
- static int fill_in_frames(jlong mode, JavaFrameStream& stream,
+ static int fill_in_frames(jlong mode, BaseFrameStream& stream,
int max_nframes, int start_index,
objArrayHandle frames_array,
int& end_index, TRAPS);
- static void fill_stackframe(Handle stackFrame, const methodHandle& method, int bci);
-
- static void fill_live_stackframe(Handle stackFrame, const methodHandle& method, int bci,
- javaVFrame* jvf, TRAPS);
-
static inline bool get_caller_class(int mode) {
return (mode & JVM_STACKWALK_GET_CALLER_CLASS) != 0;
}
static inline bool skip_hidden_frames(int mode) {
return (mode & JVM_STACKWALK_SHOW_HIDDEN_FRAMES) == 0;
}
- static inline bool need_method_info(int mode) {
- return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0;
- }
static inline bool live_frame_info(int mode) {
return (mode & JVM_STACKWALK_FILL_LIVE_STACK_FRAMES) != 0;
}
public:
+ static inline bool need_method_info(int mode) {
+ return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0;
+ }
static inline bool use_frames_array(int mode) {
return (mode & JVM_STACKWALK_FILL_CLASS_REFS_ONLY) == 0;
}
@@ -104,9 +144,12 @@
objArrayHandle frames_array,
TRAPS);
- static jint moreFrames(Handle stackStream, jlong mode, jlong magic,
- int frame_count, int start_index,
- objArrayHandle frames_array,
- TRAPS);
+ static oop fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
+ jlong mode, int skip_frames, int frame_count,
+ int start_index, objArrayHandle frames_array, TRAPS);
+
+ static jint fetchNextBatch(Handle stackStream, jlong mode, jlong magic,
+ int frame_count, int start_index,
+ objArrayHandle frames_array, TRAPS);
};
#endif // SHARE_VM_PRIMS_STACKWALK_HPP
--- a/hotspot/src/share/vm/runtime/arguments.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/runtime/arguments.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -3897,10 +3897,6 @@
void Arguments::set_shared_spaces_flags() {
if (DumpSharedSpaces) {
- if (Arguments::get_patch_mod_prefix() != NULL) {
- vm_exit_during_initialization(
- "Cannot use the following option when dumping the shared archive: --patch-module");
- }
if (RequireSharedSpaces) {
warning("Cannot dump shared archive while using shared archive");
--- a/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/runtime/vmStructs.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -2972,6 +2972,7 @@
#if INCLUDE_ALL_GCS
VM_STRUCTS_PARALLELGC(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
+ GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
GENERATE_STATIC_VM_STRUCT_ENTRY)
VM_STRUCTS_CMS(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
@@ -2984,7 +2985,7 @@
#if INCLUDE_TRACE
VM_STRUCTS_TRACE(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
- GENERATE_STATIC_VM_STRUCT_ENTRY)
+ GENERATE_STATIC_VM_STRUCT_ENTRY)
#endif
VM_STRUCTS_EXT(GENERATE_NONSTATIC_VM_STRUCT_ENTRY,
@@ -3170,11 +3171,12 @@
#if INCLUDE_ALL_GCS
VM_STRUCTS_PARALLELGC(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
- CHECK_STATIC_VM_STRUCT_ENTRY);
+ CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY,
+ CHECK_STATIC_VM_STRUCT_ENTRY);
VM_STRUCTS_CMS(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
- CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY,
- CHECK_STATIC_VM_STRUCT_ENTRY);
+ CHECK_VOLATILE_NONSTATIC_VM_STRUCT_ENTRY,
+ CHECK_STATIC_VM_STRUCT_ENTRY);
VM_STRUCTS_G1(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
CHECK_STATIC_VM_STRUCT_ENTRY);
@@ -3183,7 +3185,7 @@
#if INCLUDE_TRACE
VM_STRUCTS_TRACE(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
- CHECK_STATIC_VM_STRUCT_ENTRY);
+ CHECK_STATIC_VM_STRUCT_ENTRY);
#endif
VM_STRUCTS_EXT(CHECK_NONSTATIC_VM_STRUCT_ENTRY,
@@ -3295,6 +3297,7 @@
CHECK_NO_OP));
#if INCLUDE_ALL_GCS
debug_only(VM_STRUCTS_PARALLELGC(ENSURE_FIELD_TYPE_PRESENT,
+ ENSURE_FIELD_TYPE_PRESENT,
ENSURE_FIELD_TYPE_PRESENT));
debug_only(VM_STRUCTS_CMS(ENSURE_FIELD_TYPE_PRESENT,
ENSURE_FIELD_TYPE_PRESENT,
--- a/hotspot/src/share/vm/utilities/internalVMTests.cpp Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/src/share/vm/utilities/internalVMTests.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -52,17 +52,14 @@
run_unit_test(TestVirtualSpaceNode_test);
run_unit_test(TestGlobalDefinitions_test);
run_unit_test(GCTimer_test);
- run_unit_test(arrayOopDesc_test);
run_unit_test(CollectedHeap_test);
run_unit_test(QuickSort_test);
run_unit_test(GuardedMemory_test);
run_unit_test(TestNewSize_test);
run_unit_test(TestOldSize_test);
- run_unit_test(TestKlass_test);
run_unit_test(TestBitMap_test);
run_unit_test(TestResourcehash_test);
run_unit_test(ObjectMonitor_test);
- run_unit_test(Test_linked_list);
run_unit_test(TestChunkedList_test);
run_unit_test(Test_log_tag_combinations_limit);
run_unit_test(Test_logtarget);
@@ -81,7 +78,6 @@
run_unit_test(Test_invalid_log_file);
run_unit_test(Test_multiline_logging);
run_unit_test(DirectivesParser_test);
- run_unit_test(Test_TempNewSymbol);
#if INCLUDE_VM_STRUCTS
run_unit_test(VMStructs_test);
#endif
--- a/hotspot/src/share/vm/utilities/linkedlist.cpp Mon Sep 19 15:08:03 2016 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,114 +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.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- *
- */
-
-#include "precompiled.hpp"
-
-/////////////// Unit tests ///////////////
-
-#ifndef PRODUCT
-
-#include "runtime/os.hpp"
-#include "utilities/linkedlist.hpp"
-#include "memory/allocation.hpp"
-#include "memory/allocation.inline.hpp"
-
-class Integer : public StackObj {
- private:
- int _value;
- public:
- Integer(int i) : _value(i) { }
-
- int value() const { return _value; }
- bool equals(const Integer& i) const {
- return _value == i.value();
- }
-};
-
-int compare_Integer(const Integer& i1, const Integer& i2) {
- return i1.value() - i2.value();
-}
-
-void check_list_values(const int* expected, const LinkedList<Integer>* list) {
- LinkedListNode<Integer>* head = list->head();
- int index = 0;
- while (head != NULL) {
- assert(head->peek()->value() == expected[index], "Unexpected value");
- head = head->next();
- index ++;
- }
-}
-
-void Test_linked_list() {
- LinkedListImpl<Integer, ResourceObj::C_HEAP, mtTest> ll;
-
-
- // Test regular linked list
- assert(ll.is_empty(), "Start with empty list");
- Integer one(1), two(2), three(3), four(4), five(5), six(6);
-
- ll.add(six);
- assert(!ll.is_empty(), "Should not be empty");
-
- Integer* i = ll.find(six);
- assert(i != NULL, "Should find it");
-
- i = ll.find(three);
- assert(i == NULL, "Not in the list");
-
- LinkedListNode<Integer>* node = ll.find_node(six);
- assert(node != NULL, "6 is in the list");
-
- ll.insert_after(three, node);
- ll.insert_before(one, node);
- int expected[3] = {1, 6, 3};
- check_list_values(expected, &ll);
-
- ll.add(two);
- ll.add(four);
- ll.add(five);
-
- // Test sorted linked list
- SortedLinkedList<Integer, compare_Integer, ResourceObj::C_HEAP, mtTest> sl;
- assert(sl.is_empty(), "Start with empty list");
-
- size_t ll_size = ll.size();
- sl.move(&ll);
- size_t sl_size = sl.size();
-
- assert(ll_size == sl_size, "Should be the same size");
- assert(ll.is_empty(), "No more entires");
-
- // sorted result
- int sorted_result[] = {1, 2, 3, 4, 5, 6};
- check_list_values(sorted_result, &sl);
-
- node = sl.find_node(four);
- assert(node != NULL, "4 is in the list");
- sl.remove_before(node);
- sl.remove_after(node);
- int remains[] = {1, 2, 4, 6};
- check_list_values(remains, &sl);
-}
-#endif // PRODUCT
-
--- a/hotspot/test/TEST.groups Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/test/TEST.groups Mon Sep 26 14:21:21 2016 -0400
@@ -351,16 +351,29 @@
hotspot_fast_runtime = \
runtime/ \
+ -runtime/6626217/Test6626217.sh \
+ -runtime/7100935 \
+ -runtime/7158988/FieldMonitor.java \
+ -runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \
+ -runtime/CommandLine/PrintGCApplicationConcurrentTime.java \
+ -runtime/ConstantPool/IntfMethod.java \
+ -runtime/ErrorHandling/CreateCoredumpOnCrash.java \
-runtime/ErrorHandling/ErrorHandler.java \
- -runtime/RedefineObject/TestRedefineObject.java \
- -runtime/MirrorFrame/Test8003720.java \
+ -runtime/logging/MonitorMismatchTest.java \
+ -runtime/memory/ReserveMemory.java \
+ -runtime/memory/RunUnitTestsConcurrently.java \
-runtime/Metaspace/FragmentMetaspace.java \
-runtime/Metaspace/FragmentMetaspaceSimple.java \
- -runtime/Thread/TestThreadDumpMonitorContention.java \
- -runtime/SharedArchiveFile/SharedBaseAddress.java \
- -runtime/memory/ReserveMemory.java \
- -runtime/memory/RunUnitTestsConcurrently.java \
- -runtime/Unsafe/RangeCheck.java \
+ -runtime/MirrorFrame/Test8003720.java \
+ -runtime/modules/LoadUnloadModuleStress.java \
+ -runtime/modules/ModuleStress/ExportModuleStressTest.java \
+ -runtime/modules/ModuleStress/ModuleStressGC.java \
+ -runtime/NMT \
+ -runtime/RedefineObject/TestRedefineObject.java \
+ -runtime/RedefineTests/RedefinePreviousVersions.java \
+ -runtime/RedefineTests/RedefineRunningMethods.java \
+ -runtime/RedefineTests/RedefineRunningMethodsWithBacktrace.java \
+ -runtime/ReservedStack \
-runtime/SelectionResolution/AbstractMethodErrorTest.java \
-runtime/SelectionResolution/IllegalAccessErrorTest.java \
-runtime/SelectionResolution/InvokeInterfaceICCE.java \
@@ -372,14 +385,14 @@
-runtime/SelectionResolution/InvokeVirtualSuccessTest.java \
-runtime/SharedArchiveFile/CdsSameObjectAlignment.java \
-runtime/SharedArchiveFile/DefaultUseWithClient.java \
+ -runtime/SharedArchiveFile/SharedBaseAddress.java \
-runtime/Thread/CancellableThreadTest.java \
- -runtime/7158988/FieldMonitor.java \
- -runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \
+ -runtime/Thread/TestThreadDumpMonitorContention.java \
+ -runtime/Unsafe/RangeCheck.java \
sanity/ \
testlibrary_tests/TestMutuallyExclusivePlatformPredicates.java
hotspot_fast_serviceability = \
- sanity/ExecuteInternalVMTests.java \
serviceability/dcmd/compiler \
serviceability/logging
@@ -398,6 +411,8 @@
hotspot_runtime_tier2 = \
runtime/ \
serviceability/ \
+ -runtime/CommandLine/OptionsValidation/TestOptionsWithRanges.java \
+ -runtime/Thread/TestThreadDumpMonitorContention.java \
-:hotspot_fast_runtime \
-:hotspot_fast_serviceability \
-:hotspot_runtime_tier2_platform_agnostic
@@ -405,6 +420,14 @@
hotspot_runtime_tier2_platform_agnostic = \
runtime/SelectionResolution \
-:hotspot_fast_runtime
+
+hotspot_runtime_tier3 = \
+ runtime/ \
+ serviceability/ \
+ -:hotspot_fast_runtime \
+ -:hotspot_fast_serviceability \
+ -:hotspot_runtime_tier2_platform_agnostic \
+ -:hotspot_runtime_tier2
hotspot_runtime_minimalvm = \
runtime/MinimalVM \
--- a/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/test/compiler/codecache/stress/OverloadCompileQueueTest.java Mon Sep 26 14:21:21 2016 -0400
@@ -29,7 +29,7 @@
* @modules java.base/jdk.internal.misc
* java.management
*
- * @ignore 8071905
+ * @ignore 8166554
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* sun.hotspot.WhiteBox$WhiteBoxPermission
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/native/classfile/test_symbolTable.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+#include "precompiled.hpp"
+#include "runtime/interfaceSupport.hpp"
+#include "classfile/symbolTable.hpp"
+#include "unittest.hpp"
+
+TEST(SymbolTable, temp_new_symbol) {
+ // Assert messages assume these symbols are unique, and the refcounts start at
+ // one, but code does not rely on this.
+ JavaThread* THREAD = JavaThread::current();
+ // the thread should be in vm to use locks
+ ThreadInVMfromNative ThreadInVMfromNative(THREAD);
+
+ Symbol* abc = SymbolTable::new_symbol("abc", CATCH);
+ int abccount = abc->refcount();
+ TempNewSymbol ss = abc;
+ ASSERT_EQ(ss->refcount(), abccount) << "only one abc";
+ ASSERT_EQ(ss->refcount(), abc->refcount()) << "should match TempNewSymbol";
+
+ Symbol* efg = SymbolTable::new_symbol("efg", CATCH);
+ Symbol* hij = SymbolTable::new_symbol("hij", CATCH);
+ int efgcount = efg->refcount();
+ int hijcount = hij->refcount();
+
+ TempNewSymbol s1 = efg;
+ TempNewSymbol s2 = hij;
+ ASSERT_EQ(s1->refcount(), efgcount) << "one efg";
+ ASSERT_EQ(s2->refcount(), hijcount) << "one hij";
+
+ // Assignment operator
+ s1 = s2;
+ ASSERT_EQ(hij->refcount(), hijcount + 1) << "should be two hij";
+ ASSERT_EQ(efg->refcount(), efgcount - 1) << "should be no efg";
+
+ s1 = ss; // s1 is abc
+ ASSERT_EQ(s1->refcount(), abccount + 1) << "should be two abc (s1 and ss)";
+ ASSERT_EQ(hij->refcount(), hijcount) << "should only have one hij now (s2)";
+
+ s1 = s1; // self assignment
+ ASSERT_EQ(s1->refcount(), abccount + 1) << "should still be two abc (s1 and ss)";
+
+ TempNewSymbol s3;
+ Symbol* klm = SymbolTable::new_symbol("klm", CATCH);
+ int klmcount = klm->refcount();
+ s3 = klm; // assignment
+ ASSERT_EQ(s3->refcount(), klmcount) << "only one klm now";
+
+ Symbol* xyz = SymbolTable::new_symbol("xyz", CATCH);
+ int xyzcount = xyz->refcount();
+ { // inner scope
+ TempNewSymbol s_inner = xyz;
+ }
+ ASSERT_EQ(xyz->refcount(), xyzcount - 1)
+ << "Should have been decremented by dtor in inner scope";
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/native/oops/test_arrayOop.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,89 @@
+/*
+ * Copyright (c) 1997, 2016, 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.
+ */
+
+#include "precompiled.hpp"
+#include "oops/arrayOop.hpp"
+#include "oops/oop.inline.hpp"
+#include "unittest.hpp"
+#include "utilities/globalDefinitions.hpp"
+
+class arrayOopDescTest {
+ public:
+
+ static int header_size_in_bytes() {
+ return arrayOopDesc::header_size_in_bytes();
+ }
+};
+
+static bool check_max_length_overflow(BasicType type) {
+ julong length = arrayOopDesc::max_array_length(type);
+ julong bytes_per_element = type2aelembytes(type);
+ julong bytes = length * bytes_per_element
+ + arrayOopDescTest::header_size_in_bytes();
+ return (julong) (size_t) bytes == bytes;
+}
+
+TEST(arrayOopDesc, boolean) {
+ ASSERT_PRED1(check_max_length_overflow, T_BOOLEAN);
+}
+
+TEST(arrayOopDesc, char) {
+ ASSERT_PRED1(check_max_length_overflow, T_CHAR);
+}
+
+TEST(arrayOopDesc, float) {
+ ASSERT_PRED1(check_max_length_overflow, T_FLOAT);
+}
+
+TEST(arrayOopDesc, double) {
+ ASSERT_PRED1(check_max_length_overflow, T_DOUBLE);
+}
+
+TEST(arrayOopDesc, byte) {
+ ASSERT_PRED1(check_max_length_overflow, T_BYTE);
+}
+
+TEST(arrayOopDesc, short) {
+ ASSERT_PRED1(check_max_length_overflow, T_SHORT);
+}
+
+TEST(arrayOopDesc, int) {
+ ASSERT_PRED1(check_max_length_overflow, T_INT);
+}
+
+TEST(arrayOopDesc, long) {
+ ASSERT_PRED1(check_max_length_overflow, T_LONG);
+}
+
+TEST(arrayOopDesc, object) {
+ ASSERT_PRED1(check_max_length_overflow, T_OBJECT);
+}
+
+TEST(arrayOopDesc, array) {
+ ASSERT_PRED1(check_max_length_overflow, T_ARRAY);
+}
+
+TEST(arrayOopDesc, narrowOop) {
+ ASSERT_PRED1(check_max_length_overflow, T_NARROWOOP);
+}
+// T_VOID and T_ADDRESS are not supported by max_array_length()
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/native/oops/test_instanceKlass.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,47 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+#include "precompiled.hpp"
+#include "classfile/symbolTable.hpp"
+#include "classfile/systemDictionary.hpp"
+#include "memory/resourceArea.hpp"
+#include "oops/instanceKlass.hpp"
+#include "unittest.hpp"
+
+// Tests InstanceKlass::package_from_name()
+TEST_VM(InstanceKlass, null_symbol) {
+ ResourceMark rm;
+ TempNewSymbol package_sym = InstanceKlass::package_from_name(NULL, NULL);
+ ASSERT_TRUE(package_sym == NULL) << "Wrong package for NULL symbol";
+}
+
+// Tests for InstanceKlass::is_class_loader_instance_klass() function
+TEST_VM(InstanceKlass, class_loader_class) {
+ InstanceKlass* klass = SystemDictionary::ClassLoader_klass();
+ ASSERT_TRUE(klass->is_class_loader_instance_klass());
+}
+
+TEST_VM(InstanceKlass, string_klass) {
+ InstanceKlass* klass = SystemDictionary::String_klass();
+ ASSERT_TRUE(!klass->is_class_loader_instance_klass());
+}
--- a/hotspot/test/native/runtime/test_instanceKlass.cpp Mon Sep 19 15:08:03 2016 +0200
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,36 +0,0 @@
-/*
- * Copyright (c) 2016, 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.
- *
- */
-
-#include "precompiled.hpp"
-#include "classfile/symbolTable.hpp"
-#include "memory/resourceArea.hpp"
-#include "oops/instanceKlass.hpp"
-#include "unittest.hpp"
-
-// Tests InstanceKlass::package_from_name()
-TEST_VM(instanceKlass, null_symbol) {
- ResourceMark rm;
- TempNewSymbol package_sym = InstanceKlass::package_from_name(NULL, NULL);
- ASSERT_TRUE(package_sym == NULL) << "Wrong package for NULL symbol";
-}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/native/utilities/test_linkedlist.cpp Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2011, 2016, 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.
+
+ */
+
+#include "precompiled.hpp"
+#include "unittest.hpp"
+#include "utilities/linkedlist.hpp"
+
+class Integer : public StackObj {
+ private:
+ int _value;
+ public:
+
+ Integer(int i) : _value(i) {
+ }
+
+ int value() const {
+ return _value;
+ }
+
+ bool equals(const Integer& i) const {
+ return _value == i.value();
+ }
+
+ static int compare(const Integer& i1, const Integer& i2) {
+ return i1.value() - i2.value();
+ }
+};
+
+static void check_list_values(const int* expected, const LinkedList<Integer>* list) {
+ LinkedListNode<Integer>* head = list->head();
+ int index = 0;
+ while (head != NULL) {
+ ASSERT_EQ(expected[index], head->peek()->value())
+ << "Unexpected value at index " << index;
+ head = head->next();
+ index++;
+ }
+}
+
+const Integer one(1), two(2), three(3), four(4), five(5), six(6);
+
+// Test regular linked list
+TEST(LinkedList, simple) {
+ LinkedListImpl<Integer, ResourceObj::C_HEAP, mtTest> ll;
+
+ ASSERT_TRUE(ll.is_empty()) << "Start with empty list";
+
+ ll.add(six);
+ ASSERT_TRUE(!ll.is_empty()) << "Should not be empty";
+
+ Integer* i = ll.find(six);
+ ASSERT_TRUE(i != NULL) << "Should find it";
+ ASSERT_EQ(six.value(), i->value()) << "Should be 6";
+
+ i = ll.find(three);
+ ASSERT_EQ(NULL, i) << "Not in the list";
+
+ LinkedListNode<Integer>* node = ll.find_node(six);
+ ASSERT_TRUE(node != NULL) << "6 is in the list";
+
+ ll.insert_after(three, node);
+ ll.insert_before(one, node);
+ int expected[3] = {1, 6, 3};
+ check_list_values(expected, &ll);
+}
+
+// Test sorted linked list
+TEST(SortedLinkedList, simple) {
+ LinkedListImpl<Integer, ResourceObj::C_HEAP, mtTest> ll;
+ ll.add(one);
+ ll.add(six);
+ ll.add(three);
+ ll.add(two);
+ ll.add(four);
+ ll.add(five);
+
+ SortedLinkedList<Integer, Integer::compare, ResourceObj::C_HEAP, mtTest> sl;
+ ASSERT_TRUE(sl.is_empty()) << "Start with empty list";
+
+ size_t ll_size = ll.size();
+ sl.move(&ll);
+ size_t sl_size = sl.size();
+
+ ASSERT_EQ(ll_size, sl_size) << "Should be the same size";
+ ASSERT_TRUE(ll.is_empty()) << "No more entries";
+
+ // sorted result
+ int sorted_result[] = {1, 2, 3, 4, 5, 6};
+ check_list_values(sorted_result, &sl);
+ if (HasFatalFailure()) {
+ return;
+ }
+
+ LinkedListNode<Integer>* node = sl.find_node(four);
+ ASSERT_TRUE(node != NULL) << "4 is in the list";
+ sl.remove_before(node);
+ sl.remove_after(node);
+ int remains[] = {1, 2, 4, 6};
+ check_list_values(remains, &sl);
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/lambda-features/CyclicInterfaceInit.java Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2016, 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 8163969
+ * @summary Interface initialization was crashing on this because the wrong class was getting
+ * initialization error.
+ * @run main CyclicInterfaceInit
+ */
+/**
+ * This snippet crashes with
+ * - Java(TM) SE Runtime Environment (8.0_101-b13) (build 1.8.0_101-b13)
+ */
+public class CyclicInterfaceInit {
+
+ interface Base {
+ static final Object CONST = new Target(){}.someMethod();
+
+ default void important() {
+ // Super interfaces with default methods get initialized (JLS 12.4.1)
+ }
+ }
+
+ static boolean out(String c) {
+ System.out.println("initializing " + c);
+ return true;
+ }
+
+ interface Target extends Base {
+ boolean v = CyclicInterfaceInit.out("Target");
+ default Object someMethod() {
+ throw new RuntimeException();
+ }
+ // Target can be fully initialized before initializating Base because Target doesn't
+ // initiate the initialization of Base.
+ }
+
+ static class InnerBad implements Target {}
+
+ public static void main(String[] args) {
+ try {
+ new Target() {}; // Creates inner class that causes initialization of super interfaces
+ } catch (ExceptionInInitializerError e) {
+ System.out.println("ExceptionInInitializerError thrown as expected");
+ }
+ // Try again, InnerBad instantiation should throw NoClassdefFoundError
+ // because Base is marked erroneous due to previous exception during initialization
+ try {
+ InnerBad ig = new InnerBad();
+ throw new RuntimeException("FAILED- initialization of InnerBad should throw NCDFE");
+ } catch (NoClassDefFoundError e) {
+ System.out.println("NoClassDefFoundError thrown as expected");
+ }
+ // Target is already initialized.
+ System.out.println("Target.v is " + Target.v);
+ // shouldn't throw any exceptions.
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/runtime/lambda-features/InterfaceInitializationStates.java Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,202 @@
+/*
+ * Copyright (c) 2016, 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 8163969
+ * @summary Test interface initialization states and when certain interfaces are initialized
+ * in the presence of initialization errors.
+ * @run main InterfaceInitializationStates
+ */
+
+import java.util.List;
+import java.util.Arrays;
+import java.util.ArrayList;
+
+public class InterfaceInitializationStates {
+
+ static List<Class<?>> cInitOrder = new ArrayList<>();
+
+ // K interface with a default method has an initialization error
+ interface K {
+ boolean v = InterfaceInitializationStates.out(K.class);
+ static final Object CONST = InterfaceInitializationStates.someMethod();
+ default int method() { return 2; }
+ }
+
+ // I is initialized when CONST is used, and doesn't trigger initialization of K,
+ // I also doesn't get an initialization error just because K has an initialization error.
+ interface I extends K {
+ boolean v = InterfaceInitializationStates.out(I.class);
+ static final Object CONST = InterfaceInitializationStates.someMethod();
+ }
+
+ // L can be fully initialized even though it extends an interface that has an
+ // initialization error
+ interface L extends K {
+ boolean v = InterfaceInitializationStates.out(L.class);
+ default void lx() {}
+ static void func() {
+ System.out.println("Calling function on interface with bad super interface.");
+ }
+ }
+
+ // Another interface needing initialization.
+ // Initialization of this interface does not occur with ClassLIM because K throws
+ // an initialization error, so the interface initialization is abandoned
+ interface M {
+ boolean v = InterfaceInitializationStates.out(M.class);
+ default void mx() {}
+ }
+
+ static class ClassLIM implements L, I, M {
+ boolean v = InterfaceInitializationStates.out(ClassLIM.class);
+ int callMethodInK() { return method(); }
+ static {
+ // Since interface initialization of K fails, this should never be called
+ System.out.println("Initializing C, but L is still good");
+ L.func();
+ }
+ }
+
+ // Finally initialize M
+ static class ClassM implements M {
+ boolean v = InterfaceInitializationStates.out(ClassM.class);
+ }
+
+ // Iunlinked is testing initialization like interface I, except interface I is linked when
+ // ClassLIM is linked.
+ // Iunlinked is not linked already when K gets an initialization error. Linking Iunlinked
+ // should succeed and not get NoClassDefFoundError because it does not depend on the
+ // initialization state of K for linking. There's bug now where it gets this error.
+ // See: https://bugs.openjdk.java.net/browse/JDK-8166203.
+ interface Iunlinked extends K {
+ boolean v = InterfaceInitializationStates.out(Iunlinked.class);
+ }
+
+ // More tests. What happens if we use K for parameters and return types?
+ // K is a symbolic reference in the constant pool and the initialization error only
+ // matters when it's used.
+ interface Iparams {
+ boolean v = InterfaceInitializationStates.out(Iparams.class);
+ K the_k = null;
+ K m(K k); // abstract
+ default K method() { return new K(){}; }
+ }
+
+ static class ClassIparams implements Iparams {
+ boolean v = InterfaceInitializationStates.out(ClassIparams.class);
+ public K m(K k) { return k; }
+ }
+
+ public static void main(java.lang.String[] unused) {
+ // The rule this tests is the last sentence of JLS 12.4.1:
+
+ // When a class is initialized, its superclasses are initialized (if they have not
+ // been previously initialized), as well as any superinterfaces (s8.1.5) that declare any
+ // default methods (s9.4.3) (if they have not been previously initialized). Initialization
+ // of an interface does not, of itself, cause initialization of any of its superinterfaces.
+
+ // Trigger initialization.
+ // Now L is fully_initialized even though K should
+ // throw an error during initialization.
+ boolean v = L.v;
+ L.func();
+
+ try {
+ ClassLIM c = new ClassLIM(); // is K initialized, with a perfectly good L in the middle
+ // was bug: this used to succeed and be able to callMethodInK().
+ throw new RuntimeException("FAIL exception not thrown for class");
+ } catch (ExceptionInInitializerError e) {
+ System.out.println("ExceptionInInitializerError thrown as expected");
+ }
+
+ // Test that K already has initialization error so gets ClassNotFoundException because
+ // initialization was attempted with ClassLIM.
+ try {
+ Class.forName("InterfaceInitializationStates$K", true, InterfaceInitializationStates.class.getClassLoader());
+ throw new RuntimeException("FAIL exception not thrown for forName(K)");
+ } catch(ClassNotFoundException e) {
+ throw new RuntimeException("ClassNotFoundException should not be thrown");
+ } catch(NoClassDefFoundError e) {
+ System.out.println("NoClassDefFoundError thrown as expected");
+ }
+
+ new ClassM();
+
+ // Initialize I, which doesn't cause K (super interface) to be initialized.
+ // Since the initialization of I does _not_ cause K to be initialized, it does
+ // not get NoClassDefFoundError because K is erroneous.
+ // But the initialization of I throws RuntimeException, so we expect
+ // ExceptionInInitializerError.
+ try {
+ Object ii = I.CONST;
+ throw new RuntimeException("FAIL exception not thrown for I's initialization");
+ } catch (ExceptionInInitializerError e) {
+ System.out.println("ExceptionInInitializerError as expected");
+ }
+
+ // Initialize Iunlinked. This should not get NoClassDefFoundError because K
+ // (its super interface) is in initialization_error state.
+ // This is a bug. It does now.
+ try {
+ boolean bb = Iunlinked.v;
+ throw new RuntimeException("FAIL exception not thrown for Iunlinked initialization");
+ } catch(NoClassDefFoundError e) {
+ System.out.println("NoClassDefFoundError thrown because of bug");
+ }
+
+ // This should be okay
+ boolean value = Iparams.v;
+ System.out.println("value is " + value);
+
+ ClassIparams p = new ClassIparams();
+ try {
+ // Now we get an error because K got an initialization_error
+ K kk = p.method();
+ throw new RuntimeException("FAIL exception not thrown for calling method for K");
+ } catch(NoClassDefFoundError e) {
+ System.out.println("NoClassDefFoundError thrown as expected");
+ }
+
+ // Check expected class initialization order
+ List<Class<?>> expectedCInitOrder = Arrays.asList(L.class, K.class, M.class, ClassM.class,
+ I.class, Iparams.class,
+ ClassIparams.class);
+ if (!cInitOrder.equals(expectedCInitOrder)) {
+ throw new RuntimeException(
+ String.format("Class initialization array %s not equal to expected array %s",
+ cInitOrder, expectedCInitOrder));
+ }
+ }
+
+ static boolean out(Class c) {
+ System.out.println("#: initializing " + c.getName());
+ cInitOrder.add(c);
+ return true;
+ }
+ static Object someMethod() {
+ throw new RuntimeException();
+ }
+}
--- a/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java Mon Sep 19 15:08:03 2016 +0200
+++ b/hotspot/test/runtime/modules/PatchModule/PatchModuleCDS.java Mon Sep 26 14:21:21 2016 -0400
@@ -23,41 +23,83 @@
/*
* @test
+ * @summary test that --patch-module works with CDS
* @library /test/lib
* @modules java.base/jdk.internal.misc
+ * jdk.jartool/sun.tools.jar
+ * @build PatchModuleMain
* @run main PatchModuleCDS
*/
import java.io.File;
+import jdk.test.lib.InMemoryJavaCompiler;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class PatchModuleCDS {
public static void main(String args[]) throws Throwable {
- System.out.println("Test that --patch-module and -Xshare:dump are incompatibable");
- ProcessBuilder pb = ProcessTools.createJavaProcessBuilder("--patch-module=java.naming=mods/java.naming", "-Xshare:dump");
- OutputAnalyzer output = new OutputAnalyzer(pb.start());
- output.shouldContain("Cannot use the following option when dumping the shared archive: --patch-module");
- System.out.println("Test that --patch-module and -Xshare:on are incompatibable");
+ // Case 1: Test that --patch-module and -Xshare:dump are compatible
String filename = "patch_module.jsa";
- pb = ProcessTools.createJavaProcessBuilder(
+ ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UnlockDiagnosticVMOptions",
"-XX:SharedArchiveFile=" + filename,
- "-Xshare:dump");
- output = new OutputAnalyzer(pb.start());
- output.shouldContain("ro space:"); // Make sure archive got created.
+ "-Xshare:dump",
+ "--patch-module=java.naming=no/such/directory",
+ "-Xlog:class+path=info",
+ "-version");
+ new OutputAnalyzer(pb.start())
+ .shouldContain("ro space:"); // Make sure archive got created.
+
+ // Case 2: Test that only jar file in --patch-module is supported for CDS dumping
+ // Create a class file in the module java.base.
+ String source = "package javax.naming.spi; " +
+ "public class NamingManager { " +
+ " static { " +
+ " System.out.println(\"I pass!\"); " +
+ " } " +
+ "}";
+
+ ClassFileInstaller.writeClassToDisk("javax/naming/spi/NamingManager",
+ InMemoryJavaCompiler.compile("javax.naming.spi.NamingManager", source, "-Xmodule:java.naming"),
+ System.getProperty("test.classes"));
pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UnlockDiagnosticVMOptions",
"-XX:SharedArchiveFile=" + filename,
- "-Xshare:on",
- "--patch-module=java.naming=mods/java.naming",
+ "-Xshare:dump",
+ "--patch-module=java.base=" + System.getProperty("test.classes"),
+ "-Xlog:class+path=info",
"-version");
- output = new OutputAnalyzer(pb.start());
- output.shouldContain("The shared archive file cannot be used with --patch-module");
+ new OutputAnalyzer(pb.start())
+ .shouldContain("--patch-module requires a regular file during dumping");
- output.shouldHaveExitValue(1);
+ // Case 3a: Test CDS dumping with jar file in --patch-module
+ BasicJarBuilder.build("javanaming", "javax/naming/spi/NamingManager");
+ String moduleJar = BasicJarBuilder.getTestJar("javanaming.jar");
+ pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=" + filename,
+ "-Xshare:dump",
+ "--patch-module=java.naming=" + moduleJar,
+ "-Xlog:class+load",
+ "-Xlog:class+path=info",
+ "PatchModuleMain", "javax.naming.spi.NamingManager");
+ new OutputAnalyzer(pb.start())
+ .shouldContain("ro space:"); // Make sure archive got created.
+
+ // Case 3b: Test CDS run with jar file in --patch-module
+ pb = ProcessTools.createJavaProcessBuilder(
+ "-XX:+UnlockDiagnosticVMOptions",
+ "-XX:SharedArchiveFile=" + filename,
+ "-Xshare:auto",
+ "--patch-module=java.naming=" + moduleJar,
+ "-Xlog:class+load",
+ "-Xlog:class+path=info",
+ "PatchModuleMain", "javax.naming.spi.NamingManager");
+ new OutputAnalyzer(pb.start())
+ .shouldContain("I pass!")
+ .shouldHaveExitValue(0);
}
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/MAAClassFileLoadHook.java Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2016, 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
+ * @run main/othervm/native -agentlib:MAAClassFileLoadHook MAAClassFileLoadHook
+ * @run main/othervm/native -agentlib:MAAClassFileLoadHook=with_early_vmstart MAAClassFileLoadHook
+ * @run main/othervm/native -agentlib:MAAClassFileLoadHook=with_early_class_hook MAAClassFileLoadHook
+ * @run main/othervm/native -agentlib:MAAClassFileLoadHook=with_early_vmstart,with_early_class_hook MAAClassFileLoadHook
+ */
+
+public class MAAClassFileLoadHook {
+
+ static {
+ try {
+ System.loadLibrary("MAAClassFileLoadHook");
+ } catch (UnsatisfiedLinkError ule) {
+ System.err.println("Could not load MAAClassFileLoadHook library");
+ System.err.println("java.library.path: "
+ + System.getProperty("java.library.path"));
+ throw ule;
+ }
+ }
+
+ native static int check();
+
+ public static void main(String args[]) {
+ int status = check();
+ if (status != 0) {
+ throw new RuntimeException("Non-zero status returned from the agent: " + status);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassFileLoadHook/libMAAClassFileLoadHook.c Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,278 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+#define PASSED 0
+#define FAILED 2
+
+static const char *EXPECTED_NAME = "java/util/Collections";
+static const char *EXC_CNAME = "java/lang/Exception";
+
+static jvmtiEnv *jvmti = NULL;
+static jint result = PASSED;
+static jboolean printdump = JNI_FALSE;
+
+static jboolean with_early_vm_start_capability = JNI_FALSE;
+static jboolean with_early_class_hook_capability = JNI_FALSE;
+
+static jboolean found_class_in_vm_start = JNI_FALSE;
+static jboolean found_class_in_primordial = JNI_FALSE;
+static jboolean found_class_in_cflh_events = JNI_FALSE;
+
+static int cflh_events_primordial_count = 0;
+static int cflh_events_vm_start_count = 0;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+ return JNI_VERSION_9;
+}
+
+static
+jint throw_exc(JNIEnv *env, char *msg) {
+ jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
+
+ if (exc_class == NULL) {
+ printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
+ return -1;
+ }
+ return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+}
+
+static void JNICALL
+Callback_ClassFileLoadHook(jvmtiEnv *jvmti_env, 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) {
+ jvmtiPhase phase;
+ jvmtiError err;
+
+ err = (*jvmti)->GetPhase(jvmti_env, &phase);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("ClassFileLoadHook event: GetPhase error: %s (%d)\n", TranslateError(err), err);
+ result = FAILED;
+ return;
+ }
+
+ if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) {
+ if (phase == JVMTI_PHASE_START) {
+ cflh_events_vm_start_count++;
+ if(strcmp(name, EXPECTED_NAME) == 0) {
+ found_class_in_vm_start = JNI_TRUE;
+ }
+ } else {
+ cflh_events_primordial_count++;
+ if(strcmp(name, EXPECTED_NAME) == 0) {
+ found_class_in_primordial = JNI_TRUE;
+ }
+ }
+ }
+
+ if(strcmp(name, EXPECTED_NAME) == 0) {
+ found_class_in_cflh_events = JNI_TRUE;
+ }
+
+ if (printdump == JNI_TRUE) {
+ printf(">>> ClassFileLoadHook event: phase(%d), class name %s\n", phase, name);
+ }
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+ jint res, size;
+ jvmtiCapabilities caps;
+ jvmtiEventCallbacks callbacks;
+ jvmtiError err;
+
+ if (options != NULL) {
+ if (strstr(options, "with_early_vmstart") != NULL) {
+ with_early_vm_start_capability = JNI_TRUE;
+ }
+ if (strstr(options, "with_early_class_hook") != NULL) {
+ with_early_class_hook_capability = JNI_TRUE;
+ }
+ if (strstr(options, "printdump") != NULL) {
+ printdump = JNI_TRUE;
+ }
+ }
+
+ res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+ JVMTI_VERSION_9);
+ if (res != JNI_OK || jvmti == NULL) {
+ printf(" Error: wrong result of a valid call to GetEnv!\n");
+ return JNI_ERR;
+ }
+
+ printf("Enabling following capabilities: can_generate_all_class_hook_events");
+ memset(&caps, 0, sizeof(caps));
+ caps.can_generate_all_class_hook_events = 1;
+ if (with_early_vm_start_capability == JNI_TRUE) {
+ printf(", can_generate_early_vmstart");
+ caps.can_generate_early_vmstart = 1;
+ }
+ if (with_early_class_hook_capability == JNI_TRUE) {
+ printf(", can_generate_early_class_hook_events");
+ caps.can_generate_early_class_hook_events = 1;
+ }
+ printf("\n");
+
+ err = (*jvmti)->AddCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ size = (jint)sizeof(callbacks);
+
+ memset(&callbacks, 0, sizeof(callbacks));
+ callbacks.ClassFileLoadHook = Callback_ClassFileLoadHook;
+
+ err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_FILE_LOAD_HOOK, NULL);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL
+Java_MAAClassFileLoadHook_check(JNIEnv *env, jclass cls) {
+ jobject loader = NULL;
+
+ if (jvmti == NULL) {
+ throw_exc(env, "JVMTI client was not properly loaded!\n");
+ return FAILED;
+ }
+
+ /*
+ * Expecting that we always get ClassFileLoadHook events in the VM Start phase.
+ */
+ if (cflh_events_vm_start_count == 0) {
+ throw_exc(env, "Didn't get ClassFileLoadHook events in start phase!\n");
+ return FAILED;
+ }
+
+ if (with_early_class_hook_capability == JNI_TRUE) {
+ /*
+ * Expecting that we get ClassFileLoadHook events in the Primordial phase
+ * when can_generate_all_class_hook_events and can_generate_early_class_hook_events
+ * capabilities are enabled.
+ */
+ if (cflh_events_primordial_count == 0) {
+ throw_exc(env, "Didn't get ClassFileLoadHook events in primordial phase!\n");
+ return FAILED;
+ }
+ } else {
+ /*
+ * Expecting that we don't get ClassFileLoadHook events in the Primordial phase
+ * when can_generate_early_class_hook_events capability is disabled.
+ */
+ if (cflh_events_primordial_count != 0) {
+ throw_exc(env, "Get ClassFileLoadHook events in primordial phase!\n");
+ return FAILED;
+ }
+ }
+
+
+ if (with_early_vm_start_capability == JNI_TRUE) {
+ /*
+ * Expecting that "java/util/Collections" class from java.base module is present in the
+ * ClassFileLoadHook events during VM Start phase when can_generate_early_vmstart
+ * capability is enabled.
+ */
+ printf("Expecting to find '%s' class in ClassFileLoadHook events during VM early start phase.\n", EXPECTED_NAME);
+ if (found_class_in_vm_start == JNI_FALSE) {
+ throw_exc(env, "Unable to find expected class in ClassLoad events during VM early start phase!\n");
+ return FAILED;
+ }
+ } else if (with_early_class_hook_capability == JNI_TRUE) {
+ /*
+ * Expecting that "java/util/Collections" class from java.base module is present in the
+ * ClassFileLoadHook events during Primordial phase when can_generate_all_class_hook_events
+ * and can_generate_early_class_hook_events capabilities are enabled and can_generate_early_vmstart
+ * capability is disabled.
+ */
+ printf("Expecting to find '%s' class in ClassFileLoadHook events during VM primordial phase.\n", EXPECTED_NAME);
+ if (found_class_in_primordial == JNI_FALSE) {
+ throw_exc(env, "Unable to find expected class in ClassFileLoadHook events during primordial phase!\n");
+ return FAILED;
+ }
+ } else {
+ /*
+ * Expecting that "java/util/Collections" class from java.base module is not present in the
+ * ClassFileLoadHook events when can_generate_all_class_hook_events, can_generate_early_class_hook_events
+ * and can_generate_early_vmstart capabilities are disabled.
+ */
+ printf("Expecting that '%s' class is absent in ClassLoadHook events.\n", EXPECTED_NAME);
+ if (found_class_in_cflh_events == JNI_TRUE) {
+ throw_exc(env, "Class is found in ClassFileLoadHook events!\n");
+ return FAILED;
+ }
+ }
+
+ return result;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare/MAAClassLoadPrepare.java Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2016, 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 8165681
+ * @summary Verify ClassLoad and ClassPrepare JVMTI event with
+ * and without can_generate_early_vmstart capability
+ * @run main/othervm/native -agentlib:MAAClassLoadPrepare MAAClassLoadPrepare
+ * @run main/othervm/native -agentlib:MAAClassLoadPrepare=with_early_vmstart MAAClassLoadPrepare
+ */
+
+public class MAAClassLoadPrepare {
+
+ static {
+ try {
+ System.loadLibrary("MAAClassLoadPrepare");
+ } catch (UnsatisfiedLinkError ule) {
+ System.err.println("Could not load MAAClassLoadPrepare library");
+ System.err.println("java.library.path: "
+ + System.getProperty("java.library.path"));
+ throw ule;
+ }
+ }
+
+ native static int check();
+
+ public static void main(String args[]) {
+ int status = check();
+ if (status != 0) {
+ throw new RuntimeException("Non-zero status returned from the agent: " + status);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ClassLoadPrepare/libMAAClassLoadPrepare.c Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+#define PASSED 0
+#define FAILED 2
+
+static const char *EXPECTED_SIGNATURE = "Ljava/util/Collections;";
+static const char *EXC_CNAME = "java/lang/Exception";
+
+static jvmtiEnv *jvmti = NULL;
+static jint result = PASSED;
+static jboolean printdump = JNI_FALSE;
+
+static jboolean with_early_vm_start_capability = JNI_FALSE;
+
+static jboolean class_in_class_load_events_vm_start = JNI_FALSE;
+static jboolean class_in_class_load_events_vm_live = JNI_FALSE;
+static jboolean class_in_class_prepare_events_vm_start = JNI_FALSE;
+static jboolean class_in_class_prepare_events_vm_live = JNI_FALSE;
+
+static int class_load_events_vm_start_count = 0;
+static int class_prepare_events_vm_start_count = 0;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+ return JNI_VERSION_9;
+}
+
+static
+jint throw_exc(JNIEnv *env, char *msg) {
+ jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
+
+ if (exc_class == NULL) {
+ printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
+ return -1;
+ }
+ return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+}
+
+static void JNICALL
+Callback_ClassFileLoad(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread, jclass klass) {
+ jvmtiPhase phase;
+ char *sig, *generic;
+ jvmtiError err;
+
+ err = (*jvmti)->GetPhase(jvmti_env,&phase);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("ClassLoad event: GetPhase error: %s (%d)\n", TranslateError(err), err);
+ result = FAILED;
+ return;
+ }
+
+ if (phase == JVMTI_PHASE_START || phase == JVMTI_PHASE_LIVE) {
+
+ err = (*jvmti)->GetClassSignature(jvmti_env, klass, &sig, &generic);
+
+ if (err != JVMTI_ERROR_NONE) {
+ printf("ClassLoad event: GetClassSignature error: %s (%d)\n", TranslateError(err), err);
+ result = FAILED;
+ return;
+ }
+
+ if (phase == JVMTI_PHASE_START) {
+ class_load_events_vm_start_count++;
+ if(strcmp(sig, EXPECTED_SIGNATURE) == 0) {
+ class_in_class_load_events_vm_start = JNI_TRUE;
+ }
+ } else {
+ if(strcmp(sig, EXPECTED_SIGNATURE) == 0) {
+ class_in_class_load_events_vm_live = JNI_TRUE;
+ }
+ }
+
+ if (printdump == JNI_TRUE) {
+ printf(">>> ClassLoad event: phase(%d), class signature %s\n", phase, sig == NULL ? "null": sig);
+ }
+ } else {
+ printf("ClassLoad event: get event in unexpected phase(%d)\n", phase);
+ result = FAILED;
+ }
+}
+
+static void JNICALL
+Callback_ClassFilePrepare(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread, jclass klass) {
+ jvmtiPhase phase;
+ char *sig, *generic;
+ jvmtiError err;
+
+ err = (*jvmti)->GetPhase(jvmti_env,&phase);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("ClassPrepare event: GetPhase error: %s (%d)\n", TranslateError(err), err);
+ result = FAILED;
+ return;
+ }
+
+ if (phase == JVMTI_PHASE_START || phase == JVMTI_PHASE_LIVE) {
+
+ err = (*jvmti)->GetClassSignature(jvmti_env, klass, &sig, &generic);
+
+ if (err != JVMTI_ERROR_NONE) {
+ printf("ClassPrepare event: GetClassSignature error: %s (%d)\n", TranslateError(err), err);
+ result = FAILED;
+ return;
+ }
+
+ if (phase == JVMTI_PHASE_START) {
+ class_prepare_events_vm_start_count++;
+ if(strcmp(sig, EXPECTED_SIGNATURE) == 0) {
+ class_in_class_prepare_events_vm_start = JNI_TRUE;
+ }
+ } else {
+ if(strcmp(sig, EXPECTED_SIGNATURE) == 0) {
+ class_in_class_prepare_events_vm_live = JNI_TRUE;
+ }
+ }
+
+ if (printdump == JNI_TRUE) {
+ printf(">>> ClassPrepare event: phase(%d), class signature %s\n", phase, sig == NULL ? "null": sig);
+ }
+ } else {
+ printf("ClassPrepare event: get event in unexpected phase(%d)\n", phase);
+ result = FAILED;
+ }
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+ jint res, size;
+ jvmtiCapabilities caps;
+ jvmtiEventCallbacks callbacks;
+ jvmtiError err;
+
+ if (options != NULL) {
+ if (strstr(options, "with_early_vmstart") != NULL) {
+ with_early_vm_start_capability = JNI_TRUE;
+ }
+ if (strstr(options, "printdump") != NULL) {
+ printdump = JNI_TRUE;
+ }
+ }
+
+ res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+ JVMTI_VERSION_9);
+ if (res != JNI_OK || jvmti == NULL) {
+ printf(" Error: wrong result of a valid call to GetEnv!\n");
+ return JNI_ERR;
+ }
+
+ if (with_early_vm_start_capability == JNI_TRUE) {
+ printf("Enabling following capability: can_generate_early_vmstart\n");
+ memset(&caps, 0, sizeof(caps));
+ caps.can_generate_early_vmstart = 1;
+
+ err = (*jvmti)->AddCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+ }
+
+ size = (jint)sizeof(callbacks);
+
+ memset(&callbacks, 0, sizeof(callbacks));
+ callbacks.ClassLoad = Callback_ClassFileLoad;
+ callbacks.ClassPrepare = Callback_ClassFilePrepare;
+
+ err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_LOAD, NULL);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_CLASS_PREPARE, NULL);
+
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL
+Java_MAAClassLoadPrepare_check(JNIEnv *env, jclass cls) {
+ jobject loader = NULL;
+
+ if (jvmti == NULL) {
+ throw_exc(env, "JVMTI client was not properly loaded!\n");
+ return FAILED;
+ }
+
+ if (with_early_vm_start_capability == JNI_TRUE) {
+ /*
+ * Expecting that "java/util/Collections" class from java.base module is present in the
+ * ClassLoad and ClassPrepare events during VM Start phase when can_generate_early_vmstart
+ * capability is enabled.
+ * Expecting that ClassLoad and ClassPrepare events are sent in the VM early start phase
+ * when can_generate_early_vmstart is enabled(JDK-8165681).
+ */
+ if (class_load_events_vm_start_count == 0) {
+ throw_exc(env, "Didn't get ClassLoad events in start phase!\n");
+ return FAILED;
+ }
+
+ printf("Expecting to find '%s' class in ClassLoad events during VM early start phase.\n", EXPECTED_SIGNATURE);
+ if (class_in_class_load_events_vm_start == JNI_FALSE) {
+ throw_exc(env, "Unable to find expected class in ClassLoad events during early start phase!\n");
+ return FAILED;
+ }
+
+ if (class_prepare_events_vm_start_count == 0) {
+ throw_exc(env, "Didn't get ClassPrepare events in start phase!\n");
+ return FAILED;
+ }
+
+ printf("Expecting to find '%s' class in ClassPrepare events during VM early start phase.\n", EXPECTED_SIGNATURE);
+ if (class_in_class_prepare_events_vm_start == JNI_FALSE) {
+ throw_exc(env, "Unable to find expected class in ClassPrepare events during early start phase!\n");
+ return FAILED;
+ }
+ } else {
+ /*
+ * Expecting that "java/util/Collections" class from java.base module is not present in the
+ * ClassLoad and ClassPrepare events during VM Start phase when can_generate_early_vmstart
+ * capability is disabled.
+ */
+ printf("Expecting that '%s' class is absent in ClassLoad events during normal VM start phase.\n", EXPECTED_SIGNATURE);
+ if (class_in_class_prepare_events_vm_start == JNI_TRUE) {
+ throw_exc(env, "Class is found in ClassLoad events during normal VM start phase!\n");
+ return FAILED;
+ }
+
+ printf("Expecting that '%s' class is absent in ClassPrepare events during normal VM start phase.\n", EXPECTED_SIGNATURE);
+ if (class_in_class_prepare_events_vm_start == JNI_TRUE) {
+ throw_exc(env, "Class is found in ClassPrepare events during normal VM start phase!\n");
+ return FAILED;
+ }
+ }
+
+ /*
+ * In any case, we not expect to see "java/util/Collections" class from java.base module
+ * in the ClassLoad and ClassPrepare events during VM Live phase.
+ */
+ if (class_in_class_prepare_events_vm_live == JNI_TRUE) {
+ throw_exc(env, "Class is found in ClassLoad events during VM Live phase!\n");
+ return FAILED;
+ }
+
+ if (class_in_class_prepare_events_vm_live == JNI_TRUE) {
+ throw_exc(env, "Class is found in ClassPrepare events during VM Live phase!\n");
+ return FAILED;
+ }
+
+ return result;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart/MAAThreadStart.java Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2016, 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
+ * @summary Verify ThreadStart JVMTI event with can_generate_early_vmstart capability
+ * @run main/othervm/native -agentlib:MAAThreadStart MAAThreadStart
+ */
+
+public class MAAThreadStart {
+
+ static {
+ try {
+ System.loadLibrary("MAAThreadStart");
+ } catch (UnsatisfiedLinkError ule) {
+ System.err.println("Could not load MAAThreadStart library");
+ System.err.println("java.library.path: "
+ + System.getProperty("java.library.path"));
+ throw ule;
+ }
+ }
+
+ native static int check();
+
+ public static void main(String args[]) {
+ int status = check();
+ if (status != 0) {
+ throw new RuntimeException("Non-zero status returned from the agent: " + status);
+ }
+ }
+}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/jvmti/ModuleAwareAgents/ThreadStart/libMAAThreadStart.c Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2016, 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.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "jvmti.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef JNI_ENV_ARG
+
+#ifdef __cplusplus
+#define JNI_ENV_ARG(x, y) y
+#define JNI_ENV_PTR(x) x
+#else
+#define JNI_ENV_ARG(x,y) x, y
+#define JNI_ENV_PTR(x) (*x)
+#endif
+
+#endif
+
+#define TranslateError(err) "JVMTI error"
+
+#define PASSED 0
+#define FAILED 2
+
+static const char *EXC_CNAME = "java/lang/Exception";
+
+static jvmtiEnv *jvmti = NULL;
+static jint result = PASSED;
+static jboolean printdump = JNI_FALSE;
+
+static int thread_start_events_vm_start = 0;
+
+static jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved);
+
+JNIEXPORT
+jint JNICALL Agent_OnLoad(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL Agent_OnAttach(JavaVM *jvm, char *options, void *reserved) {
+ return Agent_Initialize(jvm, options, reserved);
+}
+
+JNIEXPORT
+jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) {
+ return JNI_VERSION_9;
+}
+
+static
+jint throw_exc(JNIEnv *env, char *msg) {
+ jclass exc_class = JNI_ENV_PTR(env)->FindClass(JNI_ENV_ARG(env, EXC_CNAME));
+
+ if (exc_class == NULL) {
+ printf("throw_exc: Error in FindClass(env, %s)\n", EXC_CNAME);
+ return -1;
+ }
+ return JNI_ENV_PTR(env)->ThrowNew(JNI_ENV_ARG(env, exc_class), msg);
+}
+
+
+void JNICALL Callback_ThreadStart(jvmtiEnv *jvmti_env, JNIEnv *env, jthread thread) {
+ jvmtiError err;
+ jvmtiPhase phase;
+
+ err = (*jvmti)->GetPhase(jvmti_env,&phase);
+ if (err != JVMTI_ERROR_NONE) {
+ printf("ThreadStart event: GetPhase error: %s (%d)\n", TranslateError(err), err);
+ result = FAILED;
+ return;
+ }
+
+ if (phase == JVMTI_PHASE_START) {
+ thread_start_events_vm_start++;
+ }
+
+ if (printdump == JNI_TRUE) {
+ printf(">>> ThreadStart event: phase(%d)\n", phase);
+ }
+}
+
+static
+jint Agent_Initialize(JavaVM *jvm, char *options, void *reserved) {
+ jint res, size;
+ jvmtiCapabilities caps;
+ jvmtiEventCallbacks callbacks;
+ jvmtiError err;
+
+ if (options != NULL && strcmp(options, "printdump") == 0) {
+ printdump = JNI_TRUE;
+ }
+
+ res = JNI_ENV_PTR(jvm)->GetEnv(JNI_ENV_ARG(jvm, (void **) &jvmti),
+ JVMTI_VERSION_9);
+ if (res != JNI_OK || jvmti == NULL) {
+ printf(" Error: wrong result of a valid call to GetEnv!\n");
+ return JNI_ERR;
+ }
+
+ printf("Enabling following capability: can_generate_early_vmstart\n");
+ memset(&caps, 0, sizeof(caps));
+ caps.can_generate_early_vmstart = 1;
+
+ err = (*jvmti)->AddCapabilities(jvmti, &caps);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in AddCapabilites: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ size = (jint)sizeof(callbacks);
+
+ memset(&callbacks, 0, sizeof(callbacks));
+ callbacks.ThreadStart = Callback_ThreadStart;
+
+ err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, size);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventCallbacks: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_THREAD_START, NULL);
+ if (err != JVMTI_ERROR_NONE) {
+ printf(" Error in SetEventNotificationMode: %s (%d)\n", TranslateError(err), err);
+ return JNI_ERR;
+ }
+
+ return JNI_OK;
+}
+
+JNIEXPORT jint JNICALL
+Java_MAAThreadStart_check(JNIEnv *env, jclass cls) {
+ jobject loader = NULL;
+
+ if (jvmti == NULL) {
+ throw_exc(env, "JVMTI client was not properly loaded!\n");
+ return FAILED;
+ }
+
+ /*
+ * Expecting that ThreadStart events are sent during VM Start phase when
+ * can_generate_early_vmstart capability is enabled.
+ */
+ if (thread_start_events_vm_start == 0) {
+ throw_exc(env, "Didn't get ThreadStart events in VM early start phase!\n");
+ return FAILED;
+ }
+
+ return result;
+}
+
+#ifdef __cplusplus
+}
+#endif
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/sa/LingeredAppWithDefaultMethods.java Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2005, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import jdk.test.lib.apps.LingeredApp;
+
+interface Language {
+ static final long nbrOfWords = 99999;
+ public abstract long getNbrOfWords();
+ default boolean hasScript() {
+ return true;
+ }
+}
+
+class ParselTongue implements Language {
+ public long getNbrOfWords() {
+ return nbrOfWords * 4;
+ }
+}
+
+class SlytherinSpeak extends ParselTongue {
+ public boolean hasScript() {
+ return false;
+ }
+}
+
+public class LingeredAppWithDefaultMethods extends LingeredApp {
+
+ public static void main(String args[]) {
+ ParselTongue lang = new ParselTongue();
+ SlytherinSpeak slang = new SlytherinSpeak();
+ System.out.println(lang.hasScript() || slang.hasScript());
+
+ LingeredApp.main(args);
+ }
+ }
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/hotspot/test/serviceability/sa/TestDefaultMethods.java Mon Sep 26 14:21:21 2016 -0400
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+
+import java.util.ArrayList;
+import java.util.List;
+
+import sun.jvm.hotspot.HotSpotAgent;
+import sun.jvm.hotspot.utilities.SystemDictionaryHelper;
+import sun.jvm.hotspot.oops.InstanceKlass;
+import sun.jvm.hotspot.debugger.*;
+import sun.jvm.hotspot.oops.Method;
+import sun.jvm.hotspot.utilities.MethodArray;
+
+import jdk.test.lib.apps.LingeredApp;
+import jdk.test.lib.JDKToolLauncher;
+import jdk.test.lib.JDKToolFinder;
+import jdk.test.lib.Platform;
+import jdk.test.lib.process.ProcessTools;
+import jdk.test.lib.process.OutputAnalyzer;
+import jdk.test.lib.Utils;
+import jdk.test.lib.Asserts;
+
+/*
+ * @test
+ * @library /test/lib
+ * @requires os.family != "mac"
+ * @modules java.base/jdk.internal.misc
+ * jdk.hotspot.agent/sun.jvm.hotspot
+ * jdk.hotspot.agent/sun.jvm.hotspot.utilities
+ * jdk.hotspot.agent/sun.jvm.hotspot.oops
+ * jdk.hotspot.agent/sun.jvm.hotspot.debugger
+ * @run main/othervm TestDefaultMethods
+ */
+
+public class TestDefaultMethods {
+
+ private static LingeredAppWithDefaultMethods theApp = null;
+
+ private static void printDefaultMethods(String pid,
+ String[] instanceKlassNames) {
+ HotSpotAgent agent = new HotSpotAgent();
+ try {
+ agent.attach(Integer.parseInt(pid));
+ }
+ catch (DebuggerException e) {
+ System.out.println(e.getMessage());
+ System.err.println("Unable to connect to process ID: " + pid);
+
+ agent.detach();
+ e.printStackTrace();
+ }
+
+ for (String instanceKlassName : instanceKlassNames) {
+ InstanceKlass iKlass = SystemDictionaryHelper.findInstanceKlass(instanceKlassName);
+ MethodArray methods = iKlass.getMethods();
+ MethodArray defaultMethods = iKlass.getDefaultMethods();
+ for (int i = 0; i < methods.length(); i++) {
+ Method m = methods.at(i);
+ System.out.println("Method: " + m.getName().asString() +
+ " in instance klass: " + instanceKlassName);
+ }
+ if (defaultMethods != null) {
+ for (int j = 0; j < defaultMethods.length(); j++) {
+ Method dm = defaultMethods.at(j);
+ System.out.println("Default method: " + dm.getName().asString() +
+ " in instance klass: " + instanceKlassName);
+ }
+ } else {
+ System.out.println("No default methods in " + instanceKlassName);
+ }
+
+ }
+ agent.detach();
+ }
+
+ private static void createAnotherToAttach(
+ String[] instanceKlassNames,
+ long lingeredAppPid) throws Exception {
+
+ String[] toolArgs = {
+ "--add-modules=jdk.hotspot.agent",
+ "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot=ALL-UNNAMED",
+ "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.utilities=ALL-UNNAMED",
+ "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.oops=ALL-UNNAMED",
+ "--add-exports=jdk.hotspot.agent/sun.jvm.hotspot.debugger=ALL-UNNAMED",
+ "TestDefaultMethods",
+ Long.toString(lingeredAppPid)
+ };
+
+ // Start a new process to attach to the lingered app
+ ProcessBuilder processBuilder = ProcessTools.createJavaProcessBuilder(toolArgs);
+ OutputAnalyzer SAOutput = ProcessTools.executeProcess(processBuilder);
+ SAOutput.shouldHaveExitValue(0);
+ System.out.println(SAOutput.getOutput());
+
+ SAOutput.shouldContain(
+ "Default method: hasScript in instance klass: " + instanceKlassNames[1]);
+ SAOutput.shouldContain(
+ "No default methods in " + instanceKlassNames[0]);
+ SAOutput.shouldContain(
+ "Method: hasScript in instance klass: " + instanceKlassNames[0]);
+ SAOutput.shouldContain(
+ "No default methods in " + instanceKlassNames[2]);
+ }
+
+ public static void main (String... args) throws Exception {
+
+ String[] instanceKlassNames = new String[] {
+ "Language",
+ "ParselTongue",
+ "SlytherinSpeak"
+ };
+
+ if (!Platform.shouldSAAttach()) {
+ System.out.println(
+ "SA attach not expected to work - test skipped.");
+ return;
+ }
+
+ if (args == null || args.length == 0) {
+ try {
+ List<String> vmArgs = new ArrayList<String>();
+ vmArgs.add("-XX:+UsePerfData");
+ vmArgs.addAll(Utils.getVmOptions());
+
+ theApp = new LingeredAppWithDefaultMethods();
+ LingeredApp.startApp(vmArgs, theApp);
+ createAnotherToAttach(instanceKlassNames,
+ theApp.getPid());
+ } finally {
+ LingeredApp.stopApp(theApp);
+ }
+ } else {
+ printDefaultMethods(args[0], instanceKlassNames);
+ }
+ }
+}