This commit is contained in:
Dean Long 2016-09-26 14:21:21 -04:00
commit 42ec83b459
66 changed files with 2311 additions and 464 deletions

View File

@ -67,7 +67,8 @@ define SetupXslTransformBody
$$($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 @@ TARGETS += $(JVMTI_OUTPUTDIR)/jvmtiEnvRecommended.cpp
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 @@ TRACE_DEPS += \
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), \
))

View File

@ -55,6 +55,9 @@ BUILD_HOTSPOT_JTREG_NATIVE_SRC := \
$(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 @@ ifeq ($(TOOLCHAIN_TYPE), solstudio)
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)

View File

@ -327,7 +327,7 @@ void InterpreterMacroAssembler::push_i(Register r) {
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) {

View File

@ -85,6 +85,7 @@ typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsig
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 GetNextEntry_t GetNextEntry = NULL;
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 @@ int ClassLoader::_num_entries = 0;
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 @@ ClassPathZipEntry::~ClassPathZipEntry() {
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 @@ void ClassLoader::check_shared_classpath(const char *path) {
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 @@ void ClassLoader::setup_patch_mod_entries() {
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 @@ ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const str
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 @@ ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path, bo
// 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 @@ void ClassLoader::load_zip_library() {
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 @@ ClassFileStream* ClassLoader::search_module_entries(const GrowableArray<ModuleCl
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 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl
// 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 @@ instanceKlassHandle ClassLoader::load_class(Symbol* name, bool search_append_onl
// 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 @@ void ClassLoader::initialize() {
}
#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()
}

View File

@ -69,6 +69,7 @@ public:
// 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 @@ class ClassPathDirEntry: public ClassPathEntry {
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 @@ class ClassPathZipEntry: public ClassPathEntry {
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 @@ public:
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 @@ class ClassLoader: AllStatic {
// 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 @@ class ClassLoader: AllStatic {
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);

View File

@ -86,6 +86,9 @@ void SharedPathsMiscInfo::print_path(int type, const char* path) {
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 @@ bool SharedPathsMiscInfo::check(jint type, const char* path) {
// 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 @@ bool SharedPathsMiscInfo::check(jint type, const char* path) {
}
}
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");
}

View File

@ -104,10 +104,28 @@ public:
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 @@ public:
enum {
BOOT = 1,
NON_EXIST = 2,
REQUIRED = 3
REQUIRED = 3,
PATCH_MOD = 4
};
virtual const char* type_name(int type) {
@ -137,6 +156,7 @@ public:
case BOOT: return "BOOT";
case NON_EXIST: return "NON_EXIST";
case REQUIRED: return "REQUIRED";
case PATCH_MOD: return "PATCH_MOD";
default: ShouldNotReachHere(); return "?";
}
}

View File

@ -710,53 +710,3 @@ int SymboltableDCmd::num_arguments() {
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

View File

@ -258,16 +258,15 @@ class PushOrMarkClosure: public MetadataAwareOopClosure {
// 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 @@ class ParPushOrMarkClosure: public MetadataAwareOopClosure {
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);

View File

@ -3025,14 +3025,14 @@ class CMSConcMarkingTerminatorTerminator: public TerminatorTerminator {
// 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 @@ class CMSConcMarkingTask: public YieldingFlexibleGangTask {
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 @@ void ParMarkFromRootsClosure::scan_oops_in_oop(HeapWord* ptr) {
// 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 @@ ParPushOrMarkClosure::ParPushOrMarkClosure(CMSCollector* collector,
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),

View File

@ -724,12 +724,12 @@ class CMSCollector: public CHeapObj<mtGC> {
// 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;

View File

@ -2474,8 +2474,16 @@ size_t G1CollectedHeap::max_capacity() const {
}
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() {

View File

@ -66,7 +66,8 @@ G1DefaultPolicy::G1DefaultPolicy() :
_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 @@ void G1DefaultPolicy::record_collection_pause_end(double pause_time_ms, size_t c
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);

View File

@ -64,6 +64,8 @@ class G1DefaultPolicy: public G1Policy {
double _full_collection_start_sec;
jlong _collection_pause_end_millis;
uint _young_list_target_length;
uint _young_list_fixed_length;
@ -237,6 +239,8 @@ public:
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();

View File

@ -119,6 +119,8 @@ public:
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;

View File

@ -56,7 +56,7 @@ class PerRegionTable: public CHeapObj<mtGC> {
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 @@ public:
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;

View File

@ -283,7 +283,7 @@ size_t RSHashTable::mem_size() const {
// ----------------------------------------------------------------------
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.

View File

@ -250,7 +250,7 @@ class SparsePRT VALUE_OBJ_CLASS_SPEC {
bool should_be_on_expanded_list();
static SparsePRT* _head_expanded_list;
static SparsePRT* volatile _head_expanded_list;
public:
SparsePRT(HeapRegion* hr);

View File

@ -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 @@ class MutableSpace: public ImmutableSpace {
MemRegion _last_setup_region;
size_t _alignment;
protected:
HeapWord* _top;
HeapWord* volatile _top;
MutableSpaceMangler* mangler() { return _mangler; }
@ -69,7 +69,7 @@ class MutableSpace: public ImmutableSpace {
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; }

View File

@ -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 @@ class ParallelScavengeHeap : public CollectedHeap {
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);

View File

@ -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 @@ class PSYoungGen : public CHeapObj<mtGC> {
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.

View File

@ -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*) \

View File

@ -512,7 +512,7 @@ size_t DefNewGeneration::contiguous_available() const {
}
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) {

View File

@ -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 @@ protected:
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

View File

@ -350,7 +350,7 @@ class CollectedHeap : public CHeapObj<mtInternal> {
// 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;
}

View File

@ -721,7 +721,7 @@ bool GenCollectedHeap::supports_inline_contig_alloc() const {
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 @@ class GenTimeOfLastGCClosure: public GenCollectedHeap::GenClosure {
};
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;

View File

@ -184,7 +184,7 @@ public:
// 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

View File

@ -263,7 +263,7 @@ class Generation: public CHeapObj<mtGC> {
// 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

View File

@ -472,23 +472,21 @@ bool SequentialSubTasksDone::valid() {
}
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;
}

View File

@ -318,9 +318,9 @@ public:
// 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 @@ public:
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();

View File

@ -112,7 +112,7 @@ uintptr_t CompilerToVM::Data::Universe_verify_oop_bits;
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 @@ void CompilerToVM::Data::initialize() {
_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 @@ JNINativeMethod CompilerToVM::methods[] = {
int CompilerToVM::methods_count() {
return sizeof(methods) / sizeof(JNINativeMethod);
}

View File

@ -58,7 +58,7 @@ class CompilerToVM {
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;

View File

@ -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) \
\

View File

@ -179,6 +179,7 @@ void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment
_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 @@ bool FileMapInfo::FileMapHeader::validate() {
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 @@ bool FileMapInfo::FileMapHeader::validate() {
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;
}

View File

@ -155,6 +155,7 @@ public:
// 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);

View File

@ -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

View File

@ -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 @@ class arrayOopDesc : public oopDesc {
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

View File

@ -517,7 +517,11 @@ bool InstanceKlass::link_class_or_fail(TRAPS) {
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 @@ void InstanceKlass::link_methods(TRAPS) {
// 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);
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);
// ignore any exception thrown, superclass initialization error is
// thrown below
CLEAR_PENDING_EXCEPTION;
}
THROW_OOP(e());
}
}
// 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 @@ void InstanceKlass::initialize_impl(instanceKlassHandle this_k, TRAPS) {
}
// 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(ClassState state, TRAPS)
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.

View File

@ -734,27 +734,3 @@ bool Klass::verify_itable_index(int i) {
}
#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

View File

@ -562,8 +562,8 @@ JVM_ENTRY(jint, JVM_MoreStackWalk(JNIEnv *env, jobject stackStream, jlong mode,
}
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))

View File

@ -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 [

View File

@ -487,8 +487,8 @@ static jvmtiError JNICALL
</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>

View File

@ -95,7 +95,7 @@ typedef enum {
</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 */

View File

@ -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.&#xA;</xsl:text>
<xsl:text> *&#xA;</xsl:text>
<xsl:text> * This code is free software; you can redistribute it and/or modify it&#xA;</xsl:text>
<xsl:text> * under the terms of the GNU General Public License version 2 only, as&#xA;</xsl:text>
<xsl:text> * published by the Free Software Foundation. Oracle designates this&#xA;</xsl:text>
<xsl:text> * particular file as subject to the "Classpath" exception as provided&#xA;</xsl:text>
<xsl:text> * by Oracle in the LICENSE file that accompanied this code.&#xA;</xsl:text>
<xsl:text> *&#xA;</xsl:text>
<xsl:text> * This code is distributed in the hope that it will be useful, but WITHOUT&#xA;</xsl:text>
<xsl:text> * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or&#xA;</xsl:text>
<xsl:text> * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License&#xA;</xsl:text>
<xsl:text> * version 2 for more details (a copy is included in the LICENSE file that&#xA;</xsl:text>
<xsl:text> * accompanied this code).&#xA;</xsl:text>
<xsl:text> *&#xA;</xsl:text>
<xsl:text> * You should have received a copy of the GNU General Public License version&#xA;</xsl:text>
<xsl:text> * 2 along with this work; if not, write to the Free Software Foundation,&#xA;</xsl:text>
<xsl:text> * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.&#xA;</xsl:text>
<xsl:text> *&#xA;</xsl:text>
<xsl:text> * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA&#xA;</xsl:text>
<xsl:text> * or visit www.oracle.com if you need additional information or have any&#xA;</xsl:text>
<xsl:text> * questions.&#xA;</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> */&#xA;&#xA;</xsl:text>
</xsl:template>
<xsl:template name="GPL_CP_copyrightComment">
<xsl:text>/*&#xA; *</xsl:text>
<!-- The Copyright year from jvmti.xml -->
<xsl:value-of select="substring-after(substring-before($GPL_header, ' DO NOT ALTER'), '&#xA;')"/>
<!-- The GPL+CP Copyright header body -->
<xsl:value-of select="$GPL_CP_header_body"/>
<xsl:text> */&#xA;&#xA;</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 */&#xA;</xsl:text>
</xsl:template>
<xsl:template name="includeHeader">
<xsl:call-template name="copyrightComment"/>
<xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */&#xA;</xsl:text>

View File

@ -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 @@ JavaFrameStream* JavaFrameStream::from_current(JavaThread* thread, jlong magic,
//
// 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 @@ JavaFrameStream* JavaFrameStream::from_current(JavaThread* thread, jlong magic,
//
// 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 StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream,
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 StackWalk::fill_in_frames(jlong mode, JavaFrameStream& stream,
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 @@ static oop create_primitive_value_instance(StackValueCollection* values, int i,
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 @@ static objArrayHandle values_to_object_array(StackValueCollection* values, TRAPS
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 @@ static objArrayHandle monitors_to_object_array(GrowableArray<MonitorInfo*>* moni
}
// 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 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
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, &regMap);
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, &regMap);
{
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 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
// 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 @@ oop StackWalk::walk(Handle stackStream, jlong mode,
//
// 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 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
}
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 @@ jint StackWalk::moreFrames(Handle stackStream, jlong mode, jlong magic,
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()) {

View File

@ -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) {}
javaVFrame* java_frame() { return _jvf; }
void next() { _jvf = _jvf->java_sender(); }
bool at_end() { return _jvf == NULL; }
virtual void next()=0;
virtual bool at_end()=0;
Method* method() { return _jvf->method(); }
int bci() { return _jvf->bci(); }
virtual Method* method()=0;
virtual int bci()=0;
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 @@ public:
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 @@ public:
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

View File

@ -3897,10 +3897,6 @@ jint Arguments::parse_options_buffer(const char* name, char* buffer, const size_
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");

View File

@ -2972,6 +2972,7 @@ VMStructEntry VMStructs::localHotSpotVMStructs[] = {
#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 @@ VMStructEntry VMStructs::localHotSpotVMStructs[] = {
#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 @@ VMStructs::init() {
#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 @@ VMStructs::init() {
#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 @@ VMStructs::init() {
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,

View File

@ -52,17 +52,14 @@ void InternalVMTests::run() {
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 @@ void InternalVMTests::run() {
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

View File

@ -351,16 +351,29 @@ hotspot_fast_gc_gcold = \
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/Metaspace/FragmentMetaspace.java \
-runtime/Metaspace/FragmentMetaspaceSimple.java \
-runtime/Thread/TestThreadDumpMonitorContention.java \
-runtime/SharedArchiveFile/SharedBaseAddress.java \
-runtime/logging/MonitorMismatchTest.java \
-runtime/memory/ReserveMemory.java \
-runtime/memory/RunUnitTestsConcurrently.java \
-runtime/Unsafe/RangeCheck.java \
-runtime/Metaspace/FragmentMetaspace.java \
-runtime/Metaspace/FragmentMetaspaceSimple.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 @@ hotspot_fast_runtime = \
-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_jprt = \
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 = \
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 \

View File

@ -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

View File

@ -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";
}

View File

@ -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()

View File

@ -19,18 +19,29 @@
* 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) {
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());
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2011, 2014, Oracle and/or its affiliates. All rights reserved.
* 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
@ -19,96 +19,103 @@
* 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 "unittest.hpp"
#include "utilities/linkedlist.hpp"
#include "memory/allocation.hpp"
#include "memory/allocation.inline.hpp"
class Integer : public StackObj {
private:
int _value;
int _value;
public:
Integer(int i) : _value(i) { }
int value() const { return _value; }
bool equals(const Integer& i) const {
return _value == i.value();
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();
}
};
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) {
static 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");
ASSERT_EQ(expected[index], head->peek()->value())
<< "Unexpected value at index " << index;
head = head->next();
index ++;
index++;
}
}
void Test_linked_list() {
LinkedListImpl<Integer, ResourceObj::C_HEAP, mtTest> ll;
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;
// 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);
ASSERT_TRUE(ll.is_empty()) << "Start with empty list";
ll.add(six);
assert(!ll.is_empty(), "Should not be empty");
ASSERT_TRUE(!ll.is_empty()) << "Should not be empty";
Integer* i = ll.find(six);
assert(i != NULL, "Should find it");
ASSERT_TRUE(i != NULL) << "Should find it";
ASSERT_EQ(six.value(), i->value()) << "Should be 6";
i = ll.find(three);
assert(i == NULL, "Not in the list");
ASSERT_EQ(NULL, i) << "Not in the list";
LinkedListNode<Integer>* node = ll.find_node(six);
assert(node != NULL, "6 is in the list");
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);
// Test sorted linked list
SortedLinkedList<Integer, compare_Integer, ResourceObj::C_HEAP, mtTest> sl;
assert(sl.is_empty(), "Start with empty list");
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(ll_size == sl_size, "Should be the same size");
assert(ll.is_empty(), "No more entires");
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;
}
node = sl.find_node(four);
assert(node != NULL, "4 is in the list");
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);
}
#endif // PRODUCT

View File

@ -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.
}
}

View File

@ -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();
}
}

View File

@ -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.
pb = ProcessTools.createJavaProcessBuilder(
"-XX:+UnlockDiagnosticVMOptions",
"-XX:SharedArchiveFile=" + filename,
"-Xshare:on",
"--patch-module=java.naming=mods/java.naming",
"-Xshare:dump",
"--patch-module=java.naming=no/such/directory",
"-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("ro space:"); // Make sure archive got created.
output.shouldHaveExitValue(1);
// 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:dump",
"--patch-module=java.base=" + System.getProperty("test.classes"),
"-Xlog:class+path=info",
"-version");
new OutputAnalyzer(pb.start())
.shouldContain("--patch-module requires a regular file during dumping");
// 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);
}
}

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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);
}
}

View File

@ -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);
}
}
}