mirror of
https://github.com/openjdk/jdk.git
synced 2026-05-04 18:55:22 +00:00
Merge
This commit is contained in:
commit
42ec83b459
@ -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), \
|
||||
))
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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()
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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");
|
||||
}
|
||||
|
||||
@ -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 "?";
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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),
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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() {
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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();
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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; }
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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*) \
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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();
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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) \
|
||||
\
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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))
|
||||
|
||||
@ -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 [
|
||||
|
||||
@ -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>
|
||||
|
||||
@ -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 */
|
||||
|
||||
|
||||
@ -43,13 +43,56 @@
|
||||
<xsl:call-template name="microversion"/>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:variable name="GPL_header">
|
||||
<!-- The Copyright comment from jvmti.xml -->
|
||||
<xsl:value-of select="/comment()[position()=1]"/>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:variable name="GPL_CP_header_body">
|
||||
<xsl:text> * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
</xsl:text>
|
||||
<xsl:text> *
</xsl:text>
|
||||
<xsl:text> * This code is free software; you can redistribute it and/or modify it
</xsl:text>
|
||||
<xsl:text> * under the terms of the GNU General Public License version 2 only, as
</xsl:text>
|
||||
<xsl:text> * published by the Free Software Foundation. Oracle designates this
</xsl:text>
|
||||
<xsl:text> * particular file as subject to the "Classpath" exception as provided
</xsl:text>
|
||||
<xsl:text> * by Oracle in the LICENSE file that accompanied this code.
</xsl:text>
|
||||
<xsl:text> *
</xsl:text>
|
||||
<xsl:text> * This code is distributed in the hope that it will be useful, but WITHOUT
</xsl:text>
|
||||
<xsl:text> * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
</xsl:text>
|
||||
<xsl:text> * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
</xsl:text>
|
||||
<xsl:text> * version 2 for more details (a copy is included in the LICENSE file that
</xsl:text>
|
||||
<xsl:text> * accompanied this code).
</xsl:text>
|
||||
<xsl:text> *
</xsl:text>
|
||||
<xsl:text> * You should have received a copy of the GNU General Public License version
</xsl:text>
|
||||
<xsl:text> * 2 along with this work; if not, write to the Free Software Foundation,
</xsl:text>
|
||||
<xsl:text> * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
</xsl:text>
|
||||
<xsl:text> *
</xsl:text>
|
||||
<xsl:text> * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
</xsl:text>
|
||||
<xsl:text> * or visit www.oracle.com if you need additional information or have any
</xsl:text>
|
||||
<xsl:text> * questions.
</xsl:text>
|
||||
</xsl:variable>
|
||||
|
||||
<xsl:template name="copyrightComment">
|
||||
<xsl:text>/*</xsl:text>
|
||||
<!-- Copy the Copyright comment from jvmti.xml -->
|
||||
<xsl:value-of select="/comment()[position()=1]"/>
|
||||
<!-- The Copyright comment from jvmti.xml -->
|
||||
<xsl:value-of select="$GPL_header"/>
|
||||
<xsl:text> */

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

</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="include_GPL_CP_Header">
|
||||
<xsl:call-template name="GPL_CP_copyrightComment"/>
|
||||
<xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
</xsl:text>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template name="includeHeader">
|
||||
<xsl:call-template name="copyrightComment"/>
|
||||
<xsl:text> /* AUTOMATICALLY GENERATED FILE - DO NOT EDIT */
</xsl:text>
|
||||
|
||||
@ -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, ®Map);
|
||||
return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
|
||||
start_index, frames_array, THREAD);
|
||||
} else {
|
||||
JavaFrameStream stream(jt, mode);
|
||||
return fetchFirstBatch(stream, stackStream, mode, skip_frames, frame_count,
|
||||
start_index, frames_array, THREAD);
|
||||
}
|
||||
}
|
||||
|
||||
oop StackWalk::fetchFirstBatch(BaseFrameStream& stream, Handle stackStream,
|
||||
jlong mode, int skip_frames, int frame_count,
|
||||
int start_index, objArrayHandle frames_array, TRAPS) {
|
||||
methodHandle m_doStackWalk(THREAD, Universe::do_stack_walk_method());
|
||||
|
||||
// Setup traversal onto my stack.
|
||||
RegisterMap regMap(jt, true);
|
||||
JavaFrameStream stream(jt, ®Map);
|
||||
{
|
||||
Klass* stackWalker_klass = SystemDictionary::StackWalker_klass();
|
||||
Klass* abstractStackWalker_klass = SystemDictionary::AbstractStackWalker_klass();
|
||||
while (!stream.at_end()) {
|
||||
InstanceKlass* ik = stream.method()->method_holder();
|
||||
if (ik != stackWalker_klass &&
|
||||
@ -341,10 +365,7 @@ 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()) {
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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");
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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 \
|
||||
|
||||
@ -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
|
||||
|
||||
77
hotspot/test/native/classfile/test_symbolTable.cpp
Normal file
77
hotspot/test/native/classfile/test_symbolTable.cpp
Normal 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";
|
||||
}
|
||||
89
hotspot/test/native/oops/test_arrayOop.cpp
Normal file
89
hotspot/test/native/oops/test_arrayOop.cpp
Normal 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()
|
||||
@ -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());
|
||||
}
|
||||
@ -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
|
||||
|
||||
@ -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.
|
||||
}
|
||||
}
|
||||
@ -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();
|
||||
}
|
||||
}
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -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
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
157
hotspot/test/serviceability/sa/TestDefaultMethods.java
Normal file
157
hotspot/test/serviceability/sa/TestDefaultMethods.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user