mirror of
https://github.com/openjdk/jdk.git
synced 2025-09-21 11:34:38 +02:00
Merge
This commit is contained in:
commit
511c342454
199 changed files with 2775 additions and 528 deletions
|
@ -428,3 +428,4 @@ c1af79d122ec9f715fa29312b5e91763f3a4dfc4 jdk9-b20
|
||||||
dd472cdacc32e3afc7c5bfa7ef16ea0e0befb7fa jdk9-b23
|
dd472cdacc32e3afc7c5bfa7ef16ea0e0befb7fa jdk9-b23
|
||||||
dde2d03b0ea46a27650839e3a1d212c7c1f7b4c8 jdk9-b24
|
dde2d03b0ea46a27650839e3a1d212c7c1f7b4c8 jdk9-b24
|
||||||
6de94e8693240cec8aae11f6b42f43433456a733 jdk9-b25
|
6de94e8693240cec8aae11f6b42f43433456a733 jdk9-b25
|
||||||
|
48b95a073d752d6891cc0d1d2836b321ecf3ce0c jdk9-b26
|
||||||
|
|
|
@ -70,7 +70,8 @@ ifeq ($(INCLUDE_CDS), false)
|
||||||
CXXFLAGS += -DINCLUDE_CDS=0
|
CXXFLAGS += -DINCLUDE_CDS=0
|
||||||
CFLAGS += -DINCLUDE_CDS=0
|
CFLAGS += -DINCLUDE_CDS=0
|
||||||
|
|
||||||
Src_Files_EXCLUDE += filemap.cpp metaspaceShared.cpp
|
Src_Files_EXCLUDE += filemap.cpp metaspaceShared*.cpp sharedPathsMiscInfo.cpp \
|
||||||
|
systemDictionaryShared.cpp classLoaderExt.cpp sharedClassUtil.cpp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifeq ($(INCLUDE_ALL_GCS), false)
|
ifeq ($(INCLUDE_ALL_GCS), false)
|
||||||
|
|
|
@ -374,6 +374,7 @@ jprt.make.rule.test.targets.standard = \
|
||||||
${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_compiler}, \
|
${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_compiler}, \
|
||||||
${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_gc}, \
|
${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_gc}, \
|
||||||
${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_runtime}, \
|
${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_runtime}, \
|
||||||
|
${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_runtime_closed}, \
|
||||||
${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_serviceability}
|
${jprt.make.rule.test.targets.standard.reg.group:GROUP=hotspot_serviceability}
|
||||||
|
|
||||||
jprt.make.rule.test.targets.embedded = \
|
jprt.make.rule.test.targets.embedded = \
|
||||||
|
|
|
@ -731,7 +731,7 @@ InterpreterFrame *InterpreterFrame::build(Method* const method, TRAPS) {
|
||||||
if (method->is_static())
|
if (method->is_static())
|
||||||
object = method->constants()->pool_holder()->java_mirror();
|
object = method->constants()->pool_holder()->java_mirror();
|
||||||
else
|
else
|
||||||
object = (oop) locals[0];
|
object = (oop) (void*)locals[0];
|
||||||
monitor->set_obj(object);
|
monitor->set_obj(object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#ifndef CPU_ZERO_VM_FRAME_ZERO_INLINE_HPP
|
#ifndef CPU_ZERO_VM_FRAME_ZERO_INLINE_HPP
|
||||||
#define CPU_ZERO_VM_FRAME_ZERO_INLINE_HPP
|
#define CPU_ZERO_VM_FRAME_ZERO_INLINE_HPP
|
||||||
|
|
||||||
|
#include "code/codeCache.hpp"
|
||||||
|
|
||||||
// Constructors
|
// Constructors
|
||||||
|
|
||||||
inline frame::frame() {
|
inline frame::frame() {
|
||||||
|
|
|
@ -2246,7 +2246,7 @@ void os::print_siginfo(outputStream* st, void* siginfo) {
|
||||||
const siginfo_t* si = (const siginfo_t*)siginfo;
|
const siginfo_t* si = (const siginfo_t*)siginfo;
|
||||||
|
|
||||||
os::Posix::print_siginfo_brief(st, si);
|
os::Posix::print_siginfo_brief(st, si);
|
||||||
|
#if INCLUDE_CDS
|
||||||
if (si && (si->si_signo == SIGBUS || si->si_signo == SIGSEGV) &&
|
if (si && (si->si_signo == SIGBUS || si->si_signo == SIGSEGV) &&
|
||||||
UseSharedSpaces) {
|
UseSharedSpaces) {
|
||||||
FileMapInfo* mapinfo = FileMapInfo::current_info();
|
FileMapInfo* mapinfo = FileMapInfo::current_info();
|
||||||
|
@ -2256,6 +2256,7 @@ void os::print_siginfo(outputStream* st, void* siginfo) {
|
||||||
" possible disk/network problem.");
|
" possible disk/network problem.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
st->cr();
|
st->cr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,9 @@
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
#include "classfile/systemDictionaryShared.hpp"
|
||||||
|
#endif
|
||||||
#include "classfile/verificationType.hpp"
|
#include "classfile/verificationType.hpp"
|
||||||
#include "classfile/verifier.hpp"
|
#include "classfile/verifier.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
|
@ -60,6 +63,7 @@
|
||||||
#include "services/threadService.hpp"
|
#include "services/threadService.hpp"
|
||||||
#include "utilities/array.hpp"
|
#include "utilities/array.hpp"
|
||||||
#include "utilities/globalDefinitions.hpp"
|
#include "utilities/globalDefinitions.hpp"
|
||||||
|
#include "utilities/ostream.hpp"
|
||||||
|
|
||||||
// We generally try to create the oops directly when parsing, rather than
|
// We generally try to create the oops directly when parsing, rather than
|
||||||
// allocating temporary data structures and copying the bytes twice. A
|
// allocating temporary data structures and copying the bytes twice. A
|
||||||
|
@ -3786,7 +3790,15 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
instanceKlassHandle nullHandle;
|
instanceKlassHandle nullHandle;
|
||||||
|
|
||||||
// Figure out whether we can skip format checking (matching classic VM behavior)
|
// Figure out whether we can skip format checking (matching classic VM behavior)
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
// verify == true means it's a 'remote' class (i.e., non-boot class)
|
||||||
|
// Verification decision is based on BytecodeVerificationRemote flag
|
||||||
|
// for those classes.
|
||||||
|
_need_verify = (verify) ? BytecodeVerificationRemote :
|
||||||
|
BytecodeVerificationLocal;
|
||||||
|
} else {
|
||||||
_need_verify = Verifier::should_verify_for(class_loader(), verify);
|
_need_verify = Verifier::should_verify_for(class_loader(), verify);
|
||||||
|
}
|
||||||
|
|
||||||
// Set the verify flag in stream
|
// Set the verify flag in stream
|
||||||
cfs->set_verify(_need_verify);
|
cfs->set_verify(_need_verify);
|
||||||
|
@ -3805,6 +3817,18 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
u2 minor_version = cfs->get_u2_fast();
|
u2 minor_version = cfs->get_u2_fast();
|
||||||
u2 major_version = cfs->get_u2_fast();
|
u2 major_version = cfs->get_u2_fast();
|
||||||
|
|
||||||
|
if (DumpSharedSpaces && major_version < JAVA_1_5_VERSION) {
|
||||||
|
ResourceMark rm;
|
||||||
|
warning("Pre JDK 1.5 class not supported by CDS: %u.%u %s",
|
||||||
|
major_version, minor_version, name->as_C_string());
|
||||||
|
Exceptions::fthrow(
|
||||||
|
THREAD_AND_LOCATION,
|
||||||
|
vmSymbols::java_lang_UnsupportedClassVersionError(),
|
||||||
|
"Unsupported major.minor version for dump time %u.%u",
|
||||||
|
major_version,
|
||||||
|
minor_version);
|
||||||
|
}
|
||||||
|
|
||||||
// Check version numbers - we check this even with verifier off
|
// Check version numbers - we check this even with verifier off
|
||||||
if (!is_supported_version(major_version, minor_version)) {
|
if (!is_supported_version(major_version, minor_version)) {
|
||||||
if (name == NULL) {
|
if (name == NULL) {
|
||||||
|
@ -3912,6 +3936,18 @@ instanceKlassHandle ClassFileParser::parseClassFile(Symbol* name,
|
||||||
if (cfs->source() != NULL) tty->print(" from %s", cfs->source());
|
if (cfs->source() != NULL) tty->print(" from %s", cfs->source());
|
||||||
tty->print_cr("]");
|
tty->print_cr("]");
|
||||||
}
|
}
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
if (DumpLoadedClassList != NULL && cfs->source() != NULL && classlist_file->is_open()) {
|
||||||
|
// Only dump the classes that can be stored into CDS archive
|
||||||
|
if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
|
||||||
|
if (name != NULL) {
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
classlist_file->print_cr("%s", name->as_C_string());
|
||||||
|
classlist_file->flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
u2 super_class_index = cfs->get_u2_fast();
|
u2 super_class_index = cfs->get_u2_fast();
|
||||||
instanceKlassHandle super_klass = parse_super_class(super_class_index,
|
instanceKlassHandle super_klass = parse_super_class(super_class_index,
|
||||||
|
|
|
@ -26,8 +26,13 @@
|
||||||
#include "classfile/classFileParser.hpp"
|
#include "classfile/classFileParser.hpp"
|
||||||
#include "classfile/classFileStream.hpp"
|
#include "classfile/classFileStream.hpp"
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
|
#include "classfile/classLoaderExt.hpp"
|
||||||
#include "classfile/classLoaderData.inline.hpp"
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
#include "classfile/sharedPathsMiscInfo.hpp"
|
||||||
|
#include "classfile/sharedClassUtil.hpp"
|
||||||
|
#endif
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "compiler/compileBroker.hpp"
|
#include "compiler/compileBroker.hpp"
|
||||||
|
@ -35,6 +40,7 @@
|
||||||
#include "interpreter/bytecodeStream.hpp"
|
#include "interpreter/bytecodeStream.hpp"
|
||||||
#include "interpreter/oopMapCache.hpp"
|
#include "interpreter/oopMapCache.hpp"
|
||||||
#include "memory/allocation.inline.hpp"
|
#include "memory/allocation.inline.hpp"
|
||||||
|
#include "memory/filemap.hpp"
|
||||||
#include "memory/generation.hpp"
|
#include "memory/generation.hpp"
|
||||||
#include "memory/oopFactory.hpp"
|
#include "memory/oopFactory.hpp"
|
||||||
#include "memory/universe.inline.hpp"
|
#include "memory/universe.inline.hpp"
|
||||||
|
@ -114,8 +120,12 @@ PerfCounter* ClassLoader::_load_instance_class_failCounter = NULL;
|
||||||
|
|
||||||
ClassPathEntry* ClassLoader::_first_entry = NULL;
|
ClassPathEntry* ClassLoader::_first_entry = NULL;
|
||||||
ClassPathEntry* ClassLoader::_last_entry = NULL;
|
ClassPathEntry* ClassLoader::_last_entry = NULL;
|
||||||
|
int ClassLoader::_num_entries = 0;
|
||||||
PackageHashtable* ClassLoader::_package_hash_table = NULL;
|
PackageHashtable* ClassLoader::_package_hash_table = NULL;
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
|
||||||
|
#endif
|
||||||
// helper routines
|
// helper routines
|
||||||
bool string_starts_with(const char* str, const char* str_to_find) {
|
bool string_starts_with(const char* str, const char* str_to_find) {
|
||||||
size_t str_len = strlen(str);
|
size_t str_len = strlen(str);
|
||||||
|
@ -194,6 +204,14 @@ ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
|
||||||
// check if file exists
|
// check if file exists
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (os::stat(path, &st) == 0) {
|
if (os::stat(path, &st) == 0) {
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
// We have already check in ClassLoader::check_shared_classpath() that the directory is empty, so
|
||||||
|
// we should never find a file underneath it -- unless user has added a new file while we are running
|
||||||
|
// the dump, in which case let's quit!
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
// found file, open it
|
// found file, open it
|
||||||
int file_handle = os::open(path, 0, 0);
|
int file_handle = os::open(path, 0, 0);
|
||||||
if (file_handle != -1) {
|
if (file_handle != -1) {
|
||||||
|
@ -228,13 +246,13 @@ ClassPathZipEntry::~ClassPathZipEntry() {
|
||||||
FREE_C_HEAP_ARRAY(char, _zip_name, mtClass);
|
FREE_C_HEAP_ARRAY(char, _zip_name, mtClass);
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) {
|
u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) {
|
||||||
// enable call to C land
|
// enable call to C land
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
ThreadToNativeFromVM ttn(thread);
|
ThreadToNativeFromVM ttn(thread);
|
||||||
// check whether zip archive contains name
|
// check whether zip archive contains name
|
||||||
jint filesize, name_len;
|
jint name_len;
|
||||||
jzentry* entry = (*FindEntry)(_zip, name, &filesize, &name_len);
|
jzentry* entry = (*FindEntry)(_zip, name, filesize, &name_len);
|
||||||
if (entry == NULL) return NULL;
|
if (entry == NULL) return NULL;
|
||||||
u1* buffer;
|
u1* buffer;
|
||||||
char name_buf[128];
|
char name_buf[128];
|
||||||
|
@ -245,18 +263,32 @@ ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) {
|
||||||
filename = NEW_RESOURCE_ARRAY(char, name_len + 1);
|
filename = NEW_RESOURCE_ARRAY(char, name_len + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// file found, get pointer to class in mmaped jar file.
|
// file found, get pointer to the entry in mmapped jar file.
|
||||||
if (ReadMappedEntry == NULL ||
|
if (ReadMappedEntry == NULL ||
|
||||||
!(*ReadMappedEntry)(_zip, entry, &buffer, filename)) {
|
!(*ReadMappedEntry)(_zip, entry, &buffer, filename)) {
|
||||||
// mmaped access not available, perhaps due to compression,
|
// mmapped access not available, perhaps due to compression,
|
||||||
// read contents into resource array
|
// read contents into resource array
|
||||||
buffer = NEW_RESOURCE_ARRAY(u1, filesize);
|
int size = (*filesize) + ((nul_terminate) ? 1 : 0);
|
||||||
|
buffer = NEW_RESOURCE_ARRAY(u1, size);
|
||||||
if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL;
|
if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// return result
|
||||||
|
if (nul_terminate) {
|
||||||
|
buffer[*filesize] = 0;
|
||||||
|
}
|
||||||
|
return buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) {
|
||||||
|
jint filesize;
|
||||||
|
u1* buffer = open_entry(name, &filesize, false, CHECK_NULL);
|
||||||
|
if (buffer == NULL) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
if (UsePerfData) {
|
if (UsePerfData) {
|
||||||
ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize);
|
ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize);
|
||||||
}
|
}
|
||||||
// return result
|
|
||||||
return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated
|
return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -272,12 +304,13 @@ void ClassPathZipEntry::contents_do(void f(const char* name, void* context), voi
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st) : ClassPathEntry() {
|
LazyClassPathEntry::LazyClassPathEntry(char* path, const struct stat* st, bool throw_exception) : ClassPathEntry() {
|
||||||
_path = os::strdup_check_oom(path);
|
_path = os::strdup_check_oom(path);
|
||||||
_st = *st;
|
_st = *st;
|
||||||
_meta_index = NULL;
|
_meta_index = NULL;
|
||||||
_resolved_entry = NULL;
|
_resolved_entry = NULL;
|
||||||
_has_error = false;
|
_has_error = false;
|
||||||
|
_throw_exception = throw_exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
LazyClassPathEntry::~LazyClassPathEntry() {
|
LazyClassPathEntry::~LazyClassPathEntry() {
|
||||||
|
@ -293,7 +326,11 @@ ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) {
|
||||||
return (ClassPathEntry*) _resolved_entry;
|
return (ClassPathEntry*) _resolved_entry;
|
||||||
}
|
}
|
||||||
ClassPathEntry* new_entry = NULL;
|
ClassPathEntry* new_entry = NULL;
|
||||||
new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, CHECK_NULL);
|
new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, _throw_exception, CHECK_NULL);
|
||||||
|
if (!_throw_exception && new_entry == NULL) {
|
||||||
|
assert(!HAS_PENDING_EXCEPTION, "must be");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
{
|
{
|
||||||
ThreadCritical tc;
|
ThreadCritical tc;
|
||||||
if (_resolved_entry == NULL) {
|
if (_resolved_entry == NULL) {
|
||||||
|
@ -327,6 +364,23 @@ bool LazyClassPathEntry::is_lazy() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u1* LazyClassPathEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) {
|
||||||
|
if (_has_error) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
ClassPathEntry* cpe = resolve_entry(THREAD);
|
||||||
|
if (cpe == NULL) {
|
||||||
|
_has_error = true;
|
||||||
|
return NULL;
|
||||||
|
} else if (cpe->is_jar_file()) {
|
||||||
|
return ((ClassPathZipEntry*)cpe)->open_entry(name, filesize, nul_terminate,THREAD);
|
||||||
|
} else {
|
||||||
|
ShouldNotReachHere();
|
||||||
|
*filesize = 0;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void print_meta_index(LazyClassPathEntry* entry,
|
static void print_meta_index(LazyClassPathEntry* entry,
|
||||||
GrowableArray<char*>& meta_packages) {
|
GrowableArray<char*>& meta_packages) {
|
||||||
tty->print("[Meta index for %s=", entry->name());
|
tty->print("[Meta index for %s=", entry->name());
|
||||||
|
@ -337,15 +391,62 @@ static void print_meta_index(LazyClassPathEntry* entry,
|
||||||
tty->print_cr("]");
|
tty->print_cr("]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
void ClassLoader::exit_with_path_failure(const char* error, const char* message) {
|
||||||
|
assert(DumpSharedSpaces, "only called at dump time");
|
||||||
|
tty->print_cr("Hint: enable -XX:+TraceClassPaths to diagnose the failure");
|
||||||
|
vm_exit_during_initialization(error, message);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void ClassLoader::setup_meta_index() {
|
void ClassLoader::trace_class_path(const char* msg, const char* name) {
|
||||||
|
if (!TraceClassPaths) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (msg) {
|
||||||
|
tty->print("%s", msg);
|
||||||
|
}
|
||||||
|
if (name) {
|
||||||
|
if (strlen(name) < 256) {
|
||||||
|
tty->print("%s", name);
|
||||||
|
} else {
|
||||||
|
// For very long paths, we need to print each character separately,
|
||||||
|
// as print_cr() has a length limit
|
||||||
|
while (name[0] != '\0') {
|
||||||
|
tty->print("%c", name[0]);
|
||||||
|
name++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (msg && msg[0] == '[') {
|
||||||
|
tty->print_cr("]");
|
||||||
|
} else {
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassLoader::setup_bootstrap_meta_index() {
|
||||||
// Set up meta index which allows us to open boot jars lazily if
|
// Set up meta index which allows us to open boot jars lazily if
|
||||||
// class data sharing is enabled
|
// class data sharing is enabled
|
||||||
|
const char* meta_index_path = Arguments::get_meta_index_path();
|
||||||
|
const char* meta_index_dir = Arguments::get_meta_index_dir();
|
||||||
|
setup_meta_index(meta_index_path, meta_index_dir, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClassLoader::setup_meta_index(const char* meta_index_path, const char* meta_index_dir, int start_index) {
|
||||||
const char* known_version = "% VERSION 2";
|
const char* known_version = "% VERSION 2";
|
||||||
char* meta_index_path = Arguments::get_meta_index_path();
|
|
||||||
char* meta_index_dir = Arguments::get_meta_index_dir();
|
|
||||||
FILE* file = fopen(meta_index_path, "r");
|
FILE* file = fopen(meta_index_path, "r");
|
||||||
int line_no = 0;
|
int line_no = 0;
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
if (file != NULL) {
|
||||||
|
_shared_paths_misc_info->add_required_file(meta_index_path);
|
||||||
|
} else {
|
||||||
|
_shared_paths_misc_info->add_nonexist_path(meta_index_path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (file != NULL) {
|
if (file != NULL) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
LazyClassPathEntry* cur_entry = NULL;
|
LazyClassPathEntry* cur_entry = NULL;
|
||||||
|
@ -380,7 +481,7 @@ void ClassLoader::setup_meta_index() {
|
||||||
// Hand off current packages to current lazy entry (if any)
|
// Hand off current packages to current lazy entry (if any)
|
||||||
if ((cur_entry != NULL) &&
|
if ((cur_entry != NULL) &&
|
||||||
(boot_class_path_packages.length() > 0)) {
|
(boot_class_path_packages.length() > 0)) {
|
||||||
if (TraceClassLoading && Verbose) {
|
if ((TraceClassLoading || TraceClassPaths) && Verbose) {
|
||||||
print_meta_index(cur_entry, boot_class_path_packages);
|
print_meta_index(cur_entry, boot_class_path_packages);
|
||||||
}
|
}
|
||||||
MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0),
|
MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0),
|
||||||
|
@ -391,8 +492,10 @@ void ClassLoader::setup_meta_index() {
|
||||||
boot_class_path_packages.clear();
|
boot_class_path_packages.clear();
|
||||||
|
|
||||||
// Find lazy entry corresponding to this jar file
|
// Find lazy entry corresponding to this jar file
|
||||||
for (ClassPathEntry* entry = _first_entry; entry != NULL; entry = entry->next()) {
|
int count = 0;
|
||||||
if (entry->is_lazy() &&
|
for (ClassPathEntry* entry = _first_entry; entry != NULL; entry = entry->next(), count++) {
|
||||||
|
if (count >= start_index &&
|
||||||
|
entry->is_lazy() &&
|
||||||
string_starts_with(entry->name(), meta_index_dir) &&
|
string_starts_with(entry->name(), meta_index_dir) &&
|
||||||
string_ends_with(entry->name(), &package_name[2])) {
|
string_ends_with(entry->name(), &package_name[2])) {
|
||||||
cur_entry = (LazyClassPathEntry*) entry;
|
cur_entry = (LazyClassPathEntry*) entry;
|
||||||
|
@ -429,7 +532,7 @@ void ClassLoader::setup_meta_index() {
|
||||||
// Hand off current packages to current lazy entry (if any)
|
// Hand off current packages to current lazy entry (if any)
|
||||||
if ((cur_entry != NULL) &&
|
if ((cur_entry != NULL) &&
|
||||||
(boot_class_path_packages.length() > 0)) {
|
(boot_class_path_packages.length() > 0)) {
|
||||||
if (TraceClassLoading && Verbose) {
|
if ((TraceClassLoading || TraceClassPaths) && Verbose) {
|
||||||
print_meta_index(cur_entry, boot_class_path_packages);
|
print_meta_index(cur_entry, boot_class_path_packages);
|
||||||
}
|
}
|
||||||
MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0),
|
MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0),
|
||||||
|
@ -440,37 +543,88 @@ void ClassLoader::setup_meta_index() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
void ClassLoader::check_shared_classpath(const char *path) {
|
||||||
|
if (strcmp(path, "") == 0) {
|
||||||
|
exit_with_path_failure("Cannot have empty path in archived classpaths", NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
if (os::stat(path, &st) == 0) {
|
||||||
|
if ((st.st_mode & S_IFREG) != S_IFREG) { // is directory
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void ClassLoader::setup_bootstrap_search_path() {
|
void ClassLoader::setup_bootstrap_search_path() {
|
||||||
assert(_first_entry == NULL, "should not setup bootstrap class search path twice");
|
assert(_first_entry == NULL, "should not setup bootstrap class search path twice");
|
||||||
char* sys_class_path = os::strdup_check_oom(Arguments::get_sysclasspath());
|
char* sys_class_path = os::strdup_check_oom(Arguments::get_sysclasspath());
|
||||||
if (TraceClassLoading && Verbose) {
|
if (!PrintSharedArchiveAndExit) {
|
||||||
tty->print_cr("[Bootstrap loader class path=%s]", sys_class_path);
|
trace_class_path("[Bootstrap loader class path=", sys_class_path);
|
||||||
|
}
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
_shared_paths_misc_info->add_boot_classpath(Arguments::get_sysclasspath());
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
setup_search_path(sys_class_path);
|
||||||
|
os::free(sys_class_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
int len = (int)strlen(sys_class_path);
|
#if INCLUDE_CDS
|
||||||
|
int ClassLoader::get_shared_paths_misc_info_size() {
|
||||||
|
return _shared_paths_misc_info->get_used_bytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
void* ClassLoader::get_shared_paths_misc_info() {
|
||||||
|
return _shared_paths_misc_info->buffer();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) {
|
||||||
|
SharedPathsMiscInfo* checker = SharedClassUtil::allocate_shared_paths_misc_info((char*)buf, size);
|
||||||
|
bool result = checker->check();
|
||||||
|
delete checker;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ClassLoader::setup_search_path(char *class_path) {
|
||||||
|
int offset = 0;
|
||||||
|
int len = (int)strlen(class_path);
|
||||||
int end = 0;
|
int end = 0;
|
||||||
|
|
||||||
// Iterate over class path entries
|
// Iterate over class path entries
|
||||||
for (int start = 0; start < len; start = end) {
|
for (int start = 0; start < len; start = end) {
|
||||||
while (sys_class_path[end] && sys_class_path[end] != os::path_separator()[0]) {
|
while (class_path[end] && class_path[end] != os::path_separator()[0]) {
|
||||||
end++;
|
end++;
|
||||||
}
|
}
|
||||||
char* path = NEW_C_HEAP_ARRAY(char, end-start+1, mtClass);
|
EXCEPTION_MARK;
|
||||||
strncpy(path, &sys_class_path[start], end-start);
|
ResourceMark rm(THREAD);
|
||||||
|
char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
|
||||||
|
strncpy(path, &class_path[start], end - start);
|
||||||
path[end - start] = '\0';
|
path[end - start] = '\0';
|
||||||
update_class_path_entry_list(path, false);
|
update_class_path_entry_list(path, false);
|
||||||
FREE_C_HEAP_ARRAY(char, path, mtClass);
|
#if INCLUDE_CDS
|
||||||
while (sys_class_path[end] == os::path_separator()[0]) {
|
if (DumpSharedSpaces) {
|
||||||
|
check_shared_classpath(path);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
while (class_path[end] == os::path_separator()[0]) {
|
||||||
end++;
|
end++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
os::free(sys_class_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st, bool lazy, TRAPS) {
|
ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct stat* st,
|
||||||
|
bool lazy, bool throw_exception, TRAPS) {
|
||||||
JavaThread* thread = JavaThread::current();
|
JavaThread* thread = JavaThread::current();
|
||||||
if (lazy) {
|
if (lazy) {
|
||||||
return new LazyClassPathEntry(path, st);
|
return new LazyClassPathEntry(path, st, throw_exception);
|
||||||
}
|
}
|
||||||
ClassPathEntry* new_entry = NULL;
|
ClassPathEntry* new_entry = NULL;
|
||||||
if ((st->st_mode & S_IFREG) == S_IFREG) {
|
if ((st->st_mode & S_IFREG) == S_IFREG) {
|
||||||
|
@ -479,7 +633,11 @@ ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct st
|
||||||
char canonical_path[JVM_MAXPATHLEN];
|
char canonical_path[JVM_MAXPATHLEN];
|
||||||
if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
|
if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
|
||||||
// This matches the classic VM
|
// This matches the classic VM
|
||||||
|
if (throw_exception) {
|
||||||
THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL);
|
THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL);
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
char* error_msg = NULL;
|
char* error_msg = NULL;
|
||||||
jzfile* zip;
|
jzfile* zip;
|
||||||
|
@ -491,7 +649,7 @@ ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct st
|
||||||
}
|
}
|
||||||
if (zip != NULL && error_msg == NULL) {
|
if (zip != NULL && error_msg == NULL) {
|
||||||
new_entry = new ClassPathZipEntry(zip, path);
|
new_entry = new ClassPathZipEntry(zip, path);
|
||||||
if (TraceClassLoading) {
|
if (TraceClassLoading || TraceClassPaths) {
|
||||||
tty->print_cr("[Opened %s]", path);
|
tty->print_cr("[Opened %s]", path);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -505,12 +663,16 @@ ClassPathEntry* ClassLoader::create_class_path_entry(char *path, const struct st
|
||||||
msg = NEW_RESOURCE_ARRAY(char, len); ;
|
msg = NEW_RESOURCE_ARRAY(char, len); ;
|
||||||
jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path);
|
jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path);
|
||||||
}
|
}
|
||||||
|
if (throw_exception) {
|
||||||
THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL);
|
THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL);
|
||||||
|
} else {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Directory
|
// Directory
|
||||||
new_entry = new ClassPathDirEntry(path);
|
new_entry = new ClassPathDirEntry(path);
|
||||||
if (TraceClassLoading) {
|
if (TraceClassLoading || TraceClassPaths) {
|
||||||
tty->print_cr("[Path %s]", path);
|
tty->print_cr("[Path %s]", path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -571,23 +733,37 @@ void ClassLoader::add_to_list(ClassPathEntry *new_entry) {
|
||||||
_last_entry = new_entry;
|
_last_entry = new_entry;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_num_entries ++;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClassLoader::update_class_path_entry_list(char *path,
|
// Returns true IFF the file/dir exists and the entry was successfully created.
|
||||||
bool check_for_duplicates) {
|
bool ClassLoader::update_class_path_entry_list(char *path,
|
||||||
|
bool check_for_duplicates,
|
||||||
|
bool throw_exception) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (os::stat(path, &st) == 0) {
|
if (os::stat(path, &st) == 0) {
|
||||||
// File or directory found
|
// File or directory found
|
||||||
ClassPathEntry* new_entry = NULL;
|
ClassPathEntry* new_entry = NULL;
|
||||||
Thread* THREAD = Thread::current();
|
Thread* THREAD = Thread::current();
|
||||||
new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, CHECK);
|
new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, throw_exception, CHECK_(false));
|
||||||
|
if (new_entry == NULL) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
// The kernel VM adds dynamically to the end of the classloader path and
|
// The kernel VM adds dynamically to the end of the classloader path and
|
||||||
// doesn't reorder the bootclasspath which would break java.lang.Package
|
// doesn't reorder the bootclasspath which would break java.lang.Package
|
||||||
// (see PackageInfo).
|
// (see PackageInfo).
|
||||||
// Add new entry to linked list
|
// Add new entry to linked list
|
||||||
if (!check_for_duplicates || !contains_entry(new_entry)) {
|
if (!check_for_duplicates || !contains_entry(new_entry)) {
|
||||||
add_to_list(new_entry);
|
ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
_shared_paths_misc_info->add_nonexist_path(path);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -739,10 +915,10 @@ public:
|
||||||
assert(n == number_of_entries(), "just checking");
|
assert(n == number_of_entries(), "just checking");
|
||||||
}
|
}
|
||||||
|
|
||||||
void copy_table(char** top, char* end, PackageHashtable* table);
|
CDS_ONLY(void copy_table(char** top, char* end, PackageHashtable* table);)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
void PackageHashtable::copy_table(char** top, char* end,
|
void PackageHashtable::copy_table(char** top, char* end,
|
||||||
PackageHashtable* table) {
|
PackageHashtable* table) {
|
||||||
// Copy (relocate) the table to the shared space.
|
// Copy (relocate) the table to the shared space.
|
||||||
|
@ -750,33 +926,30 @@ void PackageHashtable::copy_table(char** top, char* end,
|
||||||
|
|
||||||
// Calculate the space needed for the package name strings.
|
// Calculate the space needed for the package name strings.
|
||||||
int i;
|
int i;
|
||||||
int n = 0;
|
intptr_t* tableSize = (intptr_t*)(*top);
|
||||||
for (i = 0; i < table_size(); ++i) {
|
*top += sizeof(intptr_t); // For table size
|
||||||
for (PackageInfo* pp = table->bucket(i);
|
char* tableStart = *top;
|
||||||
pp != NULL;
|
|
||||||
pp = pp->next()) {
|
|
||||||
n += (int)(strlen(pp->pkgname()) + 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (*top + n + sizeof(intptr_t) >= end) {
|
|
||||||
report_out_of_shared_space(SharedMiscData);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy the table data (the strings) to the shared space.
|
|
||||||
n = align_size_up(n, sizeof(HeapWord));
|
|
||||||
*(intptr_t*)(*top) = n;
|
|
||||||
*top += sizeof(intptr_t);
|
|
||||||
|
|
||||||
for (i = 0; i < table_size(); ++i) {
|
for (i = 0; i < table_size(); ++i) {
|
||||||
for (PackageInfo* pp = table->bucket(i);
|
for (PackageInfo* pp = table->bucket(i);
|
||||||
pp != NULL;
|
pp != NULL;
|
||||||
pp = pp->next()) {
|
pp = pp->next()) {
|
||||||
int n1 = (int)(strlen(pp->pkgname()) + 1);
|
int n1 = (int)(strlen(pp->pkgname()) + 1);
|
||||||
|
if (*top + n1 >= end) {
|
||||||
|
report_out_of_shared_space(SharedMiscData);
|
||||||
|
}
|
||||||
pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1));
|
pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1));
|
||||||
*top += n1;
|
*top += n1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord));
|
*top = (char*)align_size_up((intptr_t)*top, sizeof(HeapWord));
|
||||||
|
if (*top >= end) {
|
||||||
|
report_out_of_shared_space(SharedMiscData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write table size
|
||||||
|
intptr_t len = *top - (char*)tableStart;
|
||||||
|
*tableSize = len;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -787,7 +960,7 @@ void ClassLoader::copy_package_info_buckets(char** top, char* end) {
|
||||||
void ClassLoader::copy_package_info_table(char** top, char* end) {
|
void ClassLoader::copy_package_info_table(char** top, char* end) {
|
||||||
_package_hash_table->copy_table(top, end, _package_hash_table);
|
_package_hash_table->copy_table(top, end, _package_hash_table);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
PackageInfo* ClassLoader::lookup_package(const char *pkgname) {
|
PackageInfo* ClassLoader::lookup_package(const char *pkgname) {
|
||||||
const char *cp = strrchr(pkgname, '/');
|
const char *cp = strrchr(pkgname, '/');
|
||||||
|
@ -880,7 +1053,8 @@ objArrayOop ClassLoader::get_system_packages(TRAPS) {
|
||||||
|
|
||||||
instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
|
instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
|
||||||
ResourceMark rm(THREAD);
|
ResourceMark rm(THREAD);
|
||||||
EventMark m("loading class %s", h_name->as_C_string());
|
const char* class_name = h_name->as_C_string();
|
||||||
|
EventMark m("loading class %s", class_name);
|
||||||
ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
|
ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
|
||||||
|
|
||||||
stringStream st;
|
stringStream st;
|
||||||
|
@ -888,18 +1062,24 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
|
||||||
// st.print("%s.class", h_name->as_utf8());
|
// st.print("%s.class", h_name->as_utf8());
|
||||||
st.print_raw(h_name->as_utf8());
|
st.print_raw(h_name->as_utf8());
|
||||||
st.print_raw(".class");
|
st.print_raw(".class");
|
||||||
char* name = st.as_string();
|
const char* file_name = st.as_string();
|
||||||
|
ClassLoaderExt::Context context(class_name, file_name, THREAD);
|
||||||
|
|
||||||
// Lookup stream for parsing .class file
|
// Lookup stream for parsing .class file
|
||||||
ClassFileStream* stream = NULL;
|
ClassFileStream* stream = NULL;
|
||||||
int classpath_index = 0;
|
int classpath_index = 0;
|
||||||
|
ClassPathEntry* e = NULL;
|
||||||
|
instanceKlassHandle h;
|
||||||
{
|
{
|
||||||
PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
|
PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
|
||||||
((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
|
((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
|
||||||
PerfClassTraceTime::CLASS_LOAD);
|
PerfClassTraceTime::CLASS_LOAD);
|
||||||
ClassPathEntry* e = _first_entry;
|
e = _first_entry;
|
||||||
while (e != NULL) {
|
while (e != NULL) {
|
||||||
stream = e->open_stream(name, CHECK_NULL);
|
stream = e->open_stream(file_name, CHECK_NULL);
|
||||||
|
if (!context.check(stream, classpath_index)) {
|
||||||
|
return h; // NULL
|
||||||
|
}
|
||||||
if (stream != NULL) {
|
if (stream != NULL) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -908,9 +1088,7 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceKlassHandle h;
|
|
||||||
if (stream != NULL) {
|
if (stream != NULL) {
|
||||||
|
|
||||||
// class file found, parse it
|
// class file found, parse it
|
||||||
ClassFileParser parser(stream);
|
ClassFileParser parser(stream);
|
||||||
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
||||||
|
@ -920,12 +1098,19 @@ instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
|
||||||
loader_data,
|
loader_data,
|
||||||
protection_domain,
|
protection_domain,
|
||||||
parsed_name,
|
parsed_name,
|
||||||
false,
|
context.should_verify(classpath_index),
|
||||||
CHECK_(h));
|
THREAD);
|
||||||
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
// add to package table
|
ResourceMark rm;
|
||||||
if (add_package(name, classpath_index, THREAD)) {
|
if (DumpSharedSpaces) {
|
||||||
h = result;
|
tty->print_cr("Preload Error: Failed to load %s", class_name);
|
||||||
|
}
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
h = context.record_result(classpath_index, e, result, THREAD);
|
||||||
|
} else {
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
tty->print_cr("Preload Error: Cannot find %s", class_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1020,14 +1205,27 @@ void ClassLoader::initialize() {
|
||||||
|
|
||||||
// lookup zip library entry points
|
// lookup zip library entry points
|
||||||
load_zip_library();
|
load_zip_library();
|
||||||
|
#if INCLUDE_CDS
|
||||||
// initialize search path
|
// initialize search path
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
_shared_paths_misc_info = SharedClassUtil::allocate_shared_paths_misc_info();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
setup_bootstrap_search_path();
|
setup_bootstrap_search_path();
|
||||||
if (LazyBootClassLoader) {
|
if (LazyBootClassLoader) {
|
||||||
// set up meta index which makes boot classpath initialization lazier
|
// set up meta index which makes boot classpath initialization lazier
|
||||||
setup_meta_index();
|
setup_bootstrap_meta_index();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
void ClassLoader::initialize_shared_path() {
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
ClassLoaderExt::setup_search_paths();
|
||||||
|
_shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
jlong ClassLoader::classloader_time_ms() {
|
jlong ClassLoader::classloader_time_ms() {
|
||||||
return UsePerfData ?
|
return UsePerfData ?
|
||||||
|
|
|
@ -107,6 +107,7 @@ class ClassPathZipEntry: public ClassPathEntry {
|
||||||
const char* name() { return _zip_name; }
|
const char* name() { return _zip_name; }
|
||||||
ClassPathZipEntry(jzfile* zip, const char* zip_name);
|
ClassPathZipEntry(jzfile* zip, const char* zip_name);
|
||||||
~ClassPathZipEntry();
|
~ClassPathZipEntry();
|
||||||
|
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
|
||||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||||
void contents_do(void f(const char* name, void* context), void* context);
|
void contents_do(void f(const char* name, void* context), void* context);
|
||||||
// Debugging
|
// Debugging
|
||||||
|
@ -122,13 +123,15 @@ class LazyClassPathEntry: public ClassPathEntry {
|
||||||
struct stat _st;
|
struct stat _st;
|
||||||
MetaIndex* _meta_index;
|
MetaIndex* _meta_index;
|
||||||
bool _has_error;
|
bool _has_error;
|
||||||
|
bool _throw_exception;
|
||||||
volatile ClassPathEntry* _resolved_entry;
|
volatile ClassPathEntry* _resolved_entry;
|
||||||
ClassPathEntry* resolve_entry(TRAPS);
|
ClassPathEntry* resolve_entry(TRAPS);
|
||||||
public:
|
public:
|
||||||
bool is_jar_file();
|
bool is_jar_file();
|
||||||
const char* name() { return _path; }
|
const char* name() { return _path; }
|
||||||
LazyClassPathEntry(char* path, const struct stat* st);
|
LazyClassPathEntry(char* path, const struct stat* st, bool throw_exception);
|
||||||
virtual ~LazyClassPathEntry();
|
virtual ~LazyClassPathEntry();
|
||||||
|
u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
|
||||||
|
|
||||||
ClassFileStream* open_stream(const char* name, TRAPS);
|
ClassFileStream* open_stream(const char* name, TRAPS);
|
||||||
void set_meta_index(MetaIndex* meta_index) { _meta_index = meta_index; }
|
void set_meta_index(MetaIndex* meta_index) { _meta_index = meta_index; }
|
||||||
|
@ -140,6 +143,7 @@ class LazyClassPathEntry: public ClassPathEntry {
|
||||||
|
|
||||||
class PackageHashtable;
|
class PackageHashtable;
|
||||||
class PackageInfo;
|
class PackageInfo;
|
||||||
|
class SharedPathsMiscInfo;
|
||||||
template <MEMFLAGS F> class HashtableBucket;
|
template <MEMFLAGS F> class HashtableBucket;
|
||||||
|
|
||||||
class ClassLoader: AllStatic {
|
class ClassLoader: AllStatic {
|
||||||
|
@ -147,7 +151,7 @@ class ClassLoader: AllStatic {
|
||||||
enum SomeConstants {
|
enum SomeConstants {
|
||||||
package_hash_table_size = 31 // Number of buckets
|
package_hash_table_size = 31 // Number of buckets
|
||||||
};
|
};
|
||||||
private:
|
protected:
|
||||||
friend class LazyClassPathEntry;
|
friend class LazyClassPathEntry;
|
||||||
|
|
||||||
// Performance counters
|
// Performance counters
|
||||||
|
@ -189,10 +193,15 @@ class ClassLoader: AllStatic {
|
||||||
static ClassPathEntry* _first_entry;
|
static ClassPathEntry* _first_entry;
|
||||||
// Last entry in linked list of ClassPathEntry instances
|
// Last entry in linked list of ClassPathEntry instances
|
||||||
static ClassPathEntry* _last_entry;
|
static ClassPathEntry* _last_entry;
|
||||||
|
static int _num_entries;
|
||||||
|
|
||||||
// Hash table used to keep track of loaded packages
|
// Hash table used to keep track of loaded packages
|
||||||
static PackageHashtable* _package_hash_table;
|
static PackageHashtable* _package_hash_table;
|
||||||
static const char* _shared_archive;
|
static const char* _shared_archive;
|
||||||
|
|
||||||
|
// Info used by CDS
|
||||||
|
CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
|
||||||
|
|
||||||
// Hash function
|
// Hash function
|
||||||
static unsigned int hash(const char *s, int n);
|
static unsigned int hash(const char *s, int n);
|
||||||
// Returns the package file name corresponding to the specified package
|
// Returns the package file name corresponding to the specified package
|
||||||
|
@ -203,19 +212,23 @@ class ClassLoader: AllStatic {
|
||||||
static bool add_package(const char *pkgname, int classpath_index, TRAPS);
|
static bool add_package(const char *pkgname, int classpath_index, TRAPS);
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
static void setup_meta_index();
|
static void setup_bootstrap_meta_index();
|
||||||
|
static void setup_meta_index(const char* meta_index_path, const char* meta_index_dir,
|
||||||
|
int start_index);
|
||||||
static void setup_bootstrap_search_path();
|
static void setup_bootstrap_search_path();
|
||||||
|
static void setup_search_path(char *class_path);
|
||||||
|
|
||||||
static void load_zip_library();
|
static void load_zip_library();
|
||||||
static ClassPathEntry* create_class_path_entry(char *path, const struct stat* st,
|
static ClassPathEntry* create_class_path_entry(char *path, const struct stat* st,
|
||||||
bool lazy, TRAPS);
|
bool lazy, bool throw_exception, TRAPS);
|
||||||
|
|
||||||
// Canonicalizes path names, so strcmp will work properly. This is mainly
|
// Canonicalizes path names, so strcmp will work properly. This is mainly
|
||||||
// to avoid confusing the zip library
|
// to avoid confusing the zip library
|
||||||
static bool get_canonical_path(char* orig, char* out, int len);
|
static bool get_canonical_path(char* orig, char* out, int len);
|
||||||
public:
|
public:
|
||||||
// Used by the kernel jvm.
|
static bool update_class_path_entry_list(char *path,
|
||||||
static void update_class_path_entry_list(char *path,
|
bool check_for_duplicates,
|
||||||
bool check_for_duplicates);
|
bool throw_exception=true);
|
||||||
static void print_bootclasspath();
|
static void print_bootclasspath();
|
||||||
|
|
||||||
// Timing
|
// Timing
|
||||||
|
@ -298,6 +311,7 @@ class ClassLoader: AllStatic {
|
||||||
|
|
||||||
// Initialization
|
// Initialization
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
CDS_ONLY(static void initialize_shared_path();)
|
||||||
static void create_package_info_table();
|
static void create_package_info_table();
|
||||||
static void create_package_info_table(HashtableBucket<mtClass> *t, int length,
|
static void create_package_info_table(HashtableBucket<mtClass> *t, int length,
|
||||||
int number_of_entries);
|
int number_of_entries);
|
||||||
|
@ -312,10 +326,21 @@ class ClassLoader: AllStatic {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
// Sharing dump and restore
|
// Sharing dump and restore
|
||||||
static void copy_package_info_buckets(char** top, char* end);
|
static void copy_package_info_buckets(char** top, char* end);
|
||||||
static void copy_package_info_table(char** top, char* end);
|
static void copy_package_info_table(char** top, char* end);
|
||||||
|
|
||||||
|
static void check_shared_classpath(const char *path);
|
||||||
|
static void finalize_shared_paths_misc_info();
|
||||||
|
static int get_shared_paths_misc_info_size();
|
||||||
|
static void* get_shared_paths_misc_info();
|
||||||
|
static bool check_shared_paths_misc_info(void* info, int size);
|
||||||
|
static void exit_with_path_failure(const char* error, const char* message);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static void trace_class_path(const char* msg, const char* name = NULL);
|
||||||
|
|
||||||
// VM monitoring and management support
|
// VM monitoring and management support
|
||||||
static jlong classloader_time_ms();
|
static jlong classloader_time_ms();
|
||||||
static jlong class_method_total_size();
|
static jlong class_method_total_size();
|
||||||
|
@ -339,7 +364,7 @@ class ClassLoader: AllStatic {
|
||||||
|
|
||||||
// Force compilation of all methods in all classes in bootstrap class path (stress test)
|
// Force compilation of all methods in all classes in bootstrap class path (stress test)
|
||||||
#ifndef PRODUCT
|
#ifndef PRODUCT
|
||||||
private:
|
protected:
|
||||||
static int _compile_the_world_class_counter;
|
static int _compile_the_world_class_counter;
|
||||||
static int _compile_the_world_method_counter;
|
static int _compile_the_world_method_counter;
|
||||||
public:
|
public:
|
||||||
|
|
69
hotspot/src/share/vm/classfile/classLoaderExt.hpp
Normal file
69
hotspot/src/share/vm/classfile/classLoaderExt.hpp
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
|
||||||
|
#define SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
|
||||||
|
|
||||||
|
#include "classfile/classLoader.hpp"
|
||||||
|
|
||||||
|
class ClassLoaderExt: public ClassLoader { // AllStatic
|
||||||
|
public:
|
||||||
|
|
||||||
|
class Context {
|
||||||
|
const char* _file_name;
|
||||||
|
public:
|
||||||
|
Context(const char* class_name, const char* file_name, TRAPS) {
|
||||||
|
_file_name = file_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check(ClassFileStream* stream, const int classpath_index) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool should_verify(int classpath_index) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
instanceKlassHandle record_result(const int classpath_index,
|
||||||
|
ClassPathEntry* e, instanceKlassHandle result, TRAPS) {
|
||||||
|
if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) {
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
result->set_shared_classpath_index(classpath_index);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
return instanceKlassHandle(); // NULL
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void add_class_path_entry(char* path, bool check_for_duplicates,
|
||||||
|
ClassPathEntry* new_entry) {
|
||||||
|
ClassLoader::add_to_list(new_entry);
|
||||||
|
}
|
||||||
|
static void setup_search_paths() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
|
|
@ -220,6 +220,29 @@ void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
|
||||||
_pd_cache_table->roots_oops_do(strong, weak);
|
_pd_cache_table->roots_oops_do(strong, weak);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Dictionary::remove_classes_in_error_state() {
|
||||||
|
assert(DumpSharedSpaces, "supported only when dumping");
|
||||||
|
DictionaryEntry* probe = NULL;
|
||||||
|
for (int index = 0; index < table_size(); index++) {
|
||||||
|
for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
|
||||||
|
probe = *p;
|
||||||
|
InstanceKlass* ik = InstanceKlass::cast(probe->klass());
|
||||||
|
if (ik->is_in_error_state()) { // purge this entry
|
||||||
|
*p = probe->next();
|
||||||
|
if (probe == _current_class_entry) {
|
||||||
|
_current_class_entry = NULL;
|
||||||
|
}
|
||||||
|
free_entry(probe);
|
||||||
|
ResourceMark rm;
|
||||||
|
tty->print_cr("Removed error class: %s", ik->external_name());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
p = probe->next_addr();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Dictionary::always_strong_oops_do(OopClosure* blk) {
|
void Dictionary::always_strong_oops_do(OopClosure* blk) {
|
||||||
// Follow all system classes and temporary placeholders in dictionary; only
|
// Follow all system classes and temporary placeholders in dictionary; only
|
||||||
// protection domain oops contain references into the heap. In a first
|
// protection domain oops contain references into the heap. In a first
|
||||||
|
@ -693,16 +716,17 @@ void SymbolPropertyTable::methods_do(void f(Method*)) {
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
#ifndef PRODUCT
|
|
||||||
|
|
||||||
void Dictionary::print() {
|
void Dictionary::print(bool details) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
HandleMark hm;
|
HandleMark hm;
|
||||||
|
|
||||||
|
if (details) {
|
||||||
tty->print_cr("Java system dictionary (table_size=%d, classes=%d)",
|
tty->print_cr("Java system dictionary (table_size=%d, classes=%d)",
|
||||||
table_size(), number_of_entries());
|
table_size(), number_of_entries());
|
||||||
tty->print_cr("^ indicates that initiating loader is different from "
|
tty->print_cr("^ indicates that initiating loader is different from "
|
||||||
"defining loader");
|
"defining loader");
|
||||||
|
}
|
||||||
|
|
||||||
for (int index = 0; index < table_size(); index++) {
|
for (int index = 0; index < table_size(); index++) {
|
||||||
for (DictionaryEntry* probe = bucket(index);
|
for (DictionaryEntry* probe = bucket(index);
|
||||||
|
@ -713,20 +737,27 @@ void Dictionary::print() {
|
||||||
ClassLoaderData* loader_data = probe->loader_data();
|
ClassLoaderData* loader_data = probe->loader_data();
|
||||||
bool is_defining_class =
|
bool is_defining_class =
|
||||||
(loader_data == InstanceKlass::cast(e)->class_loader_data());
|
(loader_data == InstanceKlass::cast(e)->class_loader_data());
|
||||||
tty->print("%s%s", is_defining_class ? " " : "^",
|
tty->print("%s%s", ((!details) || is_defining_class) ? " " : "^",
|
||||||
e->external_name());
|
e->external_name());
|
||||||
|
|
||||||
|
if (details) {
|
||||||
tty->print(", loader ");
|
tty->print(", loader ");
|
||||||
|
if (loader_data != NULL) {
|
||||||
loader_data->print_value();
|
loader_data->print_value();
|
||||||
tty->cr();
|
} else {
|
||||||
|
tty->print("NULL");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
tty->cr();
|
tty->cr();
|
||||||
_pd_cache_table->print();
|
}
|
||||||
tty->cr();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
if (details) {
|
||||||
|
tty->cr();
|
||||||
|
_pd_cache_table->print();
|
||||||
|
}
|
||||||
|
tty->cr();
|
||||||
|
}
|
||||||
|
|
||||||
void Dictionary::verify() {
|
void Dictionary::verify() {
|
||||||
guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
|
guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
|
||||||
|
|
|
@ -100,6 +100,7 @@ public:
|
||||||
void methods_do(void f(Method*));
|
void methods_do(void f(Method*));
|
||||||
|
|
||||||
void unlink(BoolObjectClosure* is_alive);
|
void unlink(BoolObjectClosure* is_alive);
|
||||||
|
void remove_classes_in_error_state();
|
||||||
|
|
||||||
// Classes loaded by the bootstrap loader are always strongly reachable.
|
// Classes loaded by the bootstrap loader are always strongly reachable.
|
||||||
// If we're not doing class unloading, all classes are strongly reachable.
|
// If we're not doing class unloading, all classes are strongly reachable.
|
||||||
|
@ -127,9 +128,7 @@ public:
|
||||||
|
|
||||||
ProtectionDomainCacheEntry* cache_get(oop protection_domain);
|
ProtectionDomainCacheEntry* cache_get(oop protection_domain);
|
||||||
|
|
||||||
#ifndef PRODUCT
|
void print(bool details = true);
|
||||||
void print();
|
|
||||||
#endif
|
|
||||||
void verify();
|
void verify();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
69
hotspot/src/share/vm/classfile/sharedClassUtil.hpp
Normal file
69
hotspot/src/share/vm/classfile/sharedClassUtil.hpp
Normal file
|
@ -0,0 +1,69 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP
|
||||||
|
#define SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP
|
||||||
|
|
||||||
|
#include "classfile/sharedPathsMiscInfo.hpp"
|
||||||
|
#include "memory/filemap.hpp"
|
||||||
|
|
||||||
|
class SharedClassUtil : AllStatic {
|
||||||
|
public:
|
||||||
|
|
||||||
|
static SharedPathsMiscInfo* allocate_shared_paths_misc_info() {
|
||||||
|
return new SharedPathsMiscInfo();
|
||||||
|
}
|
||||||
|
|
||||||
|
static SharedPathsMiscInfo* allocate_shared_paths_misc_info(char* buf, int size) {
|
||||||
|
return new SharedPathsMiscInfo(buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
static FileMapInfo::FileMapHeader* allocate_file_map_header() {
|
||||||
|
return new FileMapInfo::FileMapHeader();
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t file_map_header_size() {
|
||||||
|
return sizeof(FileMapInfo::FileMapHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
static size_t shared_class_path_entry_size() {
|
||||||
|
return sizeof(SharedClassPathEntry);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void update_shared_classpath(ClassPathEntry *cpe,
|
||||||
|
SharedClassPathEntry* ent,
|
||||||
|
time_t timestamp,
|
||||||
|
long filesize, TRAPS) {
|
||||||
|
ent->_timestamp = timestamp;
|
||||||
|
ent->_filesize = filesize;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void initialize(TRAPS) {}
|
||||||
|
|
||||||
|
inline static bool is_shared_boot_class(Klass* klass) {
|
||||||
|
return (klass->_shared_class_path_index >= 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARE_VM_CLASSFILE_SHAREDCLASSUTIL_HPP
|
154
hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp
Normal file
154
hotspot/src/share/vm/classfile/sharedPathsMiscInfo.cpp
Normal file
|
@ -0,0 +1,154 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoader.hpp"
|
||||||
|
#include "classfile/classLoaderData.inline.hpp"
|
||||||
|
#include "classfile/sharedPathsMiscInfo.hpp"
|
||||||
|
#include "memory/allocation.inline.hpp"
|
||||||
|
#include "memory/metaspaceShared.hpp"
|
||||||
|
#include "runtime/arguments.hpp"
|
||||||
|
|
||||||
|
void SharedPathsMiscInfo::add_path(const char* path, int type) {
|
||||||
|
if (TraceClassPaths) {
|
||||||
|
tty->print("[type=%s] ", type_name(type));
|
||||||
|
trace_class_path("[Add misc shared path ", path);
|
||||||
|
}
|
||||||
|
write(path, strlen(path) + 1);
|
||||||
|
write_jint(jint(type));
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedPathsMiscInfo::ensure_size(size_t needed_bytes) {
|
||||||
|
assert(_allocated, "cannot modify buffer during validation.");
|
||||||
|
int used = get_used_bytes();
|
||||||
|
int target = used + int(needed_bytes);
|
||||||
|
if (target > _buf_size) {
|
||||||
|
_buf_size = _buf_size * 2 + (int)needed_bytes;
|
||||||
|
_buf_start = REALLOC_C_HEAP_ARRAY(char, _buf_start, _buf_size, mtClass);
|
||||||
|
_cur_ptr = _buf_start + used;
|
||||||
|
_end_ptr = _buf_start + _buf_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SharedPathsMiscInfo::write(const void* ptr, size_t size) {
|
||||||
|
ensure_size(size);
|
||||||
|
memcpy(_cur_ptr, ptr, size);
|
||||||
|
_cur_ptr += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SharedPathsMiscInfo::read(void* ptr, size_t size) {
|
||||||
|
if (_cur_ptr + size <= _end_ptr) {
|
||||||
|
memcpy(ptr, _cur_ptr, size);
|
||||||
|
_cur_ptr += size;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SharedPathsMiscInfo::fail(const char* msg, const char* name) {
|
||||||
|
ClassLoader::trace_class_path(msg, name);
|
||||||
|
MetaspaceShared::set_archive_loading_failed();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SharedPathsMiscInfo::check() {
|
||||||
|
// The whole buffer must be 0 terminated so that we can use strlen and strcmp
|
||||||
|
// without fear.
|
||||||
|
_end_ptr -= sizeof(jint);
|
||||||
|
if (_cur_ptr >= _end_ptr) {
|
||||||
|
return fail("Truncated archive file header");
|
||||||
|
}
|
||||||
|
if (*_end_ptr != 0) {
|
||||||
|
return fail("Corrupted archive file header");
|
||||||
|
}
|
||||||
|
|
||||||
|
while (_cur_ptr < _end_ptr) {
|
||||||
|
jint type;
|
||||||
|
const char* path = _cur_ptr;
|
||||||
|
_cur_ptr += strlen(path) + 1;
|
||||||
|
if (!read_jint(&type)) {
|
||||||
|
return fail("Corrupted archive file header");
|
||||||
|
}
|
||||||
|
if (TraceClassPaths) {
|
||||||
|
tty->print("[type=%s ", type_name(type));
|
||||||
|
print_path(tty, type, path);
|
||||||
|
tty->print_cr("]");
|
||||||
|
}
|
||||||
|
if (!check(type, path)) {
|
||||||
|
if (!PrintSharedArchiveAndExit) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
trace_class_path("[ok");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SharedPathsMiscInfo::check(jint type, const char* path) {
|
||||||
|
switch (type) {
|
||||||
|
case BOOT:
|
||||||
|
if (strcmp(path, Arguments::get_sysclasspath()) != 0) {
|
||||||
|
return fail("[BOOT classpath mismatch, actual: -Dsun.boot.class.path=", Arguments::get_sysclasspath());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case NON_EXIST: // fall-through
|
||||||
|
case REQUIRED:
|
||||||
|
{
|
||||||
|
struct stat st;
|
||||||
|
if (os::stat(path, &st) != 0) {
|
||||||
|
// The file does not actually exist
|
||||||
|
if (type == REQUIRED) {
|
||||||
|
// but we require it to exist -> fail
|
||||||
|
return fail("Required file doesn't exist");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The file actually exists
|
||||||
|
if (type == NON_EXIST) {
|
||||||
|
// But we want it to not exist -> fail
|
||||||
|
return fail("File must not exist");
|
||||||
|
}
|
||||||
|
time_t timestamp;
|
||||||
|
long filesize;
|
||||||
|
|
||||||
|
if (!read_time(×tamp) || !read_long(&filesize)) {
|
||||||
|
return fail("Corrupted archive file header");
|
||||||
|
}
|
||||||
|
if (timestamp != st.st_mtime) {
|
||||||
|
return fail("Timestamp mismatch");
|
||||||
|
}
|
||||||
|
if (filesize != st.st_size) {
|
||||||
|
return fail("File size mismatch");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return fail("Corrupted archive file header");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
187
hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp
Normal file
187
hotspot/src/share/vm/classfile/sharedPathsMiscInfo.hpp
Normal file
|
@ -0,0 +1,187 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP
|
||||||
|
#define SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP
|
||||||
|
|
||||||
|
#include "runtime/os.hpp"
|
||||||
|
|
||||||
|
// During dumping time, when processing class paths, we build up the dump-time
|
||||||
|
// classpath. The JAR files that exist are stored in the list ClassLoader::_first_entry.
|
||||||
|
// However, we need to store other "misc" information for run-time checking, such as
|
||||||
|
//
|
||||||
|
// + The values of Arguments::get_sysclasspath() used during dumping.
|
||||||
|
//
|
||||||
|
// + The meta-index file(s) used during dumping (incl modification time and size)
|
||||||
|
//
|
||||||
|
// + The class path elements specified during dumping but did not exist --
|
||||||
|
// these elements must also be specified at run time, and they also must not
|
||||||
|
// exist at run time.
|
||||||
|
//
|
||||||
|
// These misc items are stored in a linear buffer in SharedPathsMiscInfo.
|
||||||
|
// The storage format is stream oriented to minimize its size.
|
||||||
|
//
|
||||||
|
// When writing the information to the archive file, SharedPathsMiscInfo is stored in
|
||||||
|
// the archive file header. At run-time, this information is used only during initialization
|
||||||
|
// (accessed using read() instead of mmap()), and is deallocated afterwards to save space.
|
||||||
|
//
|
||||||
|
// The SharedPathsMiscInfo class is used for both creating the the information (during
|
||||||
|
// dumping time) and validation (at run time). Different constructors are used in the
|
||||||
|
// two situations. See below.
|
||||||
|
|
||||||
|
class SharedPathsMiscInfo : public CHeapObj<mtClass> {
|
||||||
|
protected:
|
||||||
|
char* _buf_start;
|
||||||
|
char* _cur_ptr;
|
||||||
|
char* _end_ptr;
|
||||||
|
int _buf_size;
|
||||||
|
bool _allocated; // was _buf_start allocated by me?
|
||||||
|
void ensure_size(size_t needed_bytes);
|
||||||
|
void add_path(const char* path, int type);
|
||||||
|
|
||||||
|
void write(const void* ptr, size_t size);
|
||||||
|
bool read(void* ptr, size_t size);
|
||||||
|
|
||||||
|
static void trace_class_path(const char* msg, const char* name = NULL) {
|
||||||
|
ClassLoader::trace_class_path(msg, name);
|
||||||
|
}
|
||||||
|
protected:
|
||||||
|
static bool fail(const char* msg, const char* name = NULL);
|
||||||
|
virtual bool check(jint type, const char* path);
|
||||||
|
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
INITIAL_BUF_SIZE = 128
|
||||||
|
};
|
||||||
|
// This constructor is used when creating the misc information (during dump)
|
||||||
|
SharedPathsMiscInfo() {
|
||||||
|
_buf_size = INITIAL_BUF_SIZE;
|
||||||
|
_cur_ptr = _buf_start = NEW_C_HEAP_ARRAY(char, _buf_size, mtClass);
|
||||||
|
_allocated = true;
|
||||||
|
}
|
||||||
|
// This constructor is used when validating the misc info (during run time)
|
||||||
|
SharedPathsMiscInfo(char *buff, int size) {
|
||||||
|
_cur_ptr = _buf_start = buff;
|
||||||
|
_end_ptr = _buf_start + size;
|
||||||
|
_buf_size = size;
|
||||||
|
_allocated = false;
|
||||||
|
}
|
||||||
|
~SharedPathsMiscInfo() {
|
||||||
|
if (_allocated) {
|
||||||
|
FREE_C_HEAP_ARRAY(char, _buf_start, mtClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
int get_used_bytes() {
|
||||||
|
return _cur_ptr - _buf_start;
|
||||||
|
}
|
||||||
|
void* buffer() {
|
||||||
|
return _buf_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
// writing --
|
||||||
|
|
||||||
|
// The path must not exist at run-time
|
||||||
|
void add_nonexist_path(const char* path) {
|
||||||
|
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");
|
||||||
|
ClassLoader::exit_with_path_failure("failed to os::stat(%s)", path); // should not happen
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
int write_jint(jint num) {
|
||||||
|
write(&num, sizeof(num));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
void write_time(time_t t) {
|
||||||
|
write(&t, sizeof(t));
|
||||||
|
}
|
||||||
|
void write_long(long l) {
|
||||||
|
write(&l, sizeof(l));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool dump_to_file(int fd) {
|
||||||
|
int n = get_used_bytes();
|
||||||
|
return (os::write(fd, _buf_start, n) == (size_t)n);
|
||||||
|
}
|
||||||
|
|
||||||
|
// reading --
|
||||||
|
|
||||||
|
enum {
|
||||||
|
BOOT = 1,
|
||||||
|
NON_EXIST = 2,
|
||||||
|
REQUIRED = 3
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual const char* type_name(int type) {
|
||||||
|
switch (type) {
|
||||||
|
case BOOT: return "BOOT";
|
||||||
|
case NON_EXIST: return "NON_EXIST";
|
||||||
|
case REQUIRED: return "REQUIRED";
|
||||||
|
default: ShouldNotReachHere(); return "?";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual void print_path(outputStream* out, int type, const char* path) {
|
||||||
|
switch (type) {
|
||||||
|
case BOOT:
|
||||||
|
out->print("Expecting -Dsun.boot.class.path=%s", path);
|
||||||
|
break;
|
||||||
|
case NON_EXIST:
|
||||||
|
out->print("Expecting that %s does not exist", path);
|
||||||
|
break;
|
||||||
|
case REQUIRED:
|
||||||
|
out->print("Expecting that file %s must exist and not altered", path);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ShouldNotReachHere();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool check();
|
||||||
|
bool read_jint(jint *ptr) {
|
||||||
|
return read(ptr, sizeof(jint));
|
||||||
|
}
|
||||||
|
bool read_long(long *ptr) {
|
||||||
|
return read(ptr, sizeof(long));
|
||||||
|
}
|
||||||
|
bool read_time(time_t *ptr) {
|
||||||
|
return read(ptr, sizeof(time_t));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARE_VM_CLASSFILE_SHAREDPATHSMISCINFO_HPP
|
|
@ -31,10 +31,15 @@
|
||||||
#include "classfile/resolutionErrors.hpp"
|
#include "classfile/resolutionErrors.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
#include "classfile/sharedClassUtil.hpp"
|
||||||
|
#include "classfile/systemDictionaryShared.hpp"
|
||||||
|
#endif
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "compiler/compileBroker.hpp"
|
#include "compiler/compileBroker.hpp"
|
||||||
#include "interpreter/bytecodeStream.hpp"
|
#include "interpreter/bytecodeStream.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
|
#include "memory/filemap.hpp"
|
||||||
#include "memory/gcLocker.hpp"
|
#include "memory/gcLocker.hpp"
|
||||||
#include "memory/oopFactory.hpp"
|
#include "memory/oopFactory.hpp"
|
||||||
#include "oops/instanceKlass.hpp"
|
#include "oops/instanceKlass.hpp"
|
||||||
|
@ -110,6 +115,8 @@ void SystemDictionary::compute_java_system_loader(TRAPS) {
|
||||||
CHECK);
|
CHECK);
|
||||||
|
|
||||||
_java_system_loader = (oop)result.get_jobject();
|
_java_system_loader = (oop)result.get_jobject();
|
||||||
|
|
||||||
|
CDS_ONLY(SystemDictionaryShared::initialize(CHECK);)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -974,6 +981,7 @@ Klass* SystemDictionary::parse_stream(Symbol* class_name,
|
||||||
// Create a new CLD for anonymous class, that uses the same class loader
|
// Create a new CLD for anonymous class, that uses the same class loader
|
||||||
// as the host_klass
|
// as the host_klass
|
||||||
guarantee(host_klass->class_loader() == class_loader(), "should be the same");
|
guarantee(host_klass->class_loader() == class_loader(), "should be the same");
|
||||||
|
guarantee(!DumpSharedSpaces, "must not create anonymous classes when dumping");
|
||||||
loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader(), CHECK_NULL);
|
loader_data = ClassLoaderData::anonymous_class_loader_data(class_loader(), CHECK_NULL);
|
||||||
loader_data->record_dependency(host_klass(), CHECK_NULL);
|
loader_data->record_dependency(host_klass(), CHECK_NULL);
|
||||||
} else {
|
} else {
|
||||||
|
@ -1134,7 +1142,7 @@ Klass* SystemDictionary::resolve_from_stream(Symbol* class_name,
|
||||||
return k();
|
return k();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
void SystemDictionary::set_shared_dictionary(HashtableBucket<mtClass>* t, int length,
|
void SystemDictionary::set_shared_dictionary(HashtableBucket<mtClass>* t, int length,
|
||||||
int number_of_entries) {
|
int number_of_entries) {
|
||||||
assert(length == _nof_buckets * sizeof(HashtableBucket<mtClass>),
|
assert(length == _nof_buckets * sizeof(HashtableBucket<mtClass>),
|
||||||
|
@ -1167,12 +1175,18 @@ Klass* SystemDictionary::find_shared_class(Symbol* class_name) {
|
||||||
instanceKlassHandle SystemDictionary::load_shared_class(
|
instanceKlassHandle SystemDictionary::load_shared_class(
|
||||||
Symbol* class_name, Handle class_loader, TRAPS) {
|
Symbol* class_name, Handle class_loader, TRAPS) {
|
||||||
instanceKlassHandle ik (THREAD, find_shared_class(class_name));
|
instanceKlassHandle ik (THREAD, find_shared_class(class_name));
|
||||||
return load_shared_class(ik, class_loader, THREAD);
|
// Make sure we only return the boot class for the NULL classloader.
|
||||||
|
if (ik.not_null() &&
|
||||||
|
SharedClassUtil::is_shared_boot_class(ik()) && class_loader.is_null()) {
|
||||||
|
Handle protection_domain;
|
||||||
|
return load_shared_class(ik, class_loader, protection_domain, THREAD);
|
||||||
|
}
|
||||||
|
return instanceKlassHandle();
|
||||||
}
|
}
|
||||||
|
|
||||||
instanceKlassHandle SystemDictionary::load_shared_class(
|
instanceKlassHandle SystemDictionary::load_shared_class(instanceKlassHandle ik,
|
||||||
instanceKlassHandle ik, Handle class_loader, TRAPS) {
|
Handle class_loader,
|
||||||
assert(class_loader.is_null(), "non-null classloader for shared class?");
|
Handle protection_domain, TRAPS) {
|
||||||
if (ik.not_null()) {
|
if (ik.not_null()) {
|
||||||
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
||||||
Symbol* class_name = ik->name();
|
Symbol* class_name = ik->name();
|
||||||
|
@ -1184,7 +1198,7 @@ instanceKlassHandle SystemDictionary::load_shared_class(
|
||||||
if (ik->super() != NULL) {
|
if (ik->super() != NULL) {
|
||||||
Symbol* cn = ik->super()->name();
|
Symbol* cn = ik->super()->name();
|
||||||
resolve_super_or_fail(class_name, cn,
|
resolve_super_or_fail(class_name, cn,
|
||||||
class_loader, Handle(), true, CHECK_(nh));
|
class_loader, protection_domain, true, CHECK_(nh));
|
||||||
}
|
}
|
||||||
|
|
||||||
Array<Klass*>* interfaces = ik->local_interfaces();
|
Array<Klass*>* interfaces = ik->local_interfaces();
|
||||||
|
@ -1197,7 +1211,7 @@ instanceKlassHandle SystemDictionary::load_shared_class(
|
||||||
// reinitialized yet (they will be once the interface classes
|
// reinitialized yet (they will be once the interface classes
|
||||||
// are loaded)
|
// are loaded)
|
||||||
Symbol* name = k->name();
|
Symbol* name = k->name();
|
||||||
resolve_super_or_fail(class_name, name, class_loader, Handle(), false, CHECK_(nh));
|
resolve_super_or_fail(class_name, name, class_loader, protection_domain, false, CHECK_(nh));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adjust methods to recover missing data. They need addresses for
|
// Adjust methods to recover missing data. They need addresses for
|
||||||
|
@ -1206,30 +1220,47 @@ instanceKlassHandle SystemDictionary::load_shared_class(
|
||||||
|
|
||||||
// Updating methods must be done under a lock so multiple
|
// Updating methods must be done under a lock so multiple
|
||||||
// threads don't update these in parallel
|
// threads don't update these in parallel
|
||||||
// Shared classes are all currently loaded by the bootstrap
|
//
|
||||||
// classloader, so this will never cause a deadlock on
|
// Shared classes are all currently loaded by either the bootstrap or
|
||||||
// a custom class loader lock.
|
// internal parallel class loaders, so this will never cause a deadlock
|
||||||
|
// on a custom class loader lock.
|
||||||
|
|
||||||
|
ClassLoaderData* loader_data = ClassLoaderData::class_loader_data(class_loader());
|
||||||
{
|
{
|
||||||
Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
|
Handle lockObject = compute_loader_lock_object(class_loader, THREAD);
|
||||||
check_loader_lock_contention(lockObject, THREAD);
|
check_loader_lock_contention(lockObject, THREAD);
|
||||||
ObjectLocker ol(lockObject, THREAD, true);
|
ObjectLocker ol(lockObject, THREAD, true);
|
||||||
ik->restore_unshareable_info(CHECK_(nh));
|
ik->restore_unshareable_info(loader_data, protection_domain, CHECK_(nh));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TraceClassLoading) {
|
if (TraceClassLoading) {
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
tty->print("[Loaded %s", ik->external_name());
|
tty->print("[Loaded %s", ik->external_name());
|
||||||
tty->print(" from shared objects file");
|
tty->print(" from shared objects file");
|
||||||
|
if (class_loader.not_null()) {
|
||||||
|
tty->print(" by %s", loader_data->loader_name());
|
||||||
|
}
|
||||||
tty->print_cr("]");
|
tty->print_cr("]");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
if (DumpLoadedClassList != NULL && classlist_file->is_open()) {
|
||||||
|
// Only dump the classes that can be stored into CDS archive
|
||||||
|
if (SystemDictionaryShared::is_sharing_possible(loader_data)) {
|
||||||
|
ResourceMark rm(THREAD);
|
||||||
|
classlist_file->print_cr("%s", ik->name()->as_C_string());
|
||||||
|
classlist_file->flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// notify a class loaded from shared object
|
// notify a class loaded from shared object
|
||||||
ClassLoadingService::notify_class_loaded(InstanceKlass::cast(ik()),
|
ClassLoadingService::notify_class_loaded(InstanceKlass::cast(ik()),
|
||||||
true /* shared class */);
|
true /* shared class */);
|
||||||
}
|
}
|
||||||
return ik;
|
return ik;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
|
instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Handle class_loader, TRAPS) {
|
||||||
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
instanceKlassHandle nh = instanceKlassHandle(); // null Handle
|
||||||
|
@ -1239,8 +1270,10 @@ instanceKlassHandle SystemDictionary::load_instance_class(Symbol* class_name, Ha
|
||||||
// shared spaces.
|
// shared spaces.
|
||||||
instanceKlassHandle k;
|
instanceKlassHandle k;
|
||||||
{
|
{
|
||||||
|
#if INCLUDE_CDS
|
||||||
PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time());
|
PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time());
|
||||||
k = load_shared_class(class_name, class_loader, THREAD);
|
k = load_shared_class(class_name, class_loader, THREAD);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (k.is_null()) {
|
if (k.is_null()) {
|
||||||
|
@ -1599,7 +1632,6 @@ void SystemDictionary::add_to_hierarchy(instanceKlassHandle k, TRAPS) {
|
||||||
Universe::flush_dependents_on(k);
|
Universe::flush_dependents_on(k);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// GC support
|
// GC support
|
||||||
|
|
||||||
|
@ -1682,6 +1714,7 @@ bool SystemDictionary::do_unloading(BoolObjectClosure* is_alive) {
|
||||||
void SystemDictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
|
void SystemDictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
|
||||||
strong->do_oop(&_java_system_loader);
|
strong->do_oop(&_java_system_loader);
|
||||||
strong->do_oop(&_system_loader_lock_obj);
|
strong->do_oop(&_system_loader_lock_obj);
|
||||||
|
CDS_ONLY(SystemDictionaryShared::roots_oops_do(strong);)
|
||||||
|
|
||||||
// Adjust dictionary
|
// Adjust dictionary
|
||||||
dictionary()->roots_oops_do(strong, weak);
|
dictionary()->roots_oops_do(strong, weak);
|
||||||
|
@ -1693,6 +1726,7 @@ void SystemDictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
|
||||||
void SystemDictionary::oops_do(OopClosure* f) {
|
void SystemDictionary::oops_do(OopClosure* f) {
|
||||||
f->do_oop(&_java_system_loader);
|
f->do_oop(&_java_system_loader);
|
||||||
f->do_oop(&_system_loader_lock_obj);
|
f->do_oop(&_system_loader_lock_obj);
|
||||||
|
CDS_ONLY(SystemDictionaryShared::oops_do(f);)
|
||||||
|
|
||||||
// Adjust dictionary
|
// Adjust dictionary
|
||||||
dictionary()->oops_do(f);
|
dictionary()->oops_do(f);
|
||||||
|
@ -1754,6 +1788,10 @@ void SystemDictionary::methods_do(void f(Method*)) {
|
||||||
invoke_method_table()->methods_do(f);
|
invoke_method_table()->methods_do(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SystemDictionary::remove_classes_in_error_state() {
|
||||||
|
dictionary()->remove_classes_in_error_state();
|
||||||
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
// Lazily load klasses
|
// Lazily load klasses
|
||||||
|
|
||||||
|
@ -2563,10 +2601,12 @@ int SystemDictionary::number_of_classes() {
|
||||||
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
#ifndef PRODUCT
|
void SystemDictionary::print_shared(bool details) {
|
||||||
|
shared_dictionary()->print(details);
|
||||||
|
}
|
||||||
|
|
||||||
void SystemDictionary::print() {
|
void SystemDictionary::print(bool details) {
|
||||||
dictionary()->print();
|
dictionary()->print(details);
|
||||||
|
|
||||||
// Placeholders
|
// Placeholders
|
||||||
GCMutexLocker mu(SystemDictionary_lock);
|
GCMutexLocker mu(SystemDictionary_lock);
|
||||||
|
@ -2576,7 +2616,6 @@ void SystemDictionary::print() {
|
||||||
constraints()->print();
|
constraints()->print();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void SystemDictionary::verify() {
|
void SystemDictionary::verify() {
|
||||||
guarantee(dictionary() != NULL, "Verify of system dictionary failed");
|
guarantee(dictionary() != NULL, "Verify of system dictionary failed");
|
||||||
|
|
|
@ -111,6 +111,7 @@ class Ticks;
|
||||||
do_klass(SecurityManager_klass, java_lang_SecurityManager, Pre ) \
|
do_klass(SecurityManager_klass, java_lang_SecurityManager, Pre ) \
|
||||||
do_klass(ProtectionDomain_klass, java_security_ProtectionDomain, Pre ) \
|
do_klass(ProtectionDomain_klass, java_security_ProtectionDomain, Pre ) \
|
||||||
do_klass(AccessControlContext_klass, java_security_AccessControlContext, Pre ) \
|
do_klass(AccessControlContext_klass, java_security_AccessControlContext, Pre ) \
|
||||||
|
do_klass(SecureClassLoader_klass, java_security_SecureClassLoader, Pre ) \
|
||||||
do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre ) \
|
do_klass(ClassNotFoundException_klass, java_lang_ClassNotFoundException, Pre ) \
|
||||||
do_klass(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre ) \
|
do_klass(NoClassDefFoundError_klass, java_lang_NoClassDefFoundError, Pre ) \
|
||||||
do_klass(LinkageError_klass, java_lang_LinkageError, Pre ) \
|
do_klass(LinkageError_klass, java_lang_LinkageError, Pre ) \
|
||||||
|
@ -166,6 +167,15 @@ class Ticks;
|
||||||
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
|
do_klass(StringBuilder_klass, java_lang_StringBuilder, Pre ) \
|
||||||
do_klass(misc_Unsafe_klass, sun_misc_Unsafe, Pre ) \
|
do_klass(misc_Unsafe_klass, sun_misc_Unsafe, Pre ) \
|
||||||
\
|
\
|
||||||
|
/* support for CDS */ \
|
||||||
|
do_klass(ByteArrayInputStream_klass, java_io_ByteArrayInputStream, Pre ) \
|
||||||
|
do_klass(File_klass, java_io_File, Pre ) \
|
||||||
|
do_klass(URLClassLoader_klass, java_net_URLClassLoader, Pre ) \
|
||||||
|
do_klass(URL_klass, java_net_URL, Pre ) \
|
||||||
|
do_klass(Jar_Manifest_klass, java_util_jar_Manifest, Pre ) \
|
||||||
|
do_klass(sun_misc_Launcher_klass, sun_misc_Launcher, Pre ) \
|
||||||
|
do_klass(CodeSource_klass, java_security_CodeSource, Pre ) \
|
||||||
|
\
|
||||||
/* It's NULL in non-1.4 JDKs. */ \
|
/* It's NULL in non-1.4 JDKs. */ \
|
||||||
do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \
|
do_klass(StackTraceElement_klass, java_lang_StackTraceElement, Opt ) \
|
||||||
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
/* It's okay if this turns out to be NULL in non-1.4 JDKs. */ \
|
||||||
|
@ -221,7 +231,7 @@ class SystemDictionary : AllStatic {
|
||||||
static Klass* resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS);
|
static Klass* resolve_or_fail(Symbol* class_name, Handle class_loader, Handle protection_domain, bool throw_error, TRAPS);
|
||||||
// Convenient call for null loader and protection domain.
|
// Convenient call for null loader and protection domain.
|
||||||
static Klass* resolve_or_fail(Symbol* class_name, bool throw_error, TRAPS);
|
static Klass* resolve_or_fail(Symbol* class_name, bool throw_error, TRAPS);
|
||||||
private:
|
protected:
|
||||||
// handle error translation for resolve_or_null results
|
// handle error translation for resolve_or_null results
|
||||||
static Klass* handle_resolution_exception(Symbol* class_name, bool throw_error, KlassHandle klass_h, TRAPS);
|
static Klass* handle_resolution_exception(Symbol* class_name, bool throw_error, KlassHandle klass_h, TRAPS);
|
||||||
|
|
||||||
|
@ -326,6 +336,9 @@ public:
|
||||||
// loaders. Returns "true" iff something was unloaded.
|
// loaders. Returns "true" iff something was unloaded.
|
||||||
static bool do_unloading(BoolObjectClosure* is_alive);
|
static bool do_unloading(BoolObjectClosure* is_alive);
|
||||||
|
|
||||||
|
// Used by DumpSharedSpaces only to remove classes that failed verification
|
||||||
|
static void remove_classes_in_error_state();
|
||||||
|
|
||||||
static int calculate_systemdictionary_size(int loadedclasses);
|
static int calculate_systemdictionary_size(int loadedclasses);
|
||||||
|
|
||||||
// Applies "f->do_oop" to all root oops in the system dictionary.
|
// Applies "f->do_oop" to all root oops in the system dictionary.
|
||||||
|
@ -335,7 +348,7 @@ public:
|
||||||
// System loader lock
|
// System loader lock
|
||||||
static oop system_loader_lock() { return _system_loader_lock_obj; }
|
static oop system_loader_lock() { return _system_loader_lock_obj; }
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
// Extended Redefine classes support (tbi)
|
// Extended Redefine classes support (tbi)
|
||||||
static void preloaded_classes_do(KlassClosure* f);
|
static void preloaded_classes_do(KlassClosure* f);
|
||||||
static void lazily_loaded_classes_do(KlassClosure* f);
|
static void lazily_loaded_classes_do(KlassClosure* f);
|
||||||
|
@ -348,7 +361,8 @@ public:
|
||||||
static void set_shared_dictionary(HashtableBucket<mtClass>* t, int length,
|
static void set_shared_dictionary(HashtableBucket<mtClass>* t, int length,
|
||||||
int number_of_entries);
|
int number_of_entries);
|
||||||
// Printing
|
// Printing
|
||||||
static void print() PRODUCT_RETURN;
|
static void print(bool details = true);
|
||||||
|
static void print_shared(bool details = true);
|
||||||
static void print_class_statistics() PRODUCT_RETURN;
|
static void print_class_statistics() PRODUCT_RETURN;
|
||||||
static void print_method_statistics() PRODUCT_RETURN;
|
static void print_method_statistics() PRODUCT_RETURN;
|
||||||
|
|
||||||
|
@ -424,7 +438,7 @@ public:
|
||||||
|
|
||||||
static void load_abstract_ownable_synchronizer_klass(TRAPS);
|
static void load_abstract_ownable_synchronizer_klass(TRAPS);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
// Tells whether ClassLoader.loadClassInternal is present
|
// Tells whether ClassLoader.loadClassInternal is present
|
||||||
static bool has_loadClassInternal() { return _has_loadClassInternal; }
|
static bool has_loadClassInternal() { return _has_loadClassInternal; }
|
||||||
|
|
||||||
|
@ -452,7 +466,7 @@ public:
|
||||||
|
|
||||||
// Register a new class loader
|
// Register a new class loader
|
||||||
static ClassLoaderData* register_loader(Handle class_loader, TRAPS);
|
static ClassLoaderData* register_loader(Handle class_loader, TRAPS);
|
||||||
private:
|
protected:
|
||||||
// Mirrors for primitive classes (created eagerly)
|
// Mirrors for primitive classes (created eagerly)
|
||||||
static oop check_mirror(oop m) {
|
static oop check_mirror(oop m) {
|
||||||
assert(m != NULL, "mirror not initialized");
|
assert(m != NULL, "mirror not initialized");
|
||||||
|
@ -523,7 +537,7 @@ public:
|
||||||
static Symbol* find_resolution_error(constantPoolHandle pool, int which,
|
static Symbol* find_resolution_error(constantPoolHandle pool, int which,
|
||||||
Symbol** message);
|
Symbol** message);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
|
||||||
enum Constants {
|
enum Constants {
|
||||||
_loader_constraint_size = 107, // number of entries in constraint table
|
_loader_constraint_size = 107, // number of entries in constraint table
|
||||||
|
@ -574,7 +588,7 @@ public:
|
||||||
friend class CounterDecay;
|
friend class CounterDecay;
|
||||||
static Klass* try_get_next_class();
|
static Klass* try_get_next_class();
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
static void validate_protection_domain(instanceKlassHandle klass,
|
static void validate_protection_domain(instanceKlassHandle klass,
|
||||||
Handle class_loader,
|
Handle class_loader,
|
||||||
Handle protection_domain, TRAPS);
|
Handle protection_domain, TRAPS);
|
||||||
|
@ -601,10 +615,10 @@ private:
|
||||||
static instanceKlassHandle find_or_define_instance_class(Symbol* class_name,
|
static instanceKlassHandle find_or_define_instance_class(Symbol* class_name,
|
||||||
Handle class_loader,
|
Handle class_loader,
|
||||||
instanceKlassHandle k, TRAPS);
|
instanceKlassHandle k, TRAPS);
|
||||||
static instanceKlassHandle load_shared_class(Symbol* class_name,
|
|
||||||
Handle class_loader, TRAPS);
|
|
||||||
static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
|
static instanceKlassHandle load_shared_class(instanceKlassHandle ik,
|
||||||
Handle class_loader, TRAPS);
|
Handle class_loader,
|
||||||
|
Handle protection_domain,
|
||||||
|
TRAPS);
|
||||||
static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS);
|
static instanceKlassHandle load_instance_class(Symbol* class_name, Handle class_loader, TRAPS);
|
||||||
static Handle compute_loader_lock_object(Handle class_loader, TRAPS);
|
static Handle compute_loader_lock_object(Handle class_loader, TRAPS);
|
||||||
static void check_loader_lock_contention(Handle loader_lock, TRAPS);
|
static void check_loader_lock_contention(Handle loader_lock, TRAPS);
|
||||||
|
@ -612,9 +626,12 @@ private:
|
||||||
static bool is_parallelDefine(Handle class_loader);
|
static bool is_parallelDefine(Handle class_loader);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
static instanceKlassHandle load_shared_class(Symbol* class_name,
|
||||||
|
Handle class_loader,
|
||||||
|
TRAPS);
|
||||||
static bool is_ext_class_loader(Handle class_loader);
|
static bool is_ext_class_loader(Handle class_loader);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
static Klass* find_shared_class(Symbol* class_name);
|
static Klass* find_shared_class(Symbol* class_name);
|
||||||
|
|
||||||
// Setup link to hierarchy
|
// Setup link to hierarchy
|
||||||
|
|
47
hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
Normal file
47
hotspot/src/share/vm/classfile/systemDictionaryShared.hpp
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
|
||||||
|
#define SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
|
||||||
|
|
||||||
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
|
||||||
|
class SystemDictionaryShared: public SystemDictionary {
|
||||||
|
public:
|
||||||
|
static void initialize(TRAPS) {}
|
||||||
|
static instanceKlassHandle find_or_load_shared_class(Symbol* class_name,
|
||||||
|
Handle class_loader,
|
||||||
|
TRAPS) {
|
||||||
|
return instanceKlassHandle();
|
||||||
|
}
|
||||||
|
static void roots_oops_do(OopClosure* blk) {}
|
||||||
|
static void oops_do(OopClosure* f) {}
|
||||||
|
static bool is_sharing_possible(ClassLoaderData* loader_data) {
|
||||||
|
oop class_loader = loader_data->class_loader();
|
||||||
|
return (class_loader == NULL);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARE_VM_CLASSFILE_SYSTEMDICTIONARYSHARED_HPP
|
|
@ -91,11 +91,17 @@
|
||||||
template(java_lang_CharSequence, "java/lang/CharSequence") \
|
template(java_lang_CharSequence, "java/lang/CharSequence") \
|
||||||
template(java_lang_SecurityManager, "java/lang/SecurityManager") \
|
template(java_lang_SecurityManager, "java/lang/SecurityManager") \
|
||||||
template(java_security_AccessControlContext, "java/security/AccessControlContext") \
|
template(java_security_AccessControlContext, "java/security/AccessControlContext") \
|
||||||
|
template(java_security_CodeSource, "java/security/CodeSource") \
|
||||||
template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \
|
template(java_security_ProtectionDomain, "java/security/ProtectionDomain") \
|
||||||
|
template(java_security_SecureClassLoader, "java/security/SecureClassLoader") \
|
||||||
|
template(java_net_URLClassLoader, "java/net/URLClassLoader") \
|
||||||
|
template(java_net_URL, "java/net/URL") \
|
||||||
|
template(java_util_jar_Manifest, "java/util/jar/Manifest") \
|
||||||
template(impliesCreateAccessControlContext_name, "impliesCreateAccessControlContext") \
|
template(impliesCreateAccessControlContext_name, "impliesCreateAccessControlContext") \
|
||||||
template(java_io_OutputStream, "java/io/OutputStream") \
|
template(java_io_OutputStream, "java/io/OutputStream") \
|
||||||
template(java_io_Reader, "java/io/Reader") \
|
template(java_io_Reader, "java/io/Reader") \
|
||||||
template(java_io_BufferedReader, "java/io/BufferedReader") \
|
template(java_io_BufferedReader, "java/io/BufferedReader") \
|
||||||
|
template(java_io_File, "java/io/File") \
|
||||||
template(java_io_FileInputStream, "java/io/FileInputStream") \
|
template(java_io_FileInputStream, "java/io/FileInputStream") \
|
||||||
template(java_io_ByteArrayInputStream, "java/io/ByteArrayInputStream") \
|
template(java_io_ByteArrayInputStream, "java/io/ByteArrayInputStream") \
|
||||||
template(java_io_Serializable, "java/io/Serializable") \
|
template(java_io_Serializable, "java/io/Serializable") \
|
||||||
|
@ -106,6 +112,7 @@
|
||||||
template(java_util_Hashtable, "java/util/Hashtable") \
|
template(java_util_Hashtable, "java/util/Hashtable") \
|
||||||
template(java_lang_Compiler, "java/lang/Compiler") \
|
template(java_lang_Compiler, "java/lang/Compiler") \
|
||||||
template(sun_misc_Signal, "sun/misc/Signal") \
|
template(sun_misc_Signal, "sun/misc/Signal") \
|
||||||
|
template(sun_misc_Launcher, "sun/misc/Launcher") \
|
||||||
template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \
|
template(java_lang_AssertionStatusDirectives, "java/lang/AssertionStatusDirectives") \
|
||||||
template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \
|
template(getBootClassPathEntryForClass_name, "getBootClassPathEntryForClass") \
|
||||||
template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \
|
template(sun_misc_PostVMInitHook, "sun/misc/PostVMInitHook") \
|
||||||
|
@ -396,6 +403,14 @@
|
||||||
template(signers_name, "signers_name") \
|
template(signers_name, "signers_name") \
|
||||||
template(loader_data_name, "loader_data") \
|
template(loader_data_name, "loader_data") \
|
||||||
template(dependencies_name, "dependencies") \
|
template(dependencies_name, "dependencies") \
|
||||||
|
template(input_stream_void_signature, "(Ljava/io/InputStream;)V") \
|
||||||
|
template(getFileURL_name, "getFileURL") \
|
||||||
|
template(getFileURL_signature, "(Ljava/io/File;)Ljava/net/URL;") \
|
||||||
|
template(definePackageInternal_name, "definePackageInternal") \
|
||||||
|
template(definePackageInternal_signature, "(Ljava/lang/String;Ljava/util/jar/Manifest;Ljava/net/URL;)V") \
|
||||||
|
template(getProtectionDomain_name, "getProtectionDomain") \
|
||||||
|
template(getProtectionDomain_signature, "(Ljava/security/CodeSource;)Ljava/security/ProtectionDomain;") \
|
||||||
|
template(url_code_signer_array_void_signature, "(Ljava/net/URL;[Ljava/security/CodeSigner;)V") \
|
||||||
\
|
\
|
||||||
/* non-intrinsic name/signature pairs: */ \
|
/* non-intrinsic name/signature pairs: */ \
|
||||||
template(register_method_name, "register") \
|
template(register_method_name, "register") \
|
||||||
|
|
|
@ -2582,15 +2582,12 @@ bool G1CollectedHeap::is_in(const void* p) const {
|
||||||
|
|
||||||
// Iteration functions.
|
// Iteration functions.
|
||||||
|
|
||||||
// Iterates an OopClosure over all ref-containing fields of objects
|
// Applies an ExtendedOopClosure onto all references of objects within a HeapRegion.
|
||||||
// within a HeapRegion.
|
|
||||||
|
|
||||||
class IterateOopClosureRegionClosure: public HeapRegionClosure {
|
class IterateOopClosureRegionClosure: public HeapRegionClosure {
|
||||||
MemRegion _mr;
|
|
||||||
ExtendedOopClosure* _cl;
|
ExtendedOopClosure* _cl;
|
||||||
public:
|
public:
|
||||||
IterateOopClosureRegionClosure(MemRegion mr, ExtendedOopClosure* cl)
|
IterateOopClosureRegionClosure(ExtendedOopClosure* cl) : _cl(cl) {}
|
||||||
: _mr(mr), _cl(cl) {}
|
|
||||||
bool doHeapRegion(HeapRegion* r) {
|
bool doHeapRegion(HeapRegion* r) {
|
||||||
if (!r->continuesHumongous()) {
|
if (!r->continuesHumongous()) {
|
||||||
r->oop_iterate(_cl);
|
r->oop_iterate(_cl);
|
||||||
|
@ -2600,12 +2597,7 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
void G1CollectedHeap::oop_iterate(ExtendedOopClosure* cl) {
|
void G1CollectedHeap::oop_iterate(ExtendedOopClosure* cl) {
|
||||||
IterateOopClosureRegionClosure blk(_g1_committed, cl);
|
IterateOopClosureRegionClosure blk(cl);
|
||||||
heap_region_iterate(&blk);
|
|
||||||
}
|
|
||||||
|
|
||||||
void G1CollectedHeap::oop_iterate(MemRegion mr, ExtendedOopClosure* cl) {
|
|
||||||
IterateOopClosureRegionClosure blk(mr, cl);
|
|
||||||
heap_region_iterate(&blk);
|
heap_region_iterate(&blk);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4792,11 +4784,6 @@ protected:
|
||||||
Mutex _stats_lock;
|
Mutex _stats_lock;
|
||||||
Mutex* stats_lock() { return &_stats_lock; }
|
Mutex* stats_lock() { return &_stats_lock; }
|
||||||
|
|
||||||
size_t getNCards() {
|
|
||||||
return (_g1h->capacity() + G1BlockOffsetSharedArray::N_bytes - 1)
|
|
||||||
/ G1BlockOffsetSharedArray::N_bytes;
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues)
|
G1ParTask(G1CollectedHeap* g1h, RefToScanQueueSet *task_queues)
|
||||||
: AbstractGangTask("G1 collection"),
|
: AbstractGangTask("G1 collection"),
|
||||||
|
|
|
@ -1395,9 +1395,6 @@ public:
|
||||||
// "cl.do_oop" on each.
|
// "cl.do_oop" on each.
|
||||||
virtual void oop_iterate(ExtendedOopClosure* cl);
|
virtual void oop_iterate(ExtendedOopClosure* cl);
|
||||||
|
|
||||||
// Same as above, restricted to a memory region.
|
|
||||||
void oop_iterate(MemRegion mr, ExtendedOopClosure* cl);
|
|
||||||
|
|
||||||
// Iterate over all objects, calling "cl.do_object" on each.
|
// Iterate over all objects, calling "cl.do_object" on each.
|
||||||
virtual void object_iterate(ObjectClosure* cl);
|
virtual void object_iterate(ObjectClosure* cl);
|
||||||
|
|
||||||
|
|
|
@ -237,9 +237,11 @@ void G1GCPhaseTimes::note_gc_end() {
|
||||||
_last_gc_worker_times_ms.verify();
|
_last_gc_worker_times_ms.verify();
|
||||||
_last_gc_worker_other_times_ms.verify();
|
_last_gc_worker_other_times_ms.verify();
|
||||||
|
|
||||||
|
if (G1DeferredRSUpdate) {
|
||||||
_last_redirty_logged_cards_time_ms.verify();
|
_last_redirty_logged_cards_time_ms.verify();
|
||||||
_last_redirty_logged_cards_processed_cards.verify();
|
_last_redirty_logged_cards_processed_cards.verify();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void G1GCPhaseTimes::note_string_dedup_fixup_start() {
|
void G1GCPhaseTimes::note_string_dedup_fixup_start() {
|
||||||
_cur_string_dedup_queue_fixup_worker_times_ms.reset();
|
_cur_string_dedup_queue_fixup_worker_times_ms.reset();
|
||||||
|
|
|
@ -3402,7 +3402,7 @@ BytecodeInterpreter::print() {
|
||||||
tty->print_cr("osr._osr_buf: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_buf);
|
tty->print_cr("osr._osr_buf: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_buf);
|
||||||
tty->print_cr("osr._osr_entry: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_entry);
|
tty->print_cr("osr._osr_entry: " INTPTR_FORMAT, (uintptr_t) this->_result._osr._osr_entry);
|
||||||
tty->print_cr("prev_link: " INTPTR_FORMAT, (uintptr_t) this->_prev_link);
|
tty->print_cr("prev_link: " INTPTR_FORMAT, (uintptr_t) this->_prev_link);
|
||||||
tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) this->_oop_temp);
|
tty->print_cr("native_mirror: " INTPTR_FORMAT, (uintptr_t) p2i(this->_oop_temp));
|
||||||
tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base);
|
tty->print_cr("stack_base: " INTPTR_FORMAT, (uintptr_t) this->_stack_base);
|
||||||
tty->print_cr("stack_limit: " INTPTR_FORMAT, (uintptr_t) this->_stack_limit);
|
tty->print_cr("stack_limit: " INTPTR_FORMAT, (uintptr_t) this->_stack_limit);
|
||||||
tty->print_cr("monitor_base: " INTPTR_FORMAT, (uintptr_t) this->_monitor_base);
|
tty->print_cr("monitor_base: " INTPTR_FORMAT, (uintptr_t) this->_monitor_base);
|
||||||
|
|
|
@ -265,7 +265,8 @@ class MetaspaceObj {
|
||||||
f(ConstantPool) \
|
f(ConstantPool) \
|
||||||
f(ConstantPoolCache) \
|
f(ConstantPoolCache) \
|
||||||
f(Annotation) \
|
f(Annotation) \
|
||||||
f(MethodCounters)
|
f(MethodCounters) \
|
||||||
|
f(Deallocated)
|
||||||
|
|
||||||
#define METASPACE_OBJ_TYPE_DECLARE(name) name ## Type,
|
#define METASPACE_OBJ_TYPE_DECLARE(name) name ## Type,
|
||||||
#define METASPACE_OBJ_TYPE_NAME_CASE(name) case name ## Type: return #name;
|
#define METASPACE_OBJ_TYPE_NAME_CASE(name) case name ## Type: return #name;
|
||||||
|
|
|
@ -176,13 +176,9 @@ size_t CollectorPolicy::compute_heap_alignment() {
|
||||||
|
|
||||||
size_t alignment = GenRemSet::max_alignment_constraint();
|
size_t alignment = GenRemSet::max_alignment_constraint();
|
||||||
|
|
||||||
// Parallel GC does its own alignment of the generations to avoid requiring a
|
if (UseLargePages) {
|
||||||
// large page (256M on some platforms) for the permanent generation. The
|
|
||||||
// other collectors should also be updated to do their own alignment and then
|
|
||||||
// this use of lcm() should be removed.
|
|
||||||
if (UseLargePages && !UseParallelGC) {
|
|
||||||
// In presence of large pages we have to make sure that our
|
// In presence of large pages we have to make sure that our
|
||||||
// alignment is large page aware
|
// alignment is large page aware.
|
||||||
alignment = lcm(os::large_page_size(), alignment);
|
alignment = lcm(os::large_page_size(), alignment);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -24,9 +24,14 @@
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
|
#include "classfile/sharedClassUtil.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
|
#include "classfile/systemDictionaryShared.hpp"
|
||||||
#include "classfile/altHashing.hpp"
|
#include "classfile/altHashing.hpp"
|
||||||
#include "memory/filemap.hpp"
|
#include "memory/filemap.hpp"
|
||||||
|
#include "memory/metadataFactory.hpp"
|
||||||
|
#include "memory/oopFactory.hpp"
|
||||||
|
#include "oops/objArrayOop.hpp"
|
||||||
#include "runtime/arguments.hpp"
|
#include "runtime/arguments.hpp"
|
||||||
#include "runtime/java.hpp"
|
#include "runtime/java.hpp"
|
||||||
#include "runtime/os.hpp"
|
#include "runtime/os.hpp"
|
||||||
|
@ -42,7 +47,6 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
|
||||||
|
|
||||||
extern address JVM_FunctionAtStart();
|
extern address JVM_FunctionAtStart();
|
||||||
extern address JVM_FunctionAtEnd();
|
extern address JVM_FunctionAtEnd();
|
||||||
|
|
||||||
|
@ -78,6 +82,15 @@ void FileMapInfo::fail_stop(const char *msg, ...) {
|
||||||
void FileMapInfo::fail_continue(const char *msg, ...) {
|
void FileMapInfo::fail_continue(const char *msg, ...) {
|
||||||
va_list ap;
|
va_list ap;
|
||||||
va_start(ap, msg);
|
va_start(ap, msg);
|
||||||
|
MetaspaceShared::set_archive_loading_failed();
|
||||||
|
if (PrintSharedArchiveAndExit && _validating_classpath_entry_table) {
|
||||||
|
// If we are doing PrintSharedArchiveAndExit and some of the classpath entries
|
||||||
|
// do not validate, we can still continue "limping" to validate the remaining
|
||||||
|
// entries. No need to quit.
|
||||||
|
tty->print("[");
|
||||||
|
tty->vprint(msg, ap);
|
||||||
|
tty->print_cr("]");
|
||||||
|
} else {
|
||||||
if (RequireSharedSpaces) {
|
if (RequireSharedSpaces) {
|
||||||
fail(msg, ap);
|
fail(msg, ap);
|
||||||
} else {
|
} else {
|
||||||
|
@ -85,9 +98,11 @@ void FileMapInfo::fail_continue(const char *msg, ...) {
|
||||||
tty->print_cr("UseSharedSpaces: %s", msg);
|
tty->print_cr("UseSharedSpaces: %s", msg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
va_end(ap);
|
va_end(ap);
|
||||||
UseSharedSpaces = false;
|
UseSharedSpaces = false;
|
||||||
close();
|
assert(current_info() != NULL, "singleton must be registered");
|
||||||
|
current_info()->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fill in the fileMapInfo structure with data about this VM instance.
|
// Fill in the fileMapInfo structure with data about this VM instance.
|
||||||
|
@ -122,67 +137,201 @@ template <int N> static void get_header_version(char (&header_version) [N]) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FileMapInfo::FileMapInfo() {
|
||||||
|
assert(_current_info == NULL, "must be singleton"); // not thread safe
|
||||||
|
_current_info = this;
|
||||||
|
memset(this, 0, sizeof(FileMapInfo));
|
||||||
|
_file_offset = 0;
|
||||||
|
_file_open = false;
|
||||||
|
_header = SharedClassUtil::allocate_file_map_header();
|
||||||
|
_header->_version = _invalid_version;
|
||||||
|
}
|
||||||
|
|
||||||
|
FileMapInfo::~FileMapInfo() {
|
||||||
|
assert(_current_info == this, "must be singleton"); // not thread safe
|
||||||
|
_current_info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void FileMapInfo::populate_header(size_t alignment) {
|
void FileMapInfo::populate_header(size_t alignment) {
|
||||||
_header._magic = 0xf00baba2;
|
_header->populate(this, alignment);
|
||||||
_header._version = _current_version;
|
}
|
||||||
_header._alignment = alignment;
|
|
||||||
_header._obj_alignment = ObjectAlignmentInBytes;
|
size_t FileMapInfo::FileMapHeader::data_size() {
|
||||||
|
return SharedClassUtil::file_map_header_size() - sizeof(FileMapInfo::FileMapHeaderBase);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileMapInfo::FileMapHeader::populate(FileMapInfo* mapinfo, size_t alignment) {
|
||||||
|
_magic = 0xf00baba2;
|
||||||
|
_version = _current_version;
|
||||||
|
_alignment = alignment;
|
||||||
|
_obj_alignment = ObjectAlignmentInBytes;
|
||||||
|
_classpath_entry_table_size = mapinfo->_classpath_entry_table_size;
|
||||||
|
_classpath_entry_table = mapinfo->_classpath_entry_table;
|
||||||
|
_classpath_entry_size = mapinfo->_classpath_entry_size;
|
||||||
|
|
||||||
// The following fields are for sanity checks for whether this archive
|
// The following fields are for sanity checks for whether this archive
|
||||||
// will function correctly with this JVM and the bootclasspath it's
|
// will function correctly with this JVM and the bootclasspath it's
|
||||||
// invoked with.
|
// invoked with.
|
||||||
|
|
||||||
// JVM version string ... changes on each build.
|
// JVM version string ... changes on each build.
|
||||||
get_header_version(_header._jvm_ident);
|
get_header_version(_jvm_ident);
|
||||||
|
|
||||||
// Build checks on classpath and jar files
|
|
||||||
_header._num_jars = 0;
|
|
||||||
ClassPathEntry *cpe = ClassLoader::classpath_entry(0);
|
|
||||||
for ( ; cpe != NULL; cpe = cpe->next()) {
|
|
||||||
|
|
||||||
if (cpe->is_jar_file()) {
|
|
||||||
if (_header._num_jars >= JVM_SHARED_JARS_MAX) {
|
|
||||||
fail_stop("Too many jar files to share.", NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Jar file - record timestamp and file size.
|
void FileMapInfo::allocate_classpath_entry_table() {
|
||||||
|
int bytes = 0;
|
||||||
|
int count = 0;
|
||||||
|
char* strptr = NULL;
|
||||||
|
char* strptr_max = NULL;
|
||||||
|
Thread* THREAD = Thread::current();
|
||||||
|
|
||||||
|
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
||||||
|
size_t entry_size = SharedClassUtil::shared_class_path_entry_size();
|
||||||
|
|
||||||
|
for (int pass=0; pass<2; pass++) {
|
||||||
|
ClassPathEntry *cpe = ClassLoader::classpath_entry(0);
|
||||||
|
|
||||||
|
for (int cur_entry = 0 ; cpe != NULL; cpe = cpe->next(), cur_entry++) {
|
||||||
|
const char *name = cpe->name();
|
||||||
|
int name_bytes = (int)(strlen(name) + 1);
|
||||||
|
|
||||||
|
if (pass == 0) {
|
||||||
|
count ++;
|
||||||
|
bytes += (int)entry_size;
|
||||||
|
bytes += name_bytes;
|
||||||
|
if (TraceClassPaths || (TraceClassLoading && Verbose)) {
|
||||||
|
tty->print_cr("[Add main shared path (%s) %s]", (cpe->is_jar_file() ? "jar" : "dir"), name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
SharedClassPathEntry* ent = shared_classpath(cur_entry);
|
||||||
|
if (cpe->is_jar_file()) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
const char *path = cpe->name();
|
if (os::stat(name, &st) != 0) {
|
||||||
if (os::stat(path, &st) != 0) {
|
// The file/dir must exist, or it would not have been added
|
||||||
|
// into ClassLoader::classpath_entry().
|
||||||
|
//
|
||||||
// If we can't access a jar file in the boot path, then we can't
|
// If we can't access a jar file in the boot path, then we can't
|
||||||
// make assumptions about where classes get loaded from.
|
// make assumptions about where classes get loaded from.
|
||||||
fail_stop("Unable to open jar file %s.", path);
|
FileMapInfo::fail_stop("Unable to open jar file %s.", name);
|
||||||
}
|
}
|
||||||
_header._jar[_header._num_jars]._timestamp = st.st_mtime;
|
|
||||||
_header._jar[_header._num_jars]._filesize = st.st_size;
|
|
||||||
_header._num_jars++;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// If directories appear in boot classpath, they must be empty to
|
EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
|
||||||
// avoid having to verify each individual class file.
|
SharedClassUtil::update_shared_classpath(cpe, ent, st.st_mtime, st.st_size, THREAD);
|
||||||
const char* name = ((ClassPathDirEntry*)cpe)->name();
|
} else {
|
||||||
|
ent->_filesize = -1;
|
||||||
if (!os::dir_is_empty(name)) {
|
if (!os::dir_is_empty(name)) {
|
||||||
fail_stop("Boot classpath directory %s is not empty.", name);
|
ClassLoader::exit_with_path_failure("Cannot have non-empty directory in archived classpaths", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ent->_name = strptr;
|
||||||
|
if (strptr + name_bytes <= strptr_max) {
|
||||||
|
strncpy(strptr, name, (size_t)name_bytes); // name_bytes includes trailing 0.
|
||||||
|
strptr += name_bytes;
|
||||||
|
} else {
|
||||||
|
assert(0, "miscalculated buffer size");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pass == 0) {
|
||||||
|
EXCEPTION_MARK; // The following call should never throw, but would exit VM on error.
|
||||||
|
Array<u8>* arr = MetadataFactory::new_array<u8>(loader_data, (bytes + 7)/8, THREAD);
|
||||||
|
strptr = (char*)(arr->data());
|
||||||
|
strptr_max = strptr + bytes;
|
||||||
|
SharedClassPathEntry* table = (SharedClassPathEntry*)strptr;
|
||||||
|
strptr += entry_size * count;
|
||||||
|
|
||||||
|
_classpath_entry_table_size = count;
|
||||||
|
_classpath_entry_table = table;
|
||||||
|
_classpath_entry_size = entry_size;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileMapInfo::validate_classpath_entry_table() {
|
||||||
|
_validating_classpath_entry_table = true;
|
||||||
|
|
||||||
|
int count = _header->_classpath_entry_table_size;
|
||||||
|
|
||||||
|
_classpath_entry_table = _header->_classpath_entry_table;
|
||||||
|
_classpath_entry_size = _header->_classpath_entry_size;
|
||||||
|
|
||||||
|
for (int i=0; i<count; i++) {
|
||||||
|
SharedClassPathEntry* ent = shared_classpath(i);
|
||||||
|
struct stat st;
|
||||||
|
const char* name = ent->_name;
|
||||||
|
bool ok = true;
|
||||||
|
if (TraceClassPaths || (TraceClassLoading && Verbose)) {
|
||||||
|
tty->print_cr("[Checking shared classpath entry: %s]", name);
|
||||||
|
}
|
||||||
|
if (os::stat(name, &st) != 0) {
|
||||||
|
fail_continue("Required classpath entry does not exist: %s", name);
|
||||||
|
ok = false;
|
||||||
|
} else if (ent->is_dir()) {
|
||||||
|
if (!os::dir_is_empty(name)) {
|
||||||
|
fail_continue("directory is not empty: %s", name);
|
||||||
|
ok = false;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (ent->_timestamp != st.st_mtime ||
|
||||||
|
ent->_filesize != st.st_size) {
|
||||||
|
ok = false;
|
||||||
|
if (PrintSharedArchiveAndExit) {
|
||||||
|
fail_continue(ent->_timestamp != st.st_mtime ?
|
||||||
|
"Timestamp mismatch" :
|
||||||
|
"File size mismatch");
|
||||||
|
} else {
|
||||||
|
fail_continue("A jar file is not the one used while building"
|
||||||
|
" the shared archive file: %s", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ok) {
|
||||||
|
if (TraceClassPaths || (TraceClassLoading && Verbose)) {
|
||||||
|
tty->print_cr("[ok]");
|
||||||
|
}
|
||||||
|
} else if (!PrintSharedArchiveAndExit) {
|
||||||
|
_validating_classpath_entry_table = false;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_classpath_entry_table_size = _header->_classpath_entry_table_size;
|
||||||
|
_validating_classpath_entry_table = false;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Read the FileMapInfo information from the file.
|
// Read the FileMapInfo information from the file.
|
||||||
|
|
||||||
bool FileMapInfo::init_from_file(int fd) {
|
bool FileMapInfo::init_from_file(int fd) {
|
||||||
|
size_t sz = _header->data_size();
|
||||||
size_t n = read(fd, &_header, sizeof(struct FileMapHeader));
|
char* addr = _header->data();
|
||||||
if (n != sizeof(struct FileMapHeader)) {
|
size_t n = os::read(fd, addr, (unsigned int)sz);
|
||||||
|
if (n != sz) {
|
||||||
fail_continue("Unable to read the file header.");
|
fail_continue("Unable to read the file header.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_header._version != current_version()) {
|
if (_header->_version != current_version()) {
|
||||||
fail_continue("The shared archive file has the wrong version.");
|
fail_continue("The shared archive file has the wrong version.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
_file_offset = (long)n;
|
_file_offset = (long)n;
|
||||||
|
|
||||||
|
size_t info_size = _header->_paths_misc_info_size;
|
||||||
|
_paths_misc_info = NEW_C_HEAP_ARRAY_RETURN_NULL(char, info_size, mtClass);
|
||||||
|
if (_paths_misc_info == NULL) {
|
||||||
|
fail_continue("Unable to read the file header.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
n = os::read(fd, _paths_misc_info, (unsigned int)info_size);
|
||||||
|
if (n != info_size) {
|
||||||
|
fail_continue("Unable to read the shared path info header.");
|
||||||
|
FREE_C_HEAP_ARRAY(char, _paths_misc_info, mtClass);
|
||||||
|
_paths_misc_info = NULL;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
_file_offset += (long)n;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -237,7 +386,16 @@ void FileMapInfo::open_for_write() {
|
||||||
// Write the header to the file, seek to the next allocation boundary.
|
// Write the header to the file, seek to the next allocation boundary.
|
||||||
|
|
||||||
void FileMapInfo::write_header() {
|
void FileMapInfo::write_header() {
|
||||||
write_bytes_aligned(&_header, sizeof(FileMapHeader));
|
int info_size = ClassLoader::get_shared_paths_misc_info_size();
|
||||||
|
|
||||||
|
_header->_paths_misc_info_size = info_size;
|
||||||
|
|
||||||
|
align_file_position();
|
||||||
|
size_t sz = _header->data_size();
|
||||||
|
char* addr = _header->data();
|
||||||
|
write_bytes(addr, (int)sz); // skip the C++ vtable
|
||||||
|
write_bytes(ClassLoader::get_shared_paths_misc_info(), info_size);
|
||||||
|
align_file_position();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -247,7 +405,7 @@ void FileMapInfo::write_space(int i, Metaspace* space, bool read_only) {
|
||||||
align_file_position();
|
align_file_position();
|
||||||
size_t used = space->used_bytes_slow(Metaspace::NonClassType);
|
size_t used = space->used_bytes_slow(Metaspace::NonClassType);
|
||||||
size_t capacity = space->capacity_bytes_slow(Metaspace::NonClassType);
|
size_t capacity = space->capacity_bytes_slow(Metaspace::NonClassType);
|
||||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i];
|
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
|
||||||
write_region(i, (char*)space->bottom(), used, capacity, read_only, false);
|
write_region(i, (char*)space->bottom(), used, capacity, read_only, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -257,7 +415,7 @@ void FileMapInfo::write_space(int i, Metaspace* space, bool read_only) {
|
||||||
void FileMapInfo::write_region(int region, char* base, size_t size,
|
void FileMapInfo::write_region(int region, char* base, size_t size,
|
||||||
size_t capacity, bool read_only,
|
size_t capacity, bool read_only,
|
||||||
bool allow_exec) {
|
bool allow_exec) {
|
||||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[region];
|
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[region];
|
||||||
|
|
||||||
if (_file_open) {
|
if (_file_open) {
|
||||||
guarantee(si->_file_offset == _file_offset, "file offset mismatch.");
|
guarantee(si->_file_offset == _file_offset, "file offset mismatch.");
|
||||||
|
@ -339,7 +497,7 @@ void FileMapInfo::close() {
|
||||||
// JVM/TI RedefineClasses() support:
|
// JVM/TI RedefineClasses() support:
|
||||||
// Remap the shared readonly space to shared readwrite, private.
|
// Remap the shared readonly space to shared readwrite, private.
|
||||||
bool FileMapInfo::remap_shared_readonly_as_readwrite() {
|
bool FileMapInfo::remap_shared_readonly_as_readwrite() {
|
||||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[0];
|
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[0];
|
||||||
if (!si->_read_only) {
|
if (!si->_read_only) {
|
||||||
// the space is already readwrite so we are done
|
// the space is already readwrite so we are done
|
||||||
return true;
|
return true;
|
||||||
|
@ -367,7 +525,7 @@ bool FileMapInfo::remap_shared_readonly_as_readwrite() {
|
||||||
|
|
||||||
// Map the whole region at once, assumed to be allocated contiguously.
|
// Map the whole region at once, assumed to be allocated contiguously.
|
||||||
ReservedSpace FileMapInfo::reserve_shared_memory() {
|
ReservedSpace FileMapInfo::reserve_shared_memory() {
|
||||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[0];
|
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[0];
|
||||||
char* requested_addr = si->_base;
|
char* requested_addr = si->_base;
|
||||||
|
|
||||||
size_t size = FileMapInfo::shared_spaces_size();
|
size_t size = FileMapInfo::shared_spaces_size();
|
||||||
|
@ -389,7 +547,7 @@ ReservedSpace FileMapInfo::reserve_shared_memory() {
|
||||||
static const char* shared_region_name[] = { "ReadOnly", "ReadWrite", "MiscData", "MiscCode"};
|
static const char* shared_region_name[] = { "ReadOnly", "ReadWrite", "MiscData", "MiscCode"};
|
||||||
|
|
||||||
char* FileMapInfo::map_region(int i) {
|
char* FileMapInfo::map_region(int i) {
|
||||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i];
|
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
|
||||||
size_t used = si->_used;
|
size_t used = si->_used;
|
||||||
size_t alignment = os::vm_allocation_granularity();
|
size_t alignment = os::vm_allocation_granularity();
|
||||||
size_t size = align_size_up(used, alignment);
|
size_t size = align_size_up(used, alignment);
|
||||||
|
@ -415,7 +573,7 @@ char* FileMapInfo::map_region(int i) {
|
||||||
// Unmap a memory region in the address space.
|
// Unmap a memory region in the address space.
|
||||||
|
|
||||||
void FileMapInfo::unmap_region(int i) {
|
void FileMapInfo::unmap_region(int i) {
|
||||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i];
|
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
|
||||||
size_t used = si->_used;
|
size_t used = si->_used;
|
||||||
size_t size = align_size_up(used, os::vm_allocation_granularity());
|
size_t size = align_size_up(used, os::vm_allocation_granularity());
|
||||||
if (!os::unmap_memory(si->_base, size)) {
|
if (!os::unmap_memory(si->_base, size)) {
|
||||||
|
@ -432,12 +590,21 @@ void FileMapInfo::assert_mark(bool check) {
|
||||||
|
|
||||||
|
|
||||||
FileMapInfo* FileMapInfo::_current_info = NULL;
|
FileMapInfo* FileMapInfo::_current_info = NULL;
|
||||||
|
SharedClassPathEntry* FileMapInfo::_classpath_entry_table = NULL;
|
||||||
|
int FileMapInfo::_classpath_entry_table_size = 0;
|
||||||
|
size_t FileMapInfo::_classpath_entry_size = 0x1234baad;
|
||||||
|
bool FileMapInfo::_validating_classpath_entry_table = false;
|
||||||
|
|
||||||
// Open the shared archive file, read and validate the header
|
// Open the shared archive file, read and validate the header
|
||||||
// information (version, boot classpath, etc.). If initialization
|
// information (version, boot classpath, etc.). If initialization
|
||||||
// fails, shared spaces are disabled and the file is closed. [See
|
// fails, shared spaces are disabled and the file is closed. [See
|
||||||
// fail_continue.]
|
// fail_continue.]
|
||||||
|
//
|
||||||
|
// Validation of the archive is done in two steps:
|
||||||
|
//
|
||||||
|
// [1] validate_header() - done here. This checks the header, including _paths_misc_info.
|
||||||
|
// [2] validate_classpath_entry_table - this is done later, because the table is in the RW
|
||||||
|
// region of the archive, which is not mapped yet.
|
||||||
bool FileMapInfo::initialize() {
|
bool FileMapInfo::initialize() {
|
||||||
assert(UseSharedSpaces, "UseSharedSpaces expected.");
|
assert(UseSharedSpaces, "UseSharedSpaces expected.");
|
||||||
|
|
||||||
|
@ -451,92 +618,66 @@ bool FileMapInfo::initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
init_from_file(_fd);
|
init_from_file(_fd);
|
||||||
if (!validate()) {
|
if (!validate_header()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
SharedReadOnlySize = _header._space[0]._capacity;
|
SharedReadOnlySize = _header->_space[0]._capacity;
|
||||||
SharedReadWriteSize = _header._space[1]._capacity;
|
SharedReadWriteSize = _header->_space[1]._capacity;
|
||||||
SharedMiscDataSize = _header._space[2]._capacity;
|
SharedMiscDataSize = _header->_space[2]._capacity;
|
||||||
SharedMiscCodeSize = _header._space[3]._capacity;
|
SharedMiscCodeSize = _header->_space[3]._capacity;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileMapInfo::FileMapHeader::validate() {
|
||||||
bool FileMapInfo::validate() {
|
if (_version != current_version()) {
|
||||||
if (_header._version != current_version()) {
|
FileMapInfo::fail_continue("The shared archive file is the wrong version.");
|
||||||
fail_continue("The shared archive file is the wrong version.");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_header._magic != (int)0xf00baba2) {
|
if (_magic != (int)0xf00baba2) {
|
||||||
fail_continue("The shared archive file has a bad magic number.");
|
FileMapInfo::fail_continue("The shared archive file has a bad magic number.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
char header_version[JVM_IDENT_MAX];
|
char header_version[JVM_IDENT_MAX];
|
||||||
get_header_version(header_version);
|
get_header_version(header_version);
|
||||||
if (strncmp(_header._jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) {
|
if (strncmp(_jvm_ident, header_version, JVM_IDENT_MAX-1) != 0) {
|
||||||
fail_continue("The shared archive file was created by a different"
|
if (TraceClassPaths) {
|
||||||
" version or build of HotSpot.");
|
tty->print_cr("Expected: %s", header_version);
|
||||||
|
tty->print_cr("Actual: %s", _jvm_ident);
|
||||||
|
}
|
||||||
|
FileMapInfo::fail_continue("The shared archive file was created by a different"
|
||||||
|
" version or build of HotSpot");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (_header._obj_alignment != ObjectAlignmentInBytes) {
|
if (_obj_alignment != ObjectAlignmentInBytes) {
|
||||||
fail_continue("The shared archive file's ObjectAlignmentInBytes of %d"
|
FileMapInfo::fail_continue("The shared archive file's ObjectAlignmentInBytes of %d"
|
||||||
" does not equal the current ObjectAlignmentInBytes of %d.",
|
" does not equal the current ObjectAlignmentInBytes of %d.",
|
||||||
_header._obj_alignment, ObjectAlignmentInBytes);
|
_obj_alignment, ObjectAlignmentInBytes);
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cannot verify interpreter yet, as it can only be created after the GC
|
|
||||||
// heap has been initialized.
|
|
||||||
|
|
||||||
if (_header._num_jars >= JVM_SHARED_JARS_MAX) {
|
|
||||||
fail_continue("Too many jar files to share.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Build checks on classpath and jar files
|
|
||||||
int num_jars_now = 0;
|
|
||||||
ClassPathEntry *cpe = ClassLoader::classpath_entry(0);
|
|
||||||
for ( ; cpe != NULL; cpe = cpe->next()) {
|
|
||||||
|
|
||||||
if (cpe->is_jar_file()) {
|
|
||||||
if (num_jars_now < _header._num_jars) {
|
|
||||||
|
|
||||||
// Jar file - verify timestamp and file size.
|
|
||||||
struct stat st;
|
|
||||||
const char *path = cpe->name();
|
|
||||||
if (os::stat(path, &st) != 0) {
|
|
||||||
fail_continue("Unable to open jar file %s.", path);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (_header._jar[num_jars_now]._timestamp != st.st_mtime ||
|
|
||||||
_header._jar[num_jars_now]._filesize != st.st_size) {
|
|
||||||
fail_continue("A jar file is not the one used while building"
|
|
||||||
" the shared archive file.");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
++num_jars_now;
|
|
||||||
} else {
|
|
||||||
|
|
||||||
// If directories appear in boot classpath, they must be empty to
|
|
||||||
// avoid having to verify each individual class file.
|
|
||||||
const char* name = ((ClassPathDirEntry*)cpe)->name();
|
|
||||||
if (!os::dir_is_empty(name)) {
|
|
||||||
fail_continue("Boot classpath directory %s is not empty.", name);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (num_jars_now < _header._num_jars) {
|
|
||||||
fail_continue("The number of jar files in the boot classpath is"
|
|
||||||
" less than the number the shared archive was created with.");
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool FileMapInfo::validate_header() {
|
||||||
|
bool status = _header->validate();
|
||||||
|
|
||||||
|
if (status) {
|
||||||
|
if (!ClassLoader::check_shared_paths_misc_info(_paths_misc_info, _header->_paths_misc_info_size)) {
|
||||||
|
if (!PrintSharedArchiveAndExit) {
|
||||||
|
fail_continue("shared class paths mismatch (hint: enable -XX:+TraceClassPaths to diagnose the failure)");
|
||||||
|
status = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_paths_misc_info != NULL) {
|
||||||
|
FREE_C_HEAP_ARRAY(char, _paths_misc_info, mtClass);
|
||||||
|
_paths_misc_info = NULL;
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
// The following method is provided to see whether a given pointer
|
// The following method is provided to see whether a given pointer
|
||||||
// falls in the mapped shared space.
|
// falls in the mapped shared space.
|
||||||
// Param:
|
// Param:
|
||||||
|
@ -545,8 +686,8 @@ bool FileMapInfo::validate() {
|
||||||
// True if the p is within the mapped shared space, otherwise, false.
|
// True if the p is within the mapped shared space, otherwise, false.
|
||||||
bool FileMapInfo::is_in_shared_space(const void* p) {
|
bool FileMapInfo::is_in_shared_space(const void* p) {
|
||||||
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
||||||
if (p >= _header._space[i]._base &&
|
if (p >= _header->_space[i]._base &&
|
||||||
p < _header._space[i]._base + _header._space[i]._used) {
|
p < _header->_space[i]._base + _header->_space[i]._used) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -557,7 +698,7 @@ bool FileMapInfo::is_in_shared_space(const void* p) {
|
||||||
void FileMapInfo::print_shared_spaces() {
|
void FileMapInfo::print_shared_spaces() {
|
||||||
gclog_or_tty->print_cr("Shared Spaces:");
|
gclog_or_tty->print_cr("Shared Spaces:");
|
||||||
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
||||||
struct FileMapInfo::FileMapHeader::space_info* si = &_header._space[i];
|
struct FileMapInfo::FileMapHeader::space_info* si = &_header->_space[i];
|
||||||
gclog_or_tty->print(" %s " INTPTR_FORMAT "-" INTPTR_FORMAT,
|
gclog_or_tty->print(" %s " INTPTR_FORMAT "-" INTPTR_FORMAT,
|
||||||
shared_region_name[i],
|
shared_region_name[i],
|
||||||
si->_base, si->_base + si->_used);
|
si->_base, si->_base + si->_used);
|
||||||
|
@ -570,9 +711,9 @@ void FileMapInfo::stop_sharing_and_unmap(const char* msg) {
|
||||||
if (map_info) {
|
if (map_info) {
|
||||||
map_info->fail_continue(msg);
|
map_info->fail_continue(msg);
|
||||||
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
for (int i = 0; i < MetaspaceShared::n_regions; i++) {
|
||||||
if (map_info->_header._space[i]._base != NULL) {
|
if (map_info->_header->_space[i]._base != NULL) {
|
||||||
map_info->unmap_region(i);
|
map_info->unmap_region(i);
|
||||||
map_info->_header._space[i]._base = NULL;
|
map_info->_header->_space[i]._base = NULL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (DumpSharedSpaces) {
|
} else if (DumpSharedSpaces) {
|
||||||
|
|
|
@ -37,30 +37,55 @@
|
||||||
// misc data (block offset table, string table, symbols, dictionary, etc.)
|
// misc data (block offset table, string table, symbols, dictionary, etc.)
|
||||||
// tag(666)
|
// tag(666)
|
||||||
|
|
||||||
static const int JVM_SHARED_JARS_MAX = 128;
|
|
||||||
static const int JVM_SPACENAME_MAX = 128;
|
|
||||||
static const int JVM_IDENT_MAX = 256;
|
static const int JVM_IDENT_MAX = 256;
|
||||||
static const int JVM_ARCH_MAX = 12;
|
|
||||||
|
|
||||||
|
|
||||||
class Metaspace;
|
class Metaspace;
|
||||||
|
|
||||||
|
class SharedClassPathEntry VALUE_OBJ_CLASS_SPEC {
|
||||||
|
public:
|
||||||
|
const char *_name;
|
||||||
|
time_t _timestamp; // jar timestamp, 0 if is directory
|
||||||
|
long _filesize; // jar file size, -1 if is directory
|
||||||
|
bool is_dir() {
|
||||||
|
return _filesize == -1;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
class FileMapInfo : public CHeapObj<mtInternal> {
|
class FileMapInfo : public CHeapObj<mtInternal> {
|
||||||
private:
|
private:
|
||||||
|
friend class ManifestStream;
|
||||||
enum {
|
enum {
|
||||||
_invalid_version = -1,
|
_invalid_version = -1,
|
||||||
_current_version = 1
|
_current_version = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
bool _file_open;
|
bool _file_open;
|
||||||
int _fd;
|
int _fd;
|
||||||
long _file_offset;
|
long _file_offset;
|
||||||
|
|
||||||
|
private:
|
||||||
|
static SharedClassPathEntry* _classpath_entry_table;
|
||||||
|
static int _classpath_entry_table_size;
|
||||||
|
static size_t _classpath_entry_size;
|
||||||
|
static bool _validating_classpath_entry_table;
|
||||||
|
|
||||||
// FileMapHeader describes the shared space data in the file to be
|
// FileMapHeader describes the shared space data in the file to be
|
||||||
// mapped. This structure gets written to a file. It is not a class, so
|
// mapped. This structure gets written to a file. It is not a class, so
|
||||||
// that the compilers don't add any compiler-private data to it.
|
// that the compilers don't add any compiler-private data to it.
|
||||||
|
|
||||||
struct FileMapHeader {
|
public:
|
||||||
|
struct FileMapHeaderBase : public CHeapObj<mtClass> {
|
||||||
|
virtual bool validate() = 0;
|
||||||
|
virtual void populate(FileMapInfo* info, size_t alignment) = 0;
|
||||||
|
};
|
||||||
|
struct FileMapHeader : FileMapHeaderBase {
|
||||||
|
// Use data() and data_size() to memcopy to/from the FileMapHeader. We need to
|
||||||
|
// avoid read/writing the C++ vtable pointer.
|
||||||
|
static size_t data_size();
|
||||||
|
char* data() {
|
||||||
|
return ((char*)this) + sizeof(FileMapHeaderBase);
|
||||||
|
}
|
||||||
|
|
||||||
int _magic; // identify file type.
|
int _magic; // identify file type.
|
||||||
int _version; // (from enum, above.)
|
int _version; // (from enum, above.)
|
||||||
size_t _alignment; // how shared archive should be aligned
|
size_t _alignment; // how shared archive should be aligned
|
||||||
|
@ -78,44 +103,64 @@ private:
|
||||||
// The following fields are all sanity checks for whether this archive
|
// The following fields are all sanity checks for whether this archive
|
||||||
// will function correctly with this JVM and the bootclasspath it's
|
// will function correctly with this JVM and the bootclasspath it's
|
||||||
// invoked with.
|
// invoked with.
|
||||||
char _arch[JVM_ARCH_MAX]; // architecture
|
|
||||||
char _jvm_ident[JVM_IDENT_MAX]; // identifier for jvm
|
char _jvm_ident[JVM_IDENT_MAX]; // identifier for jvm
|
||||||
int _num_jars; // Number of jars in bootclasspath
|
|
||||||
|
|
||||||
// Per jar file data: timestamp, size.
|
// The _paths_misc_info is a variable-size structure that records "miscellaneous"
|
||||||
|
// information during dumping. It is generated and validated by the
|
||||||
|
// SharedPathsMiscInfo class. See SharedPathsMiscInfo.hpp and sharedClassUtil.hpp for
|
||||||
|
// detailed description.
|
||||||
|
//
|
||||||
|
// The _paths_misc_info data is stored as a byte array in the archive file header,
|
||||||
|
// immediately after the _header field. This information is used only when
|
||||||
|
// checking the validity of the archive and is deallocated after the archive is loaded.
|
||||||
|
//
|
||||||
|
// Note that the _paths_misc_info does NOT include information for JAR files
|
||||||
|
// that existed during dump time. Their information is stored in _classpath_entry_table.
|
||||||
|
int _paths_misc_info_size;
|
||||||
|
|
||||||
|
// The following is a table of all the class path entries that were used
|
||||||
|
// during dumping. At run time, we require these files to exist and have the same
|
||||||
|
// size/modification time, or else the archive will refuse to load.
|
||||||
|
//
|
||||||
|
// All of these entries must be JAR files. The dumping process would fail if a non-empty
|
||||||
|
// directory was specified in the classpaths. If an empty directory was specified
|
||||||
|
// it is checked by the _paths_misc_info as described above.
|
||||||
|
//
|
||||||
|
// FIXME -- if JAR files in the tail of the list were specified but not used during dumping,
|
||||||
|
// they should be removed from this table, to save space and to avoid spurious
|
||||||
|
// loading failures during runtime.
|
||||||
|
int _classpath_entry_table_size;
|
||||||
|
size_t _classpath_entry_size;
|
||||||
|
SharedClassPathEntry* _classpath_entry_table;
|
||||||
|
|
||||||
|
virtual bool validate();
|
||||||
|
virtual void populate(FileMapInfo* info, size_t alignment);
|
||||||
|
};
|
||||||
|
|
||||||
|
FileMapHeader * _header;
|
||||||
|
|
||||||
struct {
|
|
||||||
time_t _timestamp; // jar timestamp.
|
|
||||||
long _filesize; // jar file size.
|
|
||||||
} _jar[JVM_SHARED_JARS_MAX];
|
|
||||||
} _header;
|
|
||||||
const char* _full_path;
|
const char* _full_path;
|
||||||
|
char* _paths_misc_info;
|
||||||
|
|
||||||
static FileMapInfo* _current_info;
|
static FileMapInfo* _current_info;
|
||||||
|
|
||||||
bool init_from_file(int fd);
|
bool init_from_file(int fd);
|
||||||
void align_file_position();
|
void align_file_position();
|
||||||
|
bool validate_header_impl();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
FileMapInfo() {
|
FileMapInfo();
|
||||||
_file_offset = 0;
|
~FileMapInfo();
|
||||||
_file_open = false;
|
|
||||||
_header._version = _invalid_version;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int current_version() { return _current_version; }
|
static int current_version() { return _current_version; }
|
||||||
void populate_header(size_t alignment);
|
void populate_header(size_t alignment);
|
||||||
bool validate();
|
bool validate_header();
|
||||||
void invalidate();
|
void invalidate();
|
||||||
int version() { return _header._version; }
|
int version() { return _header->_version; }
|
||||||
size_t alignment() { return _header._alignment; }
|
size_t alignment() { return _header->_alignment; }
|
||||||
size_t space_capacity(int i) { return _header._space[i]._capacity; }
|
size_t space_capacity(int i) { return _header->_space[i]._capacity; }
|
||||||
char* region_base(int i) { return _header._space[i]._base; }
|
char* region_base(int i) { return _header->_space[i]._base; }
|
||||||
struct FileMapHeader* header() { return &_header; }
|
struct FileMapHeader* header() { return _header; }
|
||||||
|
|
||||||
static void set_current_info(FileMapInfo* info) {
|
|
||||||
CDS_ONLY(_current_info = info;)
|
|
||||||
}
|
|
||||||
|
|
||||||
static FileMapInfo* current_info() {
|
static FileMapInfo* current_info() {
|
||||||
CDS_ONLY(return _current_info;)
|
CDS_ONLY(return _current_info;)
|
||||||
|
@ -146,7 +191,7 @@ public:
|
||||||
|
|
||||||
// Errors.
|
// Errors.
|
||||||
static void fail_stop(const char *msg, ...);
|
static void fail_stop(const char *msg, ...);
|
||||||
void fail_continue(const char *msg, ...);
|
static void fail_continue(const char *msg, ...);
|
||||||
|
|
||||||
// Return true if given address is in the mapped shared space.
|
// Return true if given address is in the mapped shared space.
|
||||||
bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false);
|
bool is_in_shared_space(const void* p) NOT_CDS_RETURN_(false);
|
||||||
|
@ -160,6 +205,22 @@ public:
|
||||||
|
|
||||||
// Stop CDS sharing and unmap CDS regions.
|
// Stop CDS sharing and unmap CDS regions.
|
||||||
static void stop_sharing_and_unmap(const char* msg);
|
static void stop_sharing_and_unmap(const char* msg);
|
||||||
|
|
||||||
|
static void allocate_classpath_entry_table();
|
||||||
|
bool validate_classpath_entry_table();
|
||||||
|
|
||||||
|
static SharedClassPathEntry* shared_classpath(int index) {
|
||||||
|
char* p = (char*)_classpath_entry_table;
|
||||||
|
p += _classpath_entry_size * index;
|
||||||
|
return (SharedClassPathEntry*)p;
|
||||||
|
}
|
||||||
|
static const char* shared_classpath_name(int index) {
|
||||||
|
return shared_classpath(index)->_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int get_number_of_share_classpaths() {
|
||||||
|
return _classpath_entry_table_size;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SHARE_VM_MEMORY_FILEMAP_HPP
|
#endif // SHARE_VM_MEMORY_FILEMAP_HPP
|
||||||
|
|
|
@ -79,6 +79,12 @@ class MetadataFactory : AllStatic {
|
||||||
// Deallocation method for metadata
|
// Deallocation method for metadata
|
||||||
template <class T>
|
template <class T>
|
||||||
static void free_metadata(ClassLoaderData* loader_data, T md) {
|
static void free_metadata(ClassLoaderData* loader_data, T md) {
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
// FIXME: the freeing code is buggy, especially when PrintSharedSpaces is enabled.
|
||||||
|
// Disable for now -- this means if you specify bad classes in your classlist you
|
||||||
|
// may have wasted space inside the archive.
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (md != NULL) {
|
if (md != NULL) {
|
||||||
assert(loader_data != NULL, "shouldn't pass null");
|
assert(loader_data != NULL, "shouldn't pass null");
|
||||||
int size = md->size();
|
int size = md->size();
|
||||||
|
|
|
@ -413,6 +413,7 @@ static bool should_commit_large_pages_when_reserving(size_t bytes) {
|
||||||
VirtualSpaceNode::VirtualSpaceNode(size_t bytes) : _top(NULL), _next(NULL), _rs(), _container_count(0) {
|
VirtualSpaceNode::VirtualSpaceNode(size_t bytes) : _top(NULL), _next(NULL), _rs(), _container_count(0) {
|
||||||
assert_is_size_aligned(bytes, Metaspace::reserve_alignment());
|
assert_is_size_aligned(bytes, Metaspace::reserve_alignment());
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
// This allocates memory with mmap. For DumpSharedspaces, try to reserve
|
// This allocates memory with mmap. For DumpSharedspaces, try to reserve
|
||||||
// configurable address, generally at the top of the Java heap so other
|
// configurable address, generally at the top of the Java heap so other
|
||||||
// memory addresses don't conflict.
|
// memory addresses don't conflict.
|
||||||
|
@ -428,7 +429,9 @@ VirtualSpaceNode::VirtualSpaceNode(size_t bytes) : _top(NULL), _next(NULL), _rs(
|
||||||
_rs = ReservedSpace(bytes, Metaspace::reserve_alignment(), large_pages);
|
_rs = ReservedSpace(bytes, Metaspace::reserve_alignment(), large_pages);
|
||||||
}
|
}
|
||||||
MetaspaceShared::set_shared_rs(&_rs);
|
MetaspaceShared::set_shared_rs(&_rs);
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
bool large_pages = should_commit_large_pages_when_reserving(bytes);
|
bool large_pages = should_commit_large_pages_when_reserving(bytes);
|
||||||
|
|
||||||
_rs = ReservedSpace(bytes, Metaspace::reserve_alignment(), large_pages);
|
_rs = ReservedSpace(bytes, Metaspace::reserve_alignment(), large_pages);
|
||||||
|
@ -2939,11 +2942,14 @@ void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address
|
||||||
// between the lower base and higher address.
|
// between the lower base and higher address.
|
||||||
address lower_base;
|
address lower_base;
|
||||||
address higher_address;
|
address higher_address;
|
||||||
|
#if INCLUDE_CDS
|
||||||
if (UseSharedSpaces) {
|
if (UseSharedSpaces) {
|
||||||
higher_address = MAX2((address)(cds_base + FileMapInfo::shared_spaces_size()),
|
higher_address = MAX2((address)(cds_base + FileMapInfo::shared_spaces_size()),
|
||||||
(address)(metaspace_base + compressed_class_space_size()));
|
(address)(metaspace_base + compressed_class_space_size()));
|
||||||
lower_base = MIN2(metaspace_base, cds_base);
|
lower_base = MIN2(metaspace_base, cds_base);
|
||||||
} else {
|
} else
|
||||||
|
#endif
|
||||||
|
{
|
||||||
higher_address = metaspace_base + compressed_class_space_size();
|
higher_address = metaspace_base + compressed_class_space_size();
|
||||||
lower_base = metaspace_base;
|
lower_base = metaspace_base;
|
||||||
|
|
||||||
|
@ -2964,6 +2970,7 @@ void Metaspace::set_narrow_klass_base_and_shift(address metaspace_base, address
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
// Return TRUE if the specified metaspace_base and cds_base are close enough
|
// Return TRUE if the specified metaspace_base and cds_base are close enough
|
||||||
// to work with compressed klass pointers.
|
// to work with compressed klass pointers.
|
||||||
bool Metaspace::can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base) {
|
bool Metaspace::can_use_cds_with_metaspace_addr(char* metaspace_base, address cds_base) {
|
||||||
|
@ -2974,6 +2981,7 @@ bool Metaspace::can_use_cds_with_metaspace_addr(char* metaspace_base, address cd
|
||||||
(address)(metaspace_base + compressed_class_space_size()));
|
(address)(metaspace_base + compressed_class_space_size()));
|
||||||
return ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax);
|
return ((uint64_t)(higher_address - lower_base) <= UnscaledClassSpaceMax);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// Try to allocate the metaspace at the requested addr.
|
// Try to allocate the metaspace at the requested addr.
|
||||||
void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base) {
|
void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, address cds_base) {
|
||||||
|
@ -2993,6 +3001,7 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a
|
||||||
large_pages,
|
large_pages,
|
||||||
requested_addr, 0);
|
requested_addr, 0);
|
||||||
if (!metaspace_rs.is_reserved()) {
|
if (!metaspace_rs.is_reserved()) {
|
||||||
|
#if INCLUDE_CDS
|
||||||
if (UseSharedSpaces) {
|
if (UseSharedSpaces) {
|
||||||
size_t increment = align_size_up(1*G, _reserve_alignment);
|
size_t increment = align_size_up(1*G, _reserve_alignment);
|
||||||
|
|
||||||
|
@ -3007,7 +3016,7 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a
|
||||||
_reserve_alignment, large_pages, addr, 0);
|
_reserve_alignment, large_pages, addr, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
// If no successful allocation then try to allocate the space anywhere. If
|
// If no successful allocation then try to allocate the space anywhere. If
|
||||||
// that fails then OOM doom. At this point we cannot try allocating the
|
// that fails then OOM doom. At this point we cannot try allocating the
|
||||||
// metaspace as if UseCompressedClassPointers is off because too much
|
// metaspace as if UseCompressedClassPointers is off because too much
|
||||||
|
@ -3026,12 +3035,13 @@ void Metaspace::allocate_metaspace_compressed_klass_ptrs(char* requested_addr, a
|
||||||
// If we got here then the metaspace got allocated.
|
// If we got here then the metaspace got allocated.
|
||||||
MemTracker::record_virtual_memory_type((address)metaspace_rs.base(), mtClass);
|
MemTracker::record_virtual_memory_type((address)metaspace_rs.base(), mtClass);
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
// Verify that we can use shared spaces. Otherwise, turn off CDS.
|
// Verify that we can use shared spaces. Otherwise, turn off CDS.
|
||||||
if (UseSharedSpaces && !can_use_cds_with_metaspace_addr(metaspace_rs.base(), cds_base)) {
|
if (UseSharedSpaces && !can_use_cds_with_metaspace_addr(metaspace_rs.base(), cds_base)) {
|
||||||
FileMapInfo::stop_sharing_and_unmap(
|
FileMapInfo::stop_sharing_and_unmap(
|
||||||
"Could not allocate metaspace at a compatible address");
|
"Could not allocate metaspace at a compatible address");
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
set_narrow_klass_base_and_shift((address)metaspace_rs.base(),
|
set_narrow_klass_base_and_shift((address)metaspace_rs.base(),
|
||||||
UseSharedSpaces ? (address)cds_base : 0);
|
UseSharedSpaces ? (address)cds_base : 0);
|
||||||
|
|
||||||
|
@ -3115,6 +3125,7 @@ void Metaspace::global_initialize() {
|
||||||
MetaspaceShared::set_max_alignment(max_alignment);
|
MetaspaceShared::set_max_alignment(max_alignment);
|
||||||
|
|
||||||
if (DumpSharedSpaces) {
|
if (DumpSharedSpaces) {
|
||||||
|
#if INCLUDE_CDS
|
||||||
SharedReadOnlySize = align_size_up(SharedReadOnlySize, max_alignment);
|
SharedReadOnlySize = align_size_up(SharedReadOnlySize, max_alignment);
|
||||||
SharedReadWriteSize = align_size_up(SharedReadWriteSize, max_alignment);
|
SharedReadWriteSize = align_size_up(SharedReadWriteSize, max_alignment);
|
||||||
SharedMiscDataSize = align_size_up(SharedMiscDataSize, max_alignment);
|
SharedMiscDataSize = align_size_up(SharedMiscDataSize, max_alignment);
|
||||||
|
@ -3152,23 +3163,22 @@ void Metaspace::global_initialize() {
|
||||||
}
|
}
|
||||||
|
|
||||||
Universe::set_narrow_klass_shift(0);
|
Universe::set_narrow_klass_shift(0);
|
||||||
#endif
|
#endif // _LP64
|
||||||
|
#endif // INCLUDE_CDS
|
||||||
} else {
|
} else {
|
||||||
|
#if INCLUDE_CDS
|
||||||
// If using shared space, open the file that contains the shared space
|
// If using shared space, open the file that contains the shared space
|
||||||
// and map in the memory before initializing the rest of metaspace (so
|
// and map in the memory before initializing the rest of metaspace (so
|
||||||
// the addresses don't conflict)
|
// the addresses don't conflict)
|
||||||
address cds_address = NULL;
|
address cds_address = NULL;
|
||||||
if (UseSharedSpaces) {
|
if (UseSharedSpaces) {
|
||||||
FileMapInfo* mapinfo = new FileMapInfo();
|
FileMapInfo* mapinfo = new FileMapInfo();
|
||||||
memset(mapinfo, 0, sizeof(FileMapInfo));
|
|
||||||
|
|
||||||
// Open the shared archive file, read and validate the header. If
|
// Open the shared archive file, read and validate the header. If
|
||||||
// initialization fails, shared spaces [UseSharedSpaces] are
|
// initialization fails, shared spaces [UseSharedSpaces] are
|
||||||
// disabled and the file is closed.
|
// disabled and the file is closed.
|
||||||
// Map in spaces now also
|
// Map in spaces now also
|
||||||
if (mapinfo->initialize() && MetaspaceShared::map_shared_spaces(mapinfo)) {
|
if (mapinfo->initialize() && MetaspaceShared::map_shared_spaces(mapinfo)) {
|
||||||
FileMapInfo::set_current_info(mapinfo);
|
|
||||||
cds_total = FileMapInfo::shared_spaces_size();
|
cds_total = FileMapInfo::shared_spaces_size();
|
||||||
cds_address = (address)mapinfo->region_base(0);
|
cds_address = (address)mapinfo->region_base(0);
|
||||||
} else {
|
} else {
|
||||||
|
@ -3176,21 +3186,23 @@ void Metaspace::global_initialize() {
|
||||||
"archive file not closed or shared spaces not disabled.");
|
"archive file not closed or shared spaces not disabled.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif // INCLUDE_CDS
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
// If UseCompressedClassPointers is set then allocate the metaspace area
|
// If UseCompressedClassPointers is set then allocate the metaspace area
|
||||||
// above the heap and above the CDS area (if it exists).
|
// above the heap and above the CDS area (if it exists).
|
||||||
if (using_class_space()) {
|
if (using_class_space()) {
|
||||||
if (UseSharedSpaces) {
|
if (UseSharedSpaces) {
|
||||||
|
#if INCLUDE_CDS
|
||||||
char* cds_end = (char*)(cds_address + cds_total);
|
char* cds_end = (char*)(cds_address + cds_total);
|
||||||
cds_end = (char *)align_ptr_up(cds_end, _reserve_alignment);
|
cds_end = (char *)align_ptr_up(cds_end, _reserve_alignment);
|
||||||
allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
|
allocate_metaspace_compressed_klass_ptrs(cds_end, cds_address);
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
char* base = (char*)align_ptr_up(Universe::heap()->reserved_region().end(), _reserve_alignment);
|
char* base = (char*)align_ptr_up(Universe::heap()->reserved_region().end(), _reserve_alignment);
|
||||||
allocate_metaspace_compressed_klass_ptrs(base, 0);
|
allocate_metaspace_compressed_klass_ptrs(base, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif // _LP64
|
||||||
|
|
||||||
// Initialize these before initializing the VirtualSpaceList
|
// Initialize these before initializing the VirtualSpaceList
|
||||||
_first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord;
|
_first_chunk_word_size = InitialBootClassLoaderMetaspaceSize / BytesPerWord;
|
||||||
|
@ -3380,6 +3392,10 @@ void Metaspace::deallocate(MetaWord* ptr, size_t word_size, bool is_class) {
|
||||||
assert(!SafepointSynchronize::is_at_safepoint()
|
assert(!SafepointSynchronize::is_at_safepoint()
|
||||||
|| Thread::current()->is_VM_thread(), "should be the VM thread");
|
|| Thread::current()->is_VM_thread(), "should be the VM thread");
|
||||||
|
|
||||||
|
if (DumpSharedSpaces && PrintSharedSpaces) {
|
||||||
|
record_deallocation(ptr, vsm()->get_raw_word_size(word_size));
|
||||||
|
}
|
||||||
|
|
||||||
MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag);
|
MutexLockerEx ml(vsm()->lock(), Mutex::_no_safepoint_check_flag);
|
||||||
|
|
||||||
if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
|
if (word_size < TreeChunk<Metablock, FreeList<Metablock> >::min_size()) {
|
||||||
|
@ -3417,8 +3433,9 @@ MetaWord* Metaspace::allocate(ClassLoaderData* loader_data, size_t word_size,
|
||||||
if (result == NULL) {
|
if (result == NULL) {
|
||||||
report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite);
|
report_out_of_shared_space(read_only ? SharedReadOnly : SharedReadWrite);
|
||||||
}
|
}
|
||||||
|
if (PrintSharedSpaces) {
|
||||||
space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size));
|
space->record_allocation(result, type, space->vsm()->get_raw_word_size(word_size));
|
||||||
|
}
|
||||||
|
|
||||||
// Zero initialize.
|
// Zero initialize.
|
||||||
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
|
Copy::fill_to_aligned_words((HeapWord*)result, word_size, 0);
|
||||||
|
@ -3517,13 +3534,53 @@ const char* Metaspace::metadata_type_name(Metaspace::MetadataType mdtype) {
|
||||||
void Metaspace::record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size) {
|
void Metaspace::record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size) {
|
||||||
assert(DumpSharedSpaces, "sanity");
|
assert(DumpSharedSpaces, "sanity");
|
||||||
|
|
||||||
AllocRecord *rec = new AllocRecord((address)ptr, type, (int)word_size * HeapWordSize);
|
int byte_size = (int)word_size * HeapWordSize;
|
||||||
|
AllocRecord *rec = new AllocRecord((address)ptr, type, byte_size);
|
||||||
|
|
||||||
if (_alloc_record_head == NULL) {
|
if (_alloc_record_head == NULL) {
|
||||||
_alloc_record_head = _alloc_record_tail = rec;
|
_alloc_record_head = _alloc_record_tail = rec;
|
||||||
} else {
|
} else if (_alloc_record_tail->_ptr + _alloc_record_tail->_byte_size == (address)ptr) {
|
||||||
_alloc_record_tail->_next = rec;
|
_alloc_record_tail->_next = rec;
|
||||||
_alloc_record_tail = rec;
|
_alloc_record_tail = rec;
|
||||||
|
} else {
|
||||||
|
// slow linear search, but this doesn't happen that often, and only when dumping
|
||||||
|
for (AllocRecord *old = _alloc_record_head; old; old = old->_next) {
|
||||||
|
if (old->_ptr == ptr) {
|
||||||
|
assert(old->_type == MetaspaceObj::DeallocatedType, "sanity");
|
||||||
|
int remain_bytes = old->_byte_size - byte_size;
|
||||||
|
assert(remain_bytes >= 0, "sanity");
|
||||||
|
old->_type = type;
|
||||||
|
|
||||||
|
if (remain_bytes == 0) {
|
||||||
|
delete(rec);
|
||||||
|
} else {
|
||||||
|
address remain_ptr = address(ptr) + byte_size;
|
||||||
|
rec->_ptr = remain_ptr;
|
||||||
|
rec->_byte_size = remain_bytes;
|
||||||
|
rec->_type = MetaspaceObj::DeallocatedType;
|
||||||
|
rec->_next = old->_next;
|
||||||
|
old->_byte_size = byte_size;
|
||||||
|
old->_next = rec;
|
||||||
}
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(0, "reallocating a freed pointer that was not recorded");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Metaspace::record_deallocation(void* ptr, size_t word_size) {
|
||||||
|
assert(DumpSharedSpaces, "sanity");
|
||||||
|
|
||||||
|
for (AllocRecord *rec = _alloc_record_head; rec; rec = rec->_next) {
|
||||||
|
if (rec->_ptr == ptr) {
|
||||||
|
assert(rec->_byte_size == (int)word_size * HeapWordSize, "sanity");
|
||||||
|
rec->_type = MetaspaceObj::DeallocatedType;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(0, "deallocating a pointer that was not recorded");
|
||||||
}
|
}
|
||||||
|
|
||||||
void Metaspace::iterate(Metaspace::AllocRecordClosure *closure) {
|
void Metaspace::iterate(Metaspace::AllocRecordClosure *closure) {
|
||||||
|
|
|
@ -171,9 +171,10 @@ class Metaspace : public CHeapObj<mtClass> {
|
||||||
static const MetaspaceTracer* tracer() { return _tracer; }
|
static const MetaspaceTracer* tracer() { return _tracer; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// This is used by DumpSharedSpaces only, where only _vsm is used. So we will
|
// These 2 methods are used by DumpSharedSpaces only, where only _vsm is used. So we will
|
||||||
// maintain a single list for now.
|
// maintain a single list for now.
|
||||||
void record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size);
|
void record_allocation(void* ptr, MetaspaceObj::Type type, size_t word_size);
|
||||||
|
void record_deallocation(void* ptr, size_t word_size);
|
||||||
|
|
||||||
#ifdef _LP64
|
#ifdef _LP64
|
||||||
static void set_narrow_klass_base_and_shift(address metaspace_base, address cds_base);
|
static void set_narrow_klass_base_and_shift(address metaspace_base, address cds_base);
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "classfile/dictionary.hpp"
|
#include "classfile/dictionary.hpp"
|
||||||
#include "classfile/loaderConstraints.hpp"
|
#include "classfile/loaderConstraints.hpp"
|
||||||
#include "classfile/placeholders.hpp"
|
#include "classfile/placeholders.hpp"
|
||||||
|
#include "classfile/sharedClassUtil.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "code/codeCache.hpp"
|
#include "code/codeCache.hpp"
|
||||||
|
@ -47,6 +48,10 @@ int MetaspaceShared::_max_alignment = 0;
|
||||||
|
|
||||||
ReservedSpace* MetaspaceShared::_shared_rs = NULL;
|
ReservedSpace* MetaspaceShared::_shared_rs = NULL;
|
||||||
|
|
||||||
|
bool MetaspaceShared::_link_classes_made_progress;
|
||||||
|
bool MetaspaceShared::_check_classes_made_progress;
|
||||||
|
bool MetaspaceShared::_has_error_classes;
|
||||||
|
bool MetaspaceShared::_archive_loading_failed = false;
|
||||||
// Read/write a data stream for restoring/preserving metadata pointers and
|
// Read/write a data stream for restoring/preserving metadata pointers and
|
||||||
// miscellaneous data from/to the shared archive file.
|
// miscellaneous data from/to the shared archive file.
|
||||||
|
|
||||||
|
@ -446,6 +451,23 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||||
SystemDictionary::classes_do(collect_classes);
|
SystemDictionary::classes_do(collect_classes);
|
||||||
|
|
||||||
tty->print_cr("Number of classes %d", _global_klass_objects->length());
|
tty->print_cr("Number of classes %d", _global_klass_objects->length());
|
||||||
|
{
|
||||||
|
int num_type_array = 0, num_obj_array = 0, num_inst = 0;
|
||||||
|
for (int i = 0; i < _global_klass_objects->length(); i++) {
|
||||||
|
Klass* k = _global_klass_objects->at(i);
|
||||||
|
if (k->oop_is_instance()) {
|
||||||
|
num_inst ++;
|
||||||
|
} else if (k->oop_is_objArray()) {
|
||||||
|
num_obj_array ++;
|
||||||
|
} else {
|
||||||
|
assert(k->oop_is_typeArray(), "sanity");
|
||||||
|
num_type_array ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tty->print_cr(" instance classes = %5d", num_inst);
|
||||||
|
tty->print_cr(" obj array classes = %5d", num_obj_array);
|
||||||
|
tty->print_cr(" type array classes = %5d", num_type_array);
|
||||||
|
}
|
||||||
|
|
||||||
// Update all the fingerprints in the shared methods.
|
// Update all the fingerprints in the shared methods.
|
||||||
tty->print("Calculating fingerprints ... ");
|
tty->print("Calculating fingerprints ... ");
|
||||||
|
@ -611,38 +633,58 @@ void VM_PopulateDumpSharedSpace::doit() {
|
||||||
#undef fmt_space
|
#undef fmt_space
|
||||||
}
|
}
|
||||||
|
|
||||||
static void link_shared_classes(Klass* obj, TRAPS) {
|
|
||||||
|
void MetaspaceShared::link_one_shared_class(Klass* obj, TRAPS) {
|
||||||
Klass* k = obj;
|
Klass* k = obj;
|
||||||
if (k->oop_is_instance()) {
|
if (k->oop_is_instance()) {
|
||||||
InstanceKlass* ik = (InstanceKlass*) k;
|
InstanceKlass* ik = (InstanceKlass*) k;
|
||||||
// Link the class to cause the bytecodes to be rewritten and the
|
// Link the class to cause the bytecodes to be rewritten and the
|
||||||
// cpcache to be created.
|
// cpcache to be created. Class verification is done according
|
||||||
if (ik->init_state() < InstanceKlass::linked) {
|
// to -Xverify setting.
|
||||||
ik->link_class(THREAD);
|
_link_classes_made_progress |= try_link_class(ik, THREAD);
|
||||||
guarantee(!HAS_PENDING_EXCEPTION, "exception in class rewriting");
|
guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaspaceShared::check_one_shared_class(Klass* k) {
|
||||||
|
if (k->oop_is_instance() && InstanceKlass::cast(k)->check_sharing_error_state()) {
|
||||||
|
_check_classes_made_progress = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MetaspaceShared::link_and_cleanup_shared_classes(TRAPS) {
|
||||||
|
// We need to iterate because verification may cause additional classes
|
||||||
|
// to be loaded.
|
||||||
|
do {
|
||||||
|
_link_classes_made_progress = false;
|
||||||
|
SystemDictionary::classes_do(link_one_shared_class, THREAD);
|
||||||
|
guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class");
|
||||||
|
} while (_link_classes_made_progress);
|
||||||
|
|
||||||
|
if (_has_error_classes) {
|
||||||
|
// Mark all classes whose super class or interfaces failed verification.
|
||||||
|
do {
|
||||||
|
// Not completely sure if we need to do this iteratively. Anyway,
|
||||||
|
// we should come here only if there are unverifiable classes, which
|
||||||
|
// shouldn't happen in normal cases. So better safe than sorry.
|
||||||
|
_check_classes_made_progress = false;
|
||||||
|
SystemDictionary::classes_do(check_one_shared_class);
|
||||||
|
} while (_check_classes_made_progress);
|
||||||
|
|
||||||
|
if (IgnoreUnverifiableClassesDuringDump) {
|
||||||
|
// This is useful when running JCK or SQE tests. You should not
|
||||||
|
// enable this when running real apps.
|
||||||
|
SystemDictionary::remove_classes_in_error_state();
|
||||||
|
} else {
|
||||||
|
tty->print_cr("Please remove the unverifiable classes from your class list and try again");
|
||||||
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MetaspaceShared::prepare_for_dumping() {
|
||||||
// Support for a simple checksum of the contents of the class list
|
ClassLoader::initialize_shared_path();
|
||||||
// file to prevent trivial tampering. The algorithm matches that in
|
FileMapInfo::allocate_classpath_entry_table();
|
||||||
// the MakeClassList program used by the J2SE build process.
|
|
||||||
#define JSUM_SEED ((jlong)CONST64(0xcafebabebabecafe))
|
|
||||||
static jlong
|
|
||||||
jsum(jlong start, const char *buf, const int len)
|
|
||||||
{
|
|
||||||
jlong h = start;
|
|
||||||
char *p = (char *)buf, *e = p + len;
|
|
||||||
while (p < e) {
|
|
||||||
char c = *p++;
|
|
||||||
if (c <= ' ') {
|
|
||||||
/* Skip spaces and control characters */
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
h = 31 * h + c;
|
|
||||||
}
|
|
||||||
return h;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Preload classes from a list, populate the shared spaces and dump to a
|
// Preload classes from a list, populate the shared spaces and dump to a
|
||||||
|
@ -651,33 +693,37 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
|
||||||
TraceTime timer("Dump Shared Spaces", TraceStartupTime);
|
TraceTime timer("Dump Shared Spaces", TraceStartupTime);
|
||||||
ResourceMark rm;
|
ResourceMark rm;
|
||||||
|
|
||||||
|
tty->print_cr("Allocated shared space: %d bytes at " PTR_FORMAT,
|
||||||
|
MetaspaceShared::shared_rs()->size(),
|
||||||
|
MetaspaceShared::shared_rs()->base());
|
||||||
|
|
||||||
// Preload classes to be shared.
|
// Preload classes to be shared.
|
||||||
// Should use some os:: method rather than fopen() here. aB.
|
// Should use some os:: method rather than fopen() here. aB.
|
||||||
|
const char* class_list_path;
|
||||||
|
if (SharedClassListFile == NULL) {
|
||||||
// Construct the path to the class list (in jre/lib)
|
// Construct the path to the class list (in jre/lib)
|
||||||
// Walk up two directories from the location of the VM and
|
// Walk up two directories from the location of the VM and
|
||||||
// optionally tack on "lib" (depending on platform)
|
// optionally tack on "lib" (depending on platform)
|
||||||
char class_list_path[JVM_MAXPATHLEN];
|
char class_list_path_str[JVM_MAXPATHLEN];
|
||||||
os::jvm_path(class_list_path, sizeof(class_list_path));
|
os::jvm_path(class_list_path_str, sizeof(class_list_path_str));
|
||||||
for (int i = 0; i < 3; i++) {
|
for (int i = 0; i < 3; i++) {
|
||||||
char *end = strrchr(class_list_path, *os::file_separator());
|
char *end = strrchr(class_list_path_str, *os::file_separator());
|
||||||
if (end != NULL) *end = '\0';
|
if (end != NULL) *end = '\0';
|
||||||
}
|
}
|
||||||
int class_list_path_len = (int)strlen(class_list_path);
|
int class_list_path_len = (int)strlen(class_list_path_str);
|
||||||
if (class_list_path_len >= 3) {
|
if (class_list_path_len >= 3) {
|
||||||
if (strcmp(class_list_path + class_list_path_len - 3, "lib") != 0) {
|
if (strcmp(class_list_path_str + class_list_path_len - 3, "lib") != 0) {
|
||||||
strcat(class_list_path, os::file_separator());
|
strcat(class_list_path_str, os::file_separator());
|
||||||
strcat(class_list_path, "lib");
|
strcat(class_list_path_str, "lib");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
strcat(class_list_path, os::file_separator());
|
strcat(class_list_path_str, os::file_separator());
|
||||||
strcat(class_list_path, "classlist");
|
strcat(class_list_path_str, "classlist");
|
||||||
|
class_list_path = class_list_path_str;
|
||||||
|
} else {
|
||||||
|
class_list_path = SharedClassListFile;
|
||||||
|
}
|
||||||
|
|
||||||
FILE* file = fopen(class_list_path, "r");
|
|
||||||
if (file != NULL) {
|
|
||||||
jlong computed_jsum = JSUM_SEED;
|
|
||||||
jlong file_jsum = 0;
|
|
||||||
|
|
||||||
char class_name[256];
|
|
||||||
int class_count = 0;
|
int class_count = 0;
|
||||||
GrowableArray<Klass*>* class_promote_order = new GrowableArray<Klass*>();
|
GrowableArray<Klass*>* class_promote_order = new GrowableArray<Klass*>();
|
||||||
|
|
||||||
|
@ -689,34 +735,70 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
|
||||||
static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;";
|
static const char map_entry_array_sig[] = "[Ljava/util/Map$Entry;";
|
||||||
SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD);
|
SymbolTable::new_permanent_symbol(map_entry_array_sig, THREAD);
|
||||||
|
|
||||||
tty->print("Loading classes to share ... ");
|
tty->print_cr("Loading classes to share ...");
|
||||||
while ((fgets(class_name, sizeof class_name, file)) != NULL) {
|
_has_error_classes = false;
|
||||||
if (*class_name == '#') {
|
class_count += preload_and_dump(class_list_path, class_promote_order,
|
||||||
jint fsh, fsl;
|
THREAD);
|
||||||
if (sscanf(class_name, "# %8x%8x\n", &fsh, &fsl) == 2) {
|
if (ExtraSharedClassListFile) {
|
||||||
file_jsum = ((jlong)(fsh) << 32) | (fsl & 0xffffffff);
|
class_count += preload_and_dump(ExtraSharedClassListFile, class_promote_order,
|
||||||
|
THREAD);
|
||||||
|
}
|
||||||
|
tty->print_cr("Loading classes to share: done.");
|
||||||
|
|
||||||
|
if (PrintSharedSpaces) {
|
||||||
|
tty->print_cr("Shared spaces: preloaded %d classes", class_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Rewrite and link classes
|
||||||
|
tty->print_cr("Rewriting and linking classes ...");
|
||||||
|
|
||||||
|
// Link any classes which got missed. This would happen if we have loaded classes that
|
||||||
|
// were not explicitly specified in the classlist. E.g., if an interface implemented by class K
|
||||||
|
// fails verification, all other interfaces that were not specified in the classlist but
|
||||||
|
// are implemented by K are not verified.
|
||||||
|
link_and_cleanup_shared_classes(CATCH);
|
||||||
|
tty->print_cr("Rewriting and linking classes: done");
|
||||||
|
|
||||||
|
// Create and dump the shared spaces. Everything so far is loaded
|
||||||
|
// with the null class loader.
|
||||||
|
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
||||||
|
VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
|
||||||
|
VMThread::execute(&op);
|
||||||
|
|
||||||
|
// Since various initialization steps have been undone by this process,
|
||||||
|
// it is not reasonable to continue running a java process.
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int MetaspaceShared::preload_and_dump(const char * class_list_path,
|
||||||
|
GrowableArray<Klass*>* class_promote_order,
|
||||||
|
TRAPS) {
|
||||||
|
FILE* file = fopen(class_list_path, "r");
|
||||||
|
char class_name[256];
|
||||||
|
int class_count = 0;
|
||||||
|
|
||||||
|
if (file != NULL) {
|
||||||
|
while ((fgets(class_name, sizeof class_name, file)) != NULL) {
|
||||||
|
if (*class_name == '#') { // comment
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Remove trailing newline
|
// Remove trailing newline
|
||||||
size_t name_len = strlen(class_name);
|
size_t name_len = strlen(class_name);
|
||||||
|
if (class_name[name_len-1] == '\n') {
|
||||||
class_name[name_len-1] = '\0';
|
class_name[name_len-1] = '\0';
|
||||||
|
}
|
||||||
computed_jsum = jsum(computed_jsum, class_name, (const int)name_len - 1);
|
|
||||||
|
|
||||||
// Got a class name - load it.
|
// Got a class name - load it.
|
||||||
TempNewSymbol class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD);
|
TempNewSymbol class_name_symbol = SymbolTable::new_permanent_symbol(class_name, THREAD);
|
||||||
guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
|
guarantee(!HAS_PENDING_EXCEPTION, "Exception creating a symbol.");
|
||||||
Klass* klass = SystemDictionary::resolve_or_null(class_name_symbol,
|
Klass* klass = SystemDictionary::resolve_or_null(class_name_symbol,
|
||||||
THREAD);
|
THREAD);
|
||||||
guarantee(!HAS_PENDING_EXCEPTION, "Exception resolving a class.");
|
CLEAR_PENDING_EXCEPTION;
|
||||||
if (klass != NULL) {
|
if (klass != NULL) {
|
||||||
if (PrintSharedSpaces && Verbose && WizardMode) {
|
if (PrintSharedSpaces && Verbose && WizardMode) {
|
||||||
tty->print_cr("Shared spaces preloaded: %s", class_name);
|
tty->print_cr("Shared spaces preloaded: %s", class_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
InstanceKlass* ik = InstanceKlass::cast(klass);
|
InstanceKlass* ik = InstanceKlass::cast(klass);
|
||||||
|
|
||||||
// Should be class load order as per -XX:+TraceClassLoadingPreorder
|
// Should be class load order as per -XX:+TraceClassLoadingPreorder
|
||||||
|
@ -726,52 +808,14 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
|
||||||
// cpcache to be created. The linking is done as soon as classes
|
// cpcache to be created. The linking is done as soon as classes
|
||||||
// are loaded in order that the related data structures (klass and
|
// are loaded in order that the related data structures (klass and
|
||||||
// cpCache) are located together.
|
// cpCache) are located together.
|
||||||
|
try_link_class(ik, THREAD);
|
||||||
if (ik->init_state() < InstanceKlass::linked) {
|
guarantee(!HAS_PENDING_EXCEPTION, "exception in link_class");
|
||||||
ik->link_class(THREAD);
|
|
||||||
guarantee(!(HAS_PENDING_EXCEPTION), "exception in class rewriting");
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Resolve klasses in constant pool
|
|
||||||
ik->constants()->resolve_class_constants(THREAD);
|
|
||||||
|
|
||||||
class_count++;
|
class_count++;
|
||||||
} else {
|
} else {
|
||||||
if (PrintSharedSpaces && Verbose && WizardMode) {
|
//tty->print_cr("Preload failed: %s", class_name);
|
||||||
tty->cr();
|
|
||||||
tty->print_cr(" Preload failed: %s", class_name);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
file_jsum = 0; // Checksum must be on last line of file
|
|
||||||
}
|
|
||||||
if (computed_jsum != file_jsum) {
|
|
||||||
tty->cr();
|
|
||||||
tty->print_cr("Preload failed: checksum of class list was incorrect.");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
tty->print_cr("done. ");
|
|
||||||
|
|
||||||
if (PrintSharedSpaces) {
|
|
||||||
tty->print_cr("Shared spaces: preloaded %d classes", class_count);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rewrite and unlink classes.
|
|
||||||
tty->print("Rewriting and linking classes ... ");
|
|
||||||
|
|
||||||
// Link any classes which got missed. (It's not quite clear why
|
|
||||||
// they got missed.) This iteration would be unsafe if we weren't
|
|
||||||
// single-threaded at this point; however we can't do it on the VM
|
|
||||||
// thread because it requires object allocation.
|
|
||||||
SystemDictionary::classes_do(link_shared_classes, CATCH);
|
|
||||||
tty->print_cr("done. ");
|
|
||||||
|
|
||||||
// Create and dump the shared spaces. Everything so far is loaded
|
|
||||||
// with the null class loader.
|
|
||||||
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
|
||||||
VM_PopulateDumpSharedSpace op(loader_data, class_promote_order);
|
|
||||||
VMThread::execute(&op);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
char errmsg[JVM_MAXPATHLEN];
|
char errmsg[JVM_MAXPATHLEN];
|
||||||
os::lasterror(errmsg, JVM_MAXPATHLEN);
|
os::lasterror(errmsg, JVM_MAXPATHLEN);
|
||||||
|
@ -779,11 +823,39 @@ void MetaspaceShared::preload_and_dump(TRAPS) {
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since various initialization steps have been undone by this process,
|
return class_count;
|
||||||
// it is not reasonable to continue running a java process.
|
|
||||||
exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Returns true if the class's status has changed
|
||||||
|
bool MetaspaceShared::try_link_class(InstanceKlass* ik, TRAPS) {
|
||||||
|
assert(DumpSharedSpaces, "should only be called during dumping");
|
||||||
|
if (ik->init_state() < InstanceKlass::linked) {
|
||||||
|
bool saved = BytecodeVerificationLocal;
|
||||||
|
if (!SharedClassUtil::is_shared_boot_class(ik)) {
|
||||||
|
// The verification decision is based on BytecodeVerificationRemote
|
||||||
|
// for non-system classes. Since we are using the NULL classloader
|
||||||
|
// to load non-system classes during dumping, we need to temporarily
|
||||||
|
// change BytecodeVerificationLocal to be the same as
|
||||||
|
// BytecodeVerificationRemote. Note this can cause the parent system
|
||||||
|
// classes also being verified. The extra overhead is acceptable during
|
||||||
|
// dumping.
|
||||||
|
BytecodeVerificationLocal = BytecodeVerificationRemote;
|
||||||
|
}
|
||||||
|
ik->link_class(THREAD);
|
||||||
|
if (HAS_PENDING_EXCEPTION) {
|
||||||
|
ResourceMark rm;
|
||||||
|
tty->print_cr("Preload Error: Verification failed for %s",
|
||||||
|
ik->external_name());
|
||||||
|
CLEAR_PENDING_EXCEPTION;
|
||||||
|
ik->set_in_error_state();
|
||||||
|
_has_error_classes = true;
|
||||||
|
}
|
||||||
|
BytecodeVerificationLocal = saved;
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Closure for serializing initialization data in from a data area
|
// Closure for serializing initialization data in from a data area
|
||||||
// (ptr_array) read from the shared file.
|
// (ptr_array) read from the shared file.
|
||||||
|
@ -867,7 +939,8 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
|
||||||
(_rw_base = mapinfo->map_region(rw)) != NULL &&
|
(_rw_base = mapinfo->map_region(rw)) != NULL &&
|
||||||
(_md_base = mapinfo->map_region(md)) != NULL &&
|
(_md_base = mapinfo->map_region(md)) != NULL &&
|
||||||
(_mc_base = mapinfo->map_region(mc)) != NULL &&
|
(_mc_base = mapinfo->map_region(mc)) != NULL &&
|
||||||
(image_alignment == (size_t)max_alignment())) {
|
(image_alignment == (size_t)max_alignment()) &&
|
||||||
|
mapinfo->validate_classpath_entry_table()) {
|
||||||
// Success (no need to do anything)
|
// Success (no need to do anything)
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
|
@ -884,7 +957,7 @@ bool MetaspaceShared::map_shared_spaces(FileMapInfo* mapinfo) {
|
||||||
// If -Xshare:on is specified, print out the error message and exit VM,
|
// If -Xshare:on is specified, print out the error message and exit VM,
|
||||||
// otherwise, set UseSharedSpaces to false and continue.
|
// otherwise, set UseSharedSpaces to false and continue.
|
||||||
if (RequireSharedSpaces) {
|
if (RequireSharedSpaces) {
|
||||||
vm_exit_during_initialization("Unable to use shared archive.", NULL);
|
vm_exit_during_initialization("Unable to use shared archive.", "Failed map_region for using -Xshare:on.");
|
||||||
} else {
|
} else {
|
||||||
FLAG_SET_DEFAULT(UseSharedSpaces, false);
|
FLAG_SET_DEFAULT(UseSharedSpaces, false);
|
||||||
}
|
}
|
||||||
|
@ -984,6 +1057,20 @@ void MetaspaceShared::initialize_shared_spaces() {
|
||||||
|
|
||||||
// Close the mapinfo file
|
// Close the mapinfo file
|
||||||
mapinfo->close();
|
mapinfo->close();
|
||||||
|
|
||||||
|
if (PrintSharedArchiveAndExit) {
|
||||||
|
if (PrintSharedDictionary) {
|
||||||
|
tty->print_cr("\nShared classes:\n");
|
||||||
|
SystemDictionary::print_shared(false);
|
||||||
|
}
|
||||||
|
if (_archive_loading_failed) {
|
||||||
|
tty->print_cr("archive is invalid");
|
||||||
|
vm_exit(1);
|
||||||
|
} else {
|
||||||
|
tty->print_cr("archive is valid");
|
||||||
|
vm_exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// JVM/TI RedefineClasses() support:
|
// JVM/TI RedefineClasses() support:
|
||||||
|
|
|
@ -38,7 +38,10 @@ class MetaspaceShared : AllStatic {
|
||||||
// CDS support
|
// CDS support
|
||||||
static ReservedSpace* _shared_rs;
|
static ReservedSpace* _shared_rs;
|
||||||
static int _max_alignment;
|
static int _max_alignment;
|
||||||
|
static bool _link_classes_made_progress;
|
||||||
|
static bool _check_classes_made_progress;
|
||||||
|
static bool _has_error_classes;
|
||||||
|
static bool _archive_loading_failed;
|
||||||
public:
|
public:
|
||||||
enum {
|
enum {
|
||||||
vtbl_list_size = 17, // number of entries in the shared space vtable list.
|
vtbl_list_size = 17, // number of entries in the shared space vtable list.
|
||||||
|
@ -67,7 +70,11 @@ class MetaspaceShared : AllStatic {
|
||||||
NOT_CDS(return 0);
|
NOT_CDS(return 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void prepare_for_dumping() NOT_CDS_RETURN;
|
||||||
static void preload_and_dump(TRAPS) NOT_CDS_RETURN;
|
static void preload_and_dump(TRAPS) NOT_CDS_RETURN;
|
||||||
|
static int preload_and_dump(const char * class_list_path,
|
||||||
|
GrowableArray<Klass*>* class_promote_order,
|
||||||
|
TRAPS) NOT_CDS_RETURN;
|
||||||
|
|
||||||
static ReservedSpace* shared_rs() {
|
static ReservedSpace* shared_rs() {
|
||||||
CDS_ONLY(return _shared_rs);
|
CDS_ONLY(return _shared_rs);
|
||||||
|
@ -78,6 +85,9 @@ class MetaspaceShared : AllStatic {
|
||||||
CDS_ONLY(_shared_rs = rs;)
|
CDS_ONLY(_shared_rs = rs;)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void set_archive_loading_failed() {
|
||||||
|
_archive_loading_failed = true;
|
||||||
|
}
|
||||||
static bool map_shared_spaces(FileMapInfo* mapinfo) NOT_CDS_RETURN_(false);
|
static bool map_shared_spaces(FileMapInfo* mapinfo) NOT_CDS_RETURN_(false);
|
||||||
static void initialize_shared_spaces() NOT_CDS_RETURN;
|
static void initialize_shared_spaces() NOT_CDS_RETURN;
|
||||||
|
|
||||||
|
@ -97,5 +107,10 @@ class MetaspaceShared : AllStatic {
|
||||||
static bool remap_shared_readonly_as_readwrite() NOT_CDS_RETURN_(true);
|
static bool remap_shared_readonly_as_readwrite() NOT_CDS_RETURN_(true);
|
||||||
|
|
||||||
static void print_shared_spaces();
|
static void print_shared_spaces();
|
||||||
|
|
||||||
|
static bool try_link_class(InstanceKlass* ik, TRAPS);
|
||||||
|
static void link_one_shared_class(Klass* obj, TRAPS);
|
||||||
|
static void check_one_shared_class(Klass* obj);
|
||||||
|
static void link_and_cleanup_shared_classes(TRAPS);
|
||||||
};
|
};
|
||||||
#endif // SHARE_VM_MEMORY_METASPACE_SHARED_HPP
|
#endif // SHARE_VM_MEMORY_METASPACE_SHARED_HPP
|
||||||
|
|
|
@ -26,6 +26,9 @@
|
||||||
#include "classfile/classLoader.hpp"
|
#include "classfile/classLoader.hpp"
|
||||||
#include "classfile/classLoaderData.hpp"
|
#include "classfile/classLoaderData.hpp"
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
#include "classfile/sharedClassUtil.hpp"
|
||||||
|
#endif
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
|
@ -34,6 +37,7 @@
|
||||||
#include "gc_interface/collectedHeap.inline.hpp"
|
#include "gc_interface/collectedHeap.inline.hpp"
|
||||||
#include "interpreter/interpreter.hpp"
|
#include "interpreter/interpreter.hpp"
|
||||||
#include "memory/cardTableModRefBS.hpp"
|
#include "memory/cardTableModRefBS.hpp"
|
||||||
|
#include "memory/filemap.hpp"
|
||||||
#include "memory/gcLocker.inline.hpp"
|
#include "memory/gcLocker.inline.hpp"
|
||||||
#include "memory/genCollectedHeap.hpp"
|
#include "memory/genCollectedHeap.hpp"
|
||||||
#include "memory/genRemSet.hpp"
|
#include "memory/genRemSet.hpp"
|
||||||
|
@ -239,8 +243,9 @@ void Universe::check_alignment(uintx size, uintx alignment, const char* name) {
|
||||||
void initialize_basic_type_klass(Klass* k, TRAPS) {
|
void initialize_basic_type_klass(Klass* k, TRAPS) {
|
||||||
Klass* ok = SystemDictionary::Object_klass();
|
Klass* ok = SystemDictionary::Object_klass();
|
||||||
if (UseSharedSpaces) {
|
if (UseSharedSpaces) {
|
||||||
|
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
||||||
assert(k->super() == ok, "u3");
|
assert(k->super() == ok, "u3");
|
||||||
k->restore_unshareable_info(CHECK);
|
k->restore_unshareable_info(loader_data, Handle(), CHECK);
|
||||||
} else {
|
} else {
|
||||||
k->initialize_supers(ok, CHECK);
|
k->initialize_supers(ok, CHECK);
|
||||||
}
|
}
|
||||||
|
@ -666,6 +671,10 @@ jint universe_init() {
|
||||||
SymbolTable::create_table();
|
SymbolTable::create_table();
|
||||||
StringTable::create_table();
|
StringTable::create_table();
|
||||||
ClassLoader::create_package_info_table();
|
ClassLoader::create_package_info_table();
|
||||||
|
|
||||||
|
if (DumpSharedSpaces) {
|
||||||
|
MetaspaceShared::prepare_for_dumping();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return JNI_OK;
|
return JNI_OK;
|
||||||
|
@ -1155,6 +1164,11 @@ bool universe_post_init() {
|
||||||
MemoryService::add_metaspace_memory_pools();
|
MemoryService::add_metaspace_memory_pools();
|
||||||
|
|
||||||
MemoryService::set_universe_heap(Universe::_collectedHeap);
|
MemoryService::set_universe_heap(Universe::_collectedHeap);
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
if (UseSharedSpaces) {
|
||||||
|
SharedClassUtil::initialize(CHECK_false);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -186,8 +186,9 @@ void ArrayKlass::remove_unshareable_info() {
|
||||||
set_component_mirror(NULL);
|
set_component_mirror(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ArrayKlass::restore_unshareable_info(TRAPS) {
|
void ArrayKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
|
||||||
Klass::restore_unshareable_info(CHECK);
|
assert(loader_data == ClassLoaderData::the_null_class_loader_data(), "array classes belong to null loader");
|
||||||
|
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
|
||||||
// Klass recreates the component mirror also
|
// Klass recreates the component mirror also
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -137,7 +137,7 @@ class ArrayKlass: public Klass {
|
||||||
|
|
||||||
// CDS support - remove and restore oops from metadata. Oops are not shared.
|
// CDS support - remove and restore oops from metadata. Oops are not shared.
|
||||||
virtual void remove_unshareable_info();
|
virtual void remove_unshareable_info();
|
||||||
virtual void restore_unshareable_info(TRAPS);
|
virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS);
|
||||||
|
|
||||||
// Printing
|
// Printing
|
||||||
void print_on(outputStream* st) const;
|
void print_on(outputStream* st) const;
|
||||||
|
|
|
@ -2303,12 +2303,14 @@ void InstanceKlass::remove_unshareable_info() {
|
||||||
array_klasses_do(remove_unshareable_in_class);
|
array_klasses_do(remove_unshareable_in_class);
|
||||||
}
|
}
|
||||||
|
|
||||||
void restore_unshareable_in_class(Klass* k, TRAPS) {
|
static void restore_unshareable_in_class(Klass* k, TRAPS) {
|
||||||
k->restore_unshareable_info(CHECK);
|
// Array classes have null protection domain.
|
||||||
|
// --> see ArrayKlass::complete_create_array_klass()
|
||||||
|
k->restore_unshareable_info(ClassLoaderData::the_null_class_loader_data(), Handle(), CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
void InstanceKlass::restore_unshareable_info(TRAPS) {
|
void InstanceKlass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
|
||||||
Klass::restore_unshareable_info(CHECK);
|
Klass::restore_unshareable_info(loader_data, protection_domain, CHECK);
|
||||||
instanceKlassHandle ik(THREAD, this);
|
instanceKlassHandle ik(THREAD, this);
|
||||||
|
|
||||||
Array<Method*>* methods = ik->methods();
|
Array<Method*>* methods = ik->methods();
|
||||||
|
@ -2334,6 +2336,38 @@ void InstanceKlass::restore_unshareable_info(TRAPS) {
|
||||||
ik->array_klasses_do(restore_unshareable_in_class, CHECK);
|
ik->array_klasses_do(restore_unshareable_in_class, CHECK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// returns true IFF is_in_error_state() has been changed as a result of this call.
|
||||||
|
bool InstanceKlass::check_sharing_error_state() {
|
||||||
|
assert(DumpSharedSpaces, "should only be called during dumping");
|
||||||
|
bool old_state = is_in_error_state();
|
||||||
|
|
||||||
|
if (!is_in_error_state()) {
|
||||||
|
bool bad = false;
|
||||||
|
for (InstanceKlass* sup = java_super(); sup; sup = sup->java_super()) {
|
||||||
|
if (sup->is_in_error_state()) {
|
||||||
|
bad = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!bad) {
|
||||||
|
Array<Klass*>* interfaces = transitive_interfaces();
|
||||||
|
for (int i = 0; i < interfaces->length(); i++) {
|
||||||
|
Klass* iface = interfaces->at(i);
|
||||||
|
if (InstanceKlass::cast(iface)->is_in_error_state()) {
|
||||||
|
bad = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bad) {
|
||||||
|
set_in_error_state();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (old_state != is_in_error_state());
|
||||||
|
}
|
||||||
|
|
||||||
static void clear_all_breakpoints(Method* m) {
|
static void clear_all_breakpoints(Method* m) {
|
||||||
m->clear_all_breakpoints();
|
m->clear_all_breakpoints();
|
||||||
}
|
}
|
||||||
|
|
|
@ -980,6 +980,13 @@ class InstanceKlass: public Klass {
|
||||||
|
|
||||||
u2 idnum_allocated_count() const { return _idnum_allocated_count; }
|
u2 idnum_allocated_count() const { return _idnum_allocated_count; }
|
||||||
|
|
||||||
|
public:
|
||||||
|
void set_in_error_state() {
|
||||||
|
assert(DumpSharedSpaces, "only call this when dumping archive");
|
||||||
|
_init_state = initialization_error;
|
||||||
|
}
|
||||||
|
bool check_sharing_error_state();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// initialization state
|
// initialization state
|
||||||
#ifdef ASSERT
|
#ifdef ASSERT
|
||||||
|
@ -1038,7 +1045,7 @@ private:
|
||||||
public:
|
public:
|
||||||
// CDS support - remove and restore oops from metadata. Oops are not shared.
|
// CDS support - remove and restore oops from metadata. Oops are not shared.
|
||||||
virtual void remove_unshareable_info();
|
virtual void remove_unshareable_info();
|
||||||
virtual void restore_unshareable_info(TRAPS);
|
virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS);
|
||||||
|
|
||||||
// jvm support
|
// jvm support
|
||||||
jint compute_modifier_flags(TRAPS) const;
|
jint compute_modifier_flags(TRAPS) const;
|
||||||
|
|
|
@ -184,6 +184,7 @@ Klass::Klass() {
|
||||||
// The klass doesn't have any references at this point.
|
// The klass doesn't have any references at this point.
|
||||||
clear_modified_oops();
|
clear_modified_oops();
|
||||||
clear_accumulated_modified_oops();
|
clear_accumulated_modified_oops();
|
||||||
|
_shared_class_path_index = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
jint Klass::array_layout_helper(BasicType etype) {
|
jint Klass::array_layout_helper(BasicType etype) {
|
||||||
|
@ -500,13 +501,12 @@ void Klass::remove_unshareable_info() {
|
||||||
set_class_loader_data(NULL);
|
set_class_loader_data(NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Klass::restore_unshareable_info(TRAPS) {
|
void Klass::restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
|
||||||
TRACE_INIT_ID(this);
|
TRACE_INIT_ID(this);
|
||||||
// If an exception happened during CDS restore, some of these fields may already be
|
// If an exception happened during CDS restore, some of these fields may already be
|
||||||
// set. We leave the class on the CLD list, even if incomplete so that we don't
|
// set. We leave the class on the CLD list, even if incomplete so that we don't
|
||||||
// modify the CLD list outside a safepoint.
|
// modify the CLD list outside a safepoint.
|
||||||
if (class_loader_data() == NULL) {
|
if (class_loader_data() == NULL) {
|
||||||
ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
|
|
||||||
// Restore class_loader_data to the null class loader data
|
// Restore class_loader_data to the null class loader data
|
||||||
set_class_loader_data(loader_data);
|
set_class_loader_data(loader_data);
|
||||||
|
|
||||||
|
@ -515,12 +515,12 @@ void Klass::restore_unshareable_info(TRAPS) {
|
||||||
loader_data->add_class(this);
|
loader_data->add_class(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Recreate the class mirror. The protection_domain is always null for
|
// Recreate the class mirror.
|
||||||
// boot loader, for now.
|
|
||||||
// Only recreate it if not present. A previous attempt to restore may have
|
// Only recreate it if not present. A previous attempt to restore may have
|
||||||
// gotten an OOM later but keep the mirror if it was created.
|
// gotten an OOM later but keep the mirror if it was created.
|
||||||
if (java_mirror() == NULL) {
|
if (java_mirror() == NULL) {
|
||||||
java_lang_Class::create_mirror(this, Handle(NULL), Handle(NULL), CHECK);
|
Handle loader = loader_data->class_loader();
|
||||||
|
java_lang_Class::create_mirror(this, loader, protection_domain, CHECK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,16 @@ class Klass : public Metadata {
|
||||||
jbyte _modified_oops; // Card Table Equivalent (YC/CMS support)
|
jbyte _modified_oops; // Card Table Equivalent (YC/CMS support)
|
||||||
jbyte _accumulated_modified_oops; // Mod Union Equivalent (CMS support)
|
jbyte _accumulated_modified_oops; // Mod Union Equivalent (CMS support)
|
||||||
|
|
||||||
|
private:
|
||||||
|
// This is an index into FileMapHeader::_classpath_entry_table[], to
|
||||||
|
// associate this class with the JAR file where it's loaded from during
|
||||||
|
// dump time. If a class is not loaded from the shared archive, this field is
|
||||||
|
// -1.
|
||||||
|
jshort _shared_class_path_index;
|
||||||
|
|
||||||
|
friend class SharedClassUtil;
|
||||||
|
protected:
|
||||||
|
|
||||||
// Constructor
|
// Constructor
|
||||||
Klass();
|
Klass();
|
||||||
|
|
||||||
|
@ -253,6 +263,15 @@ class Klass : public Metadata {
|
||||||
void clear_accumulated_modified_oops() { _accumulated_modified_oops = 0; }
|
void clear_accumulated_modified_oops() { _accumulated_modified_oops = 0; }
|
||||||
bool has_accumulated_modified_oops() { return _accumulated_modified_oops == 1; }
|
bool has_accumulated_modified_oops() { return _accumulated_modified_oops == 1; }
|
||||||
|
|
||||||
|
int shared_classpath_index() const {
|
||||||
|
return _shared_class_path_index;
|
||||||
|
};
|
||||||
|
|
||||||
|
void set_shared_classpath_index(int index) {
|
||||||
|
_shared_class_path_index = index;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
protected: // internal accessors
|
protected: // internal accessors
|
||||||
void set_subklass(Klass* s);
|
void set_subklass(Klass* s);
|
||||||
void set_next_sibling(Klass* s);
|
void set_next_sibling(Klass* s);
|
||||||
|
@ -422,7 +441,7 @@ class Klass : public Metadata {
|
||||||
public:
|
public:
|
||||||
// CDS support - remove and restore oops from metadata. Oops are not shared.
|
// CDS support - remove and restore oops from metadata. Oops are not shared.
|
||||||
virtual void remove_unshareable_info();
|
virtual void remove_unshareable_info();
|
||||||
virtual void restore_unshareable_info(TRAPS);
|
virtual void restore_unshareable_info(ClassLoaderData* loader_data, Handle protection_domain, TRAPS);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// computes the subtype relationship
|
// computes the subtype relationship
|
||||||
|
|
|
@ -28,6 +28,10 @@
|
||||||
#include "classfile/javaClasses.hpp"
|
#include "classfile/javaClasses.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/systemDictionary.hpp"
|
#include "classfile/systemDictionary.hpp"
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
#include "classfile/sharedClassUtil.hpp"
|
||||||
|
#include "classfile/systemDictionaryShared.hpp"
|
||||||
|
#endif
|
||||||
#include "classfile/vmSymbols.hpp"
|
#include "classfile/vmSymbols.hpp"
|
||||||
#include "gc_interface/collectedHeap.inline.hpp"
|
#include "gc_interface/collectedHeap.inline.hpp"
|
||||||
#include "interpreter/bytecode.hpp"
|
#include "interpreter/bytecode.hpp"
|
||||||
|
@ -993,7 +997,15 @@ JVM_ENTRY(jclass, JVM_FindLoadedClass(JNIEnv *env, jobject loader, jstring name)
|
||||||
h_loader,
|
h_loader,
|
||||||
Handle(),
|
Handle(),
|
||||||
CHECK_NULL);
|
CHECK_NULL);
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
if (k == NULL) {
|
||||||
|
// If the class is not already loaded, try to see if it's in the shared
|
||||||
|
// archive for the current classloader (h_loader).
|
||||||
|
instanceKlassHandle ik = SystemDictionaryShared::find_or_load_shared_class(
|
||||||
|
klass_name, h_loader, CHECK_NULL);
|
||||||
|
k = ik();
|
||||||
|
}
|
||||||
|
#endif
|
||||||
return (k == NULL) ? NULL :
|
return (k == NULL) ? NULL :
|
||||||
(jclass) JNIHandles::make_local(env, k->java_mirror());
|
(jclass) JNIHandles::make_local(env, k->java_mirror());
|
||||||
JVM_END
|
JVM_END
|
||||||
|
|
|
@ -601,6 +601,15 @@ WB_ENTRY(jobject, WB_GetUint64VMFlag(JNIEnv* env, jobject o, jstring name))
|
||||||
return NULL;
|
return NULL;
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(jobject, WB_GetSizeTVMFlag(JNIEnv* env, jobject o, jstring name))
|
||||||
|
uintx result;
|
||||||
|
if (GetVMFlag <size_t> (thread, env, name, &result, &CommandLineFlags::size_tAt)) {
|
||||||
|
ThreadToNativeFromVM ttnfv(thread); // can't be in VM when we call JNI
|
||||||
|
return longBox(thread, env, result);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
|
WB_ENTRY(jobject, WB_GetDoubleVMFlag(JNIEnv* env, jobject o, jstring name))
|
||||||
double result;
|
double result;
|
||||||
if (GetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAt)) {
|
if (GetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAt)) {
|
||||||
|
@ -641,6 +650,11 @@ WB_ENTRY(void, WB_SetUint64VMFlag(JNIEnv* env, jobject o, jstring name, jlong va
|
||||||
SetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAtPut);
|
SetVMFlag <uint64_t> (thread, env, name, &result, &CommandLineFlags::uint64_tAtPut);
|
||||||
WB_END
|
WB_END
|
||||||
|
|
||||||
|
WB_ENTRY(void, WB_SetSizeTVMFlag(JNIEnv* env, jobject o, jstring name, jlong value))
|
||||||
|
size_t result = value;
|
||||||
|
SetVMFlag <size_t> (thread, env, name, &result, &CommandLineFlags::size_tAtPut);
|
||||||
|
WB_END
|
||||||
|
|
||||||
WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
|
WB_ENTRY(void, WB_SetDoubleVMFlag(JNIEnv* env, jobject o, jstring name, jdouble value))
|
||||||
double result = value;
|
double result = value;
|
||||||
SetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAtPut);
|
SetVMFlag <double> (thread, env, name, &result, &CommandLineFlags::doubleAtPut);
|
||||||
|
@ -885,6 +899,7 @@ static JNINativeMethod methods[] = {
|
||||||
{CC"setIntxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
|
{CC"setIntxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetIntxVMFlag},
|
||||||
{CC"setUintxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
|
{CC"setUintxVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUintxVMFlag},
|
||||||
{CC"setUint64VMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
|
{CC"setUint64VMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetUint64VMFlag},
|
||||||
|
{CC"setSizeTVMFlag", CC"(Ljava/lang/String;J)V",(void*)&WB_SetSizeTVMFlag},
|
||||||
{CC"setDoubleVMFlag", CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
|
{CC"setDoubleVMFlag", CC"(Ljava/lang/String;D)V",(void*)&WB_SetDoubleVMFlag},
|
||||||
{CC"setStringVMFlag", CC"(Ljava/lang/String;Ljava/lang/String;)V",
|
{CC"setStringVMFlag", CC"(Ljava/lang/String;Ljava/lang/String;)V",
|
||||||
(void*)&WB_SetStringVMFlag},
|
(void*)&WB_SetStringVMFlag},
|
||||||
|
@ -896,6 +911,8 @@ static JNINativeMethod methods[] = {
|
||||||
(void*)&WB_GetUintxVMFlag},
|
(void*)&WB_GetUintxVMFlag},
|
||||||
{CC"getUint64VMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
|
{CC"getUint64VMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
|
||||||
(void*)&WB_GetUint64VMFlag},
|
(void*)&WB_GetUint64VMFlag},
|
||||||
|
{CC"getSizeTVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Long;",
|
||||||
|
(void*)&WB_GetSizeTVMFlag},
|
||||||
{CC"getDoubleVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Double;",
|
{CC"getDoubleVMFlag", CC"(Ljava/lang/String;)Ljava/lang/Double;",
|
||||||
(void*)&WB_GetDoubleVMFlag},
|
(void*)&WB_GetDoubleVMFlag},
|
||||||
{CC"getStringVMFlag", CC"(Ljava/lang/String;)Ljava/lang/String;",
|
{CC"getStringVMFlag", CC"(Ljava/lang/String;)Ljava/lang/String;",
|
||||||
|
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "precompiled.hpp"
|
#include "precompiled.hpp"
|
||||||
|
#include "classfile/classLoader.hpp"
|
||||||
#include "classfile/javaAssertions.hpp"
|
#include "classfile/javaAssertions.hpp"
|
||||||
#include "classfile/stringTable.hpp"
|
#include "classfile/stringTable.hpp"
|
||||||
#include "classfile/symbolTable.hpp"
|
#include "classfile/symbolTable.hpp"
|
||||||
|
@ -43,6 +44,7 @@
|
||||||
#include "services/memTracker.hpp"
|
#include "services/memTracker.hpp"
|
||||||
#include "utilities/defaultStream.hpp"
|
#include "utilities/defaultStream.hpp"
|
||||||
#include "utilities/macros.hpp"
|
#include "utilities/macros.hpp"
|
||||||
|
#include "utilities/stringUtils.hpp"
|
||||||
#include "utilities/taskqueue.hpp"
|
#include "utilities/taskqueue.hpp"
|
||||||
#if INCLUDE_ALL_GCS
|
#if INCLUDE_ALL_GCS
|
||||||
#include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
|
#include "gc_implementation/concurrentMarkSweep/compactibleFreeListSpace.hpp"
|
||||||
|
@ -691,6 +693,10 @@ static bool set_numeric_flag(char* name, char* value, Flag::Flags origin) {
|
||||||
if (!is_neg && CommandLineFlags::uint64_tAtPut(name, &uint64_t_v, origin)) {
|
if (!is_neg && CommandLineFlags::uint64_tAtPut(name, &uint64_t_v, origin)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
size_t size_t_v = (size_t) v;
|
||||||
|
if (!is_neg && CommandLineFlags::size_tAtPut(name, &size_t_v, origin)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1115,11 +1121,11 @@ void Arguments::set_mode_flags(Mode mode) {
|
||||||
// Conflict: required to use shared spaces (-Xshare:on), but
|
// Conflict: required to use shared spaces (-Xshare:on), but
|
||||||
// incompatible command line options were chosen.
|
// incompatible command line options were chosen.
|
||||||
|
|
||||||
static void no_shared_spaces() {
|
static void no_shared_spaces(const char* message) {
|
||||||
if (RequireSharedSpaces) {
|
if (RequireSharedSpaces) {
|
||||||
jio_fprintf(defaultStream::error_stream(),
|
jio_fprintf(defaultStream::error_stream(),
|
||||||
"Class data sharing is inconsistent with other specified options.\n");
|
"Class data sharing is inconsistent with other specified options.\n");
|
||||||
vm_exit_during_initialization("Unable to use shared archive.", NULL);
|
vm_exit_during_initialization("Unable to use shared archive.", message);
|
||||||
} else {
|
} else {
|
||||||
FLAG_SET_DEFAULT(UseSharedSpaces, false);
|
FLAG_SET_DEFAULT(UseSharedSpaces, false);
|
||||||
}
|
}
|
||||||
|
@ -1581,7 +1587,7 @@ void Arguments::set_ergonomics_flags() {
|
||||||
// at link time, or rewrite bytecodes in non-shared methods.
|
// at link time, or rewrite bytecodes in non-shared methods.
|
||||||
if (!DumpSharedSpaces && !RequireSharedSpaces &&
|
if (!DumpSharedSpaces && !RequireSharedSpaces &&
|
||||||
(FLAG_IS_DEFAULT(UseSharedSpaces) || !UseSharedSpaces)) {
|
(FLAG_IS_DEFAULT(UseSharedSpaces) || !UseSharedSpaces)) {
|
||||||
no_shared_spaces();
|
no_shared_spaces("COMPILER2 default: -Xshare:auto | off, have to manually setup to on.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -3302,6 +3308,15 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PrintSharedArchiveAndExit will turn on
|
||||||
|
// -Xshare:on
|
||||||
|
// -XX:+TraceClassPaths
|
||||||
|
if (PrintSharedArchiveAndExit) {
|
||||||
|
FLAG_SET_CMDLINE(bool, UseSharedSpaces, true);
|
||||||
|
FLAG_SET_CMDLINE(bool, RequireSharedSpaces, true);
|
||||||
|
FLAG_SET_CMDLINE(bool, TraceClassPaths, true);
|
||||||
|
}
|
||||||
|
|
||||||
// Change the default value for flags which have different default values
|
// Change the default value for flags which have different default values
|
||||||
// when working with older JDKs.
|
// when working with older JDKs.
|
||||||
#ifdef LINUX
|
#ifdef LINUX
|
||||||
|
@ -3310,9 +3325,55 @@ jint Arguments::parse_each_vm_init_arg(const JavaVMInitArgs* args,
|
||||||
FLAG_SET_DEFAULT(UseLinuxPosixThreadCPUClocks, false);
|
FLAG_SET_DEFAULT(UseLinuxPosixThreadCPUClocks, false);
|
||||||
}
|
}
|
||||||
#endif // LINUX
|
#endif // LINUX
|
||||||
|
fix_appclasspath();
|
||||||
return JNI_OK;
|
return JNI_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove all empty paths from the app classpath (if IgnoreEmptyClassPaths is enabled)
|
||||||
|
//
|
||||||
|
// This is necessary because some apps like to specify classpath like -cp foo.jar:${XYZ}:bar.jar
|
||||||
|
// in their start-up scripts. If XYZ is empty, the classpath will look like "-cp foo.jar::bar.jar".
|
||||||
|
// Java treats such empty paths as if the user specified "-cp foo.jar:.:bar.jar". I.e., an empty
|
||||||
|
// path is treated as the current directory.
|
||||||
|
//
|
||||||
|
// This causes problems with CDS, which requires that all directories specified in the classpath
|
||||||
|
// must be empty. In most cases, applications do NOT want to load classes from the current
|
||||||
|
// directory anyway. Adding -XX:+IgnoreEmptyClassPaths will make these applications' start-up
|
||||||
|
// scripts compatible with CDS.
|
||||||
|
void Arguments::fix_appclasspath() {
|
||||||
|
if (IgnoreEmptyClassPaths) {
|
||||||
|
const char separator = *os::path_separator();
|
||||||
|
const char* src = _java_class_path->value();
|
||||||
|
|
||||||
|
// skip over all the leading empty paths
|
||||||
|
while (*src == separator) {
|
||||||
|
src ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* copy = AllocateHeap(strlen(src) + 1, mtInternal);
|
||||||
|
strncpy(copy, src, strlen(src) + 1);
|
||||||
|
|
||||||
|
// trim all trailing empty paths
|
||||||
|
for (char* tail = copy + strlen(copy) - 1; tail >= copy && *tail == separator; tail--) {
|
||||||
|
*tail = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
char from[3] = {separator, separator, '\0'};
|
||||||
|
char to [2] = {separator, '\0'};
|
||||||
|
while (StringUtils::replace_no_expand(copy, from, to) > 0) {
|
||||||
|
// Keep replacing "::" -> ":" until we have no more "::" (non-windows)
|
||||||
|
// Keep replacing ";;" -> ";" until we have no more ";;" (windows)
|
||||||
|
}
|
||||||
|
|
||||||
|
_java_class_path->set_value(copy);
|
||||||
|
FreeHeap(copy); // a copy was made by set_value, so don't need this anymore
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!PrintSharedArchiveAndExit) {
|
||||||
|
ClassLoader::trace_class_path("[classpath: ", _java_class_path->value());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required) {
|
jint Arguments::finalize_vm_init_args(SysClassPath* scp_p, bool scp_assembly_required) {
|
||||||
// This must be done after all -D arguments have been processed.
|
// This must be done after all -D arguments have been processed.
|
||||||
scp_p->expand_endorsed();
|
scp_p->expand_endorsed();
|
||||||
|
@ -3483,9 +3544,8 @@ void Arguments::set_shared_spaces_flags() {
|
||||||
"Cannot dump shared archive when UseCompressedOops or UseCompressedClassPointers is off.", NULL);
|
"Cannot dump shared archive when UseCompressedOops or UseCompressedClassPointers is off.", NULL);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces.
|
|
||||||
if (!UseCompressedOops || !UseCompressedClassPointers) {
|
if (!UseCompressedOops || !UseCompressedClassPointers) {
|
||||||
no_shared_spaces();
|
no_shared_spaces("UseCompressedOops and UseCompressedClassPointers must be on for UseSharedSpaces.");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -3596,9 +3656,9 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
||||||
#if INCLUDE_NMT
|
#if INCLUDE_NMT
|
||||||
if (match_option(option, "-XX:NativeMemoryTracking", &tail)) {
|
if (match_option(option, "-XX:NativeMemoryTracking", &tail)) {
|
||||||
// The launcher did not setup nmt environment variable properly.
|
// The launcher did not setup nmt environment variable properly.
|
||||||
// if (!MemTracker::check_launcher_nmt_support(tail)) {
|
if (!MemTracker::check_launcher_nmt_support(tail)) {
|
||||||
// warning("Native Memory Tracking did not setup properly, using wrong launcher?");
|
warning("Native Memory Tracking did not setup properly, using wrong launcher?");
|
||||||
// }
|
}
|
||||||
|
|
||||||
// Verify if nmt option is valid.
|
// Verify if nmt option is valid.
|
||||||
if (MemTracker::verify_nmt_option()) {
|
if (MemTracker::verify_nmt_option()) {
|
||||||
|
@ -3725,7 +3785,7 @@ jint Arguments::parse(const JavaVMInitArgs* args) {
|
||||||
FLAG_SET_DEFAULT(UseSharedSpaces, false);
|
FLAG_SET_DEFAULT(UseSharedSpaces, false);
|
||||||
FLAG_SET_DEFAULT(PrintSharedSpaces, false);
|
FLAG_SET_DEFAULT(PrintSharedSpaces, false);
|
||||||
}
|
}
|
||||||
no_shared_spaces();
|
no_shared_spaces("CDS Disabled");
|
||||||
#endif // INCLUDE_CDS
|
#endif // INCLUDE_CDS
|
||||||
|
|
||||||
return JNI_OK;
|
return JNI_OK;
|
||||||
|
|
|
@ -585,6 +585,9 @@ class Arguments : AllStatic {
|
||||||
static char* get_sysclasspath() { return _sun_boot_class_path->value(); }
|
static char* get_sysclasspath() { return _sun_boot_class_path->value(); }
|
||||||
static char* get_meta_index_path() { return _meta_index_path; }
|
static char* get_meta_index_path() { return _meta_index_path; }
|
||||||
static char* get_meta_index_dir() { return _meta_index_dir; }
|
static char* get_meta_index_dir() { return _meta_index_dir; }
|
||||||
|
static char* get_ext_dirs() { return _java_ext_dirs->value(); }
|
||||||
|
static char* get_appclasspath() { return _java_class_path->value(); }
|
||||||
|
static void fix_appclasspath();
|
||||||
|
|
||||||
// Operation modi
|
// Operation modi
|
||||||
static Mode mode() { return _mode; }
|
static Mode mode() { return _mode; }
|
||||||
|
|
|
@ -131,6 +131,19 @@ void Flag::set_uint64_t(uint64_t value) {
|
||||||
*((uint64_t*) _addr) = value;
|
*((uint64_t*) _addr) = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Flag::is_size_t() const {
|
||||||
|
return strcmp(_type, "size_t") == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t Flag::get_size_t() const {
|
||||||
|
return *((size_t*) _addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Flag::set_size_t(size_t value) {
|
||||||
|
check_writable();
|
||||||
|
*((size_t*) _addr) = value;
|
||||||
|
}
|
||||||
|
|
||||||
bool Flag::is_double() const {
|
bool Flag::is_double() const {
|
||||||
return strcmp(_type, "double") == 0;
|
return strcmp(_type, "double") == 0;
|
||||||
}
|
}
|
||||||
|
@ -306,6 +319,9 @@ void Flag::print_on(outputStream* st, bool withComments) {
|
||||||
if (is_uint64_t()) {
|
if (is_uint64_t()) {
|
||||||
st->print("%-16lu", get_uint64_t());
|
st->print("%-16lu", get_uint64_t());
|
||||||
}
|
}
|
||||||
|
if (is_size_t()) {
|
||||||
|
st->print(SIZE_FORMAT_W(-16), get_size_t());
|
||||||
|
}
|
||||||
if (is_double()) {
|
if (is_double()) {
|
||||||
st->print("%-16f", get_double());
|
st->print("%-16f", get_double());
|
||||||
}
|
}
|
||||||
|
@ -395,6 +411,8 @@ void Flag::print_as_flag(outputStream* st) {
|
||||||
st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx());
|
st->print("-XX:%s=" UINTX_FORMAT, _name, get_uintx());
|
||||||
} else if (is_uint64_t()) {
|
} else if (is_uint64_t()) {
|
||||||
st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t());
|
st->print("-XX:%s=" UINT64_FORMAT, _name, get_uint64_t());
|
||||||
|
} else if (is_size_t()) {
|
||||||
|
st->print("-XX:%s=" SIZE_FORMAT, _name, get_size_t());
|
||||||
} else if (is_double()) {
|
} else if (is_double()) {
|
||||||
st->print("-XX:%s=%f", _name, get_double());
|
st->print("-XX:%s=%f", _name, get_double());
|
||||||
} else if (is_ccstr()) {
|
} else if (is_ccstr()) {
|
||||||
|
@ -723,6 +741,34 @@ void CommandLineFlagsEx::uint64_tAtPut(CommandLineFlagWithType flag, uint64_t va
|
||||||
faddr->set_origin(origin);
|
faddr->set_origin(origin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CommandLineFlags::size_tAt(const char* name, size_t len, size_t* value) {
|
||||||
|
Flag* result = Flag::find_flag(name, len);
|
||||||
|
if (result == NULL) return false;
|
||||||
|
if (!result->is_size_t()) return false;
|
||||||
|
*value = result->get_size_t();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CommandLineFlags::size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin) {
|
||||||
|
Flag* result = Flag::find_flag(name, len);
|
||||||
|
if (result == NULL) return false;
|
||||||
|
if (!result->is_size_t()) return false;
|
||||||
|
size_t old_value = result->get_size_t();
|
||||||
|
trace_flag_changed<EventUnsignedLongFlagChanged, u8>(name, old_value, *value, origin);
|
||||||
|
result->set_size_t(*value);
|
||||||
|
*value = old_value;
|
||||||
|
result->set_origin(origin);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CommandLineFlagsEx::size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin) {
|
||||||
|
Flag* faddr = address_of_flag(flag);
|
||||||
|
guarantee(faddr != NULL && faddr->is_size_t(), "wrong flag type");
|
||||||
|
trace_flag_changed<EventUnsignedLongFlagChanged, u8>(faddr->_name, faddr->get_size_t(), value, origin);
|
||||||
|
faddr->set_size_t(value);
|
||||||
|
faddr->set_origin(origin);
|
||||||
|
}
|
||||||
|
|
||||||
bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value) {
|
bool CommandLineFlags::doubleAt(const char* name, size_t len, double* value) {
|
||||||
Flag* result = Flag::find_flag(name, len);
|
Flag* result = Flag::find_flag(name, len);
|
||||||
if (result == NULL) return false;
|
if (result == NULL) return false;
|
||||||
|
|
|
@ -275,6 +275,10 @@ struct Flag {
|
||||||
uint64_t get_uint64_t() const;
|
uint64_t get_uint64_t() const;
|
||||||
void set_uint64_t(uint64_t value);
|
void set_uint64_t(uint64_t value);
|
||||||
|
|
||||||
|
bool is_size_t() const;
|
||||||
|
size_t get_size_t() const;
|
||||||
|
void set_size_t(size_t value);
|
||||||
|
|
||||||
bool is_double() const;
|
bool is_double() const;
|
||||||
double get_double() const;
|
double get_double() const;
|
||||||
void set_double(double value);
|
void set_double(double value);
|
||||||
|
@ -350,7 +354,6 @@ class UIntFlagSetting {
|
||||||
~UIntFlagSetting() { *flag = val; }
|
~UIntFlagSetting() { *flag = val; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class DoubleFlagSetting {
|
class DoubleFlagSetting {
|
||||||
double val;
|
double val;
|
||||||
double* flag;
|
double* flag;
|
||||||
|
@ -359,6 +362,14 @@ class DoubleFlagSetting {
|
||||||
~DoubleFlagSetting() { *flag = val; }
|
~DoubleFlagSetting() { *flag = val; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class SizeTFlagSetting {
|
||||||
|
size_t val;
|
||||||
|
size_t* flag;
|
||||||
|
public:
|
||||||
|
SizeTFlagSetting(size_t& fl, size_t newValue) { flag = &fl; val = fl; fl = newValue; }
|
||||||
|
~SizeTFlagSetting() { *flag = val; }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class CommandLineFlags {
|
class CommandLineFlags {
|
||||||
public:
|
public:
|
||||||
|
@ -377,6 +388,11 @@ class CommandLineFlags {
|
||||||
static bool uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin);
|
static bool uintxAtPut(const char* name, size_t len, uintx* value, Flag::Flags origin);
|
||||||
static bool uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); }
|
static bool uintxAtPut(const char* name, uintx* value, Flag::Flags origin) { return uintxAtPut(name, strlen(name), value, origin); }
|
||||||
|
|
||||||
|
static bool size_tAt(const char* name, size_t len, size_t* value);
|
||||||
|
static bool size_tAt(const char* name, size_t* value) { return size_tAt(name, strlen(name), value); }
|
||||||
|
static bool size_tAtPut(const char* name, size_t len, size_t* value, Flag::Flags origin);
|
||||||
|
static bool size_tAtPut(const char* name, size_t* value, Flag::Flags origin) { return size_tAtPut(name, strlen(name), value, origin); }
|
||||||
|
|
||||||
static bool uint64_tAt(const char* name, size_t len, uint64_t* value);
|
static bool uint64_tAt(const char* name, size_t len, uint64_t* value);
|
||||||
static bool uint64_tAt(const char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); }
|
static bool uint64_tAt(const char* name, uint64_t* value) { return uint64_tAt(name, strlen(name), value); }
|
||||||
static bool uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin);
|
static bool uint64_tAtPut(const char* name, size_t len, uint64_t* value, Flag::Flags origin);
|
||||||
|
@ -2329,6 +2345,12 @@ class CommandLineFlags {
|
||||||
notproduct(bool, TraceScavenge, false, \
|
notproduct(bool, TraceScavenge, false, \
|
||||||
"Trace scavenge") \
|
"Trace scavenge") \
|
||||||
\
|
\
|
||||||
|
product(bool, IgnoreEmptyClassPaths, false, \
|
||||||
|
"Ignore empty path elements in -classpath") \
|
||||||
|
\
|
||||||
|
product(bool, TraceClassPaths, false, \
|
||||||
|
"Trace processing of class paths") \
|
||||||
|
\
|
||||||
product_rw(bool, TraceClassLoading, false, \
|
product_rw(bool, TraceClassLoading, false, \
|
||||||
"Trace all classes loaded") \
|
"Trace all classes loaded") \
|
||||||
\
|
\
|
||||||
|
@ -3763,6 +3785,13 @@ class CommandLineFlags {
|
||||||
product(bool, PrintSharedSpaces, false, \
|
product(bool, PrintSharedSpaces, false, \
|
||||||
"Print usage of shared spaces") \
|
"Print usage of shared spaces") \
|
||||||
\
|
\
|
||||||
|
product(bool, PrintSharedArchiveAndExit, false, \
|
||||||
|
"Print shared archive file contents") \
|
||||||
|
\
|
||||||
|
product(bool, PrintSharedDictionary, false, \
|
||||||
|
"If PrintSharedArchiveAndExit is true, also print the shared " \
|
||||||
|
"dictionary") \
|
||||||
|
\
|
||||||
product(uintx, SharedReadWriteSize, NOT_LP64(12*M) LP64_ONLY(16*M), \
|
product(uintx, SharedReadWriteSize, NOT_LP64(12*M) LP64_ONLY(16*M), \
|
||||||
"Size of read-write space for metadata (in bytes)") \
|
"Size of read-write space for metadata (in bytes)") \
|
||||||
\
|
\
|
||||||
|
@ -3779,6 +3808,10 @@ class CommandLineFlags {
|
||||||
NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)), \
|
NOT_LP64(LINUX_ONLY(2*G) NOT_LINUX(0)), \
|
||||||
"Address to allocate shared memory region for class data") \
|
"Address to allocate shared memory region for class data") \
|
||||||
\
|
\
|
||||||
|
diagnostic(bool, IgnoreUnverifiableClassesDuringDump, false, \
|
||||||
|
"Do not quit -Xshare:dump even if we encounter unverifiable " \
|
||||||
|
"classes. Just exclude them from the shared dictionary.") \
|
||||||
|
\
|
||||||
diagnostic(bool, PrintMethodHandleStubs, false, \
|
diagnostic(bool, PrintMethodHandleStubs, false, \
|
||||||
"Print generated stub code for method handles") \
|
"Print generated stub code for method handles") \
|
||||||
\
|
\
|
||||||
|
@ -3869,11 +3902,21 @@ class CommandLineFlags {
|
||||||
product(bool , AllowNonVirtualCalls, false, \
|
product(bool , AllowNonVirtualCalls, false, \
|
||||||
"Obey the ACC_SUPER flag and allow invokenonvirtual calls") \
|
"Obey the ACC_SUPER flag and allow invokenonvirtual calls") \
|
||||||
\
|
\
|
||||||
|
product(ccstr, DumpLoadedClassList, NULL, \
|
||||||
|
"Dump the names all loaded classes, that could be stored into " \
|
||||||
|
"the CDS archive, in the specified file") \
|
||||||
|
\
|
||||||
|
product(ccstr, SharedClassListFile, NULL, \
|
||||||
|
"Override the default CDS class list") \
|
||||||
|
\
|
||||||
diagnostic(ccstr, SharedArchiveFile, NULL, \
|
diagnostic(ccstr, SharedArchiveFile, NULL, \
|
||||||
"Override the default location of the CDS archive file") \
|
"Override the default location of the CDS archive file") \
|
||||||
\
|
\
|
||||||
experimental(uintx, ArrayAllocatorMallocLimit, \
|
product(ccstr, ExtraSharedClassListFile, NULL, \
|
||||||
SOLARIS_ONLY(64*K) NOT_SOLARIS(max_uintx), \
|
"Extra classlist for building the CDS archive file") \
|
||||||
|
\
|
||||||
|
experimental(size_t, ArrayAllocatorMallocLimit, \
|
||||||
|
SOLARIS_ONLY(64*K) NOT_SOLARIS((size_t)-1), \
|
||||||
"Allocation less than this value will be allocated " \
|
"Allocation less than this value will be allocated " \
|
||||||
"using malloc. Larger allocations will use mmap.") \
|
"using malloc. Larger allocations will use mmap.") \
|
||||||
\
|
\
|
||||||
|
|
|
@ -200,6 +200,7 @@ class CommandLineFlagsEx : CommandLineFlags {
|
||||||
static void intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin);
|
static void intxAtPut(CommandLineFlagWithType flag, intx value, Flag::Flags origin);
|
||||||
static void uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin);
|
static void uintxAtPut(CommandLineFlagWithType flag, uintx value, Flag::Flags origin);
|
||||||
static void uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin);
|
static void uint64_tAtPut(CommandLineFlagWithType flag, uint64_t value, Flag::Flags origin);
|
||||||
|
static void size_tAtPut(CommandLineFlagWithType flag, size_t value, Flag::Flags origin);
|
||||||
static void doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin);
|
static void doubleAtPut(CommandLineFlagWithType flag, double value, Flag::Flags origin);
|
||||||
// Contract: Flag will make private copy of the incoming value
|
// Contract: Flag will make private copy of the incoming value
|
||||||
static void ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin);
|
static void ccstrAtPut(CommandLineFlagWithType flag, ccstr value, Flag::Flags origin);
|
||||||
|
|
|
@ -309,6 +309,10 @@ void JavaCalls::call(JavaValue* result, methodHandle method, JavaCallArguments*
|
||||||
}
|
}
|
||||||
|
|
||||||
void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) {
|
void JavaCalls::call_helper(JavaValue* result, methodHandle* m, JavaCallArguments* args, TRAPS) {
|
||||||
|
// During dumping, Java execution environment is not fully initialized. Also, Java execution
|
||||||
|
// may cause undesirable side-effects in the class metadata.
|
||||||
|
assert(!DumpSharedSpaces, "must not execute Java bytecodes when dumping");
|
||||||
|
|
||||||
methodHandle method = *m;
|
methodHandle method = *m;
|
||||||
JavaThread* thread = (JavaThread*)THREAD;
|
JavaThread* thread = (JavaThread*)THREAD;
|
||||||
assert(thread->is_Java_thread(), "must be called by a java thread");
|
assert(thread->is_Java_thread(), "must be called by a java thread");
|
||||||
|
|
|
@ -662,6 +662,7 @@ typedef TwoOopHashtable<Symbol*, mtClass> SymbolTwoOopHashtable;
|
||||||
static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), Klass*) \
|
static_field(SystemDictionary, WK_KLASS(StackOverflowError_klass), Klass*) \
|
||||||
static_field(SystemDictionary, WK_KLASS(ProtectionDomain_klass), Klass*) \
|
static_field(SystemDictionary, WK_KLASS(ProtectionDomain_klass), Klass*) \
|
||||||
static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), Klass*) \
|
static_field(SystemDictionary, WK_KLASS(AccessControlContext_klass), Klass*) \
|
||||||
|
static_field(SystemDictionary, WK_KLASS(SecureClassLoader_klass), Klass*) \
|
||||||
static_field(SystemDictionary, WK_KLASS(Reference_klass), Klass*) \
|
static_field(SystemDictionary, WK_KLASS(Reference_klass), Klass*) \
|
||||||
static_field(SystemDictionary, WK_KLASS(SoftReference_klass), Klass*) \
|
static_field(SystemDictionary, WK_KLASS(SoftReference_klass), Klass*) \
|
||||||
static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \
|
static_field(SystemDictionary, WK_KLASS(WeakReference_klass), Klass*) \
|
||||||
|
|
|
@ -320,6 +320,25 @@ static jint set_uint64_t_flag(const char* name, AttachOperation* op, outputStrea
|
||||||
return res? JNI_OK : JNI_ERR;
|
return res? JNI_OK : JNI_ERR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// set a size_t global flag using value from AttachOperation
|
||||||
|
static jint set_size_t_flag(const char* name, AttachOperation* op, outputStream* out) {
|
||||||
|
size_t value;
|
||||||
|
const char* arg1;
|
||||||
|
if ((arg1 = op->arg(1)) != NULL) {
|
||||||
|
int n = sscanf(arg1, SIZE_FORMAT, &value);
|
||||||
|
if (n != 1) {
|
||||||
|
out->print_cr("flag value must be an unsigned integer");
|
||||||
|
return JNI_ERR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool res = CommandLineFlags::size_tAtPut((char*)name, &value, Flag::ATTACH_ON_DEMAND);
|
||||||
|
if (! res) {
|
||||||
|
out->print_cr("setting flag %s failed", name);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res? JNI_OK : JNI_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
// set a string global flag using value from AttachOperation
|
// set a string global flag using value from AttachOperation
|
||||||
static jint set_ccstr_flag(const char* name, AttachOperation* op, outputStream* out) {
|
static jint set_ccstr_flag(const char* name, AttachOperation* op, outputStream* out) {
|
||||||
const char* value;
|
const char* value;
|
||||||
|
@ -356,6 +375,8 @@ static jint set_flag(AttachOperation* op, outputStream* out) {
|
||||||
return set_uintx_flag(name, op, out);
|
return set_uintx_flag(name, op, out);
|
||||||
} else if (f->is_uint64_t()) {
|
} else if (f->is_uint64_t()) {
|
||||||
return set_uint64_t_flag(name, op, out);
|
return set_uint64_t_flag(name, op, out);
|
||||||
|
} else if (f->is_size_t()) {
|
||||||
|
return set_size_t_flag(name, op, out);
|
||||||
} else if (f->is_ccstr()) {
|
} else if (f->is_ccstr()) {
|
||||||
return set_ccstr_flag(name, op, out);
|
return set_ccstr_flag(name, op, out);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1696,6 +1696,9 @@ bool add_global_entry(JNIEnv* env, Handle name, jmmVMGlobal *global, Flag *flag,
|
||||||
} else if (flag->is_uint64_t()) {
|
} else if (flag->is_uint64_t()) {
|
||||||
global->value.j = (jlong)flag->get_uint64_t();
|
global->value.j = (jlong)flag->get_uint64_t();
|
||||||
global->type = JMM_VMGLOBAL_TYPE_JLONG;
|
global->type = JMM_VMGLOBAL_TYPE_JLONG;
|
||||||
|
} else if (flag->is_size_t()) {
|
||||||
|
global->value.j = (jlong)flag->get_size_t();
|
||||||
|
global->type = JMM_VMGLOBAL_TYPE_JLONG;
|
||||||
} else if (flag->is_ccstr()) {
|
} else if (flag->is_ccstr()) {
|
||||||
Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false);
|
Handle str = java_lang_String::create_from_str(flag->get_ccstr(), CHECK_false);
|
||||||
global->value.l = (jobject)JNIHandles::make_local(env, str());
|
global->value.l = (jobject)JNIHandles::make_local(env, str());
|
||||||
|
@ -1851,6 +1854,9 @@ JVM_ENTRY(void, jmm_SetVMGlobal(JNIEnv *env, jstring flag_name, jvalue new_value
|
||||||
} else if (flag->is_uint64_t()) {
|
} else if (flag->is_uint64_t()) {
|
||||||
uint64_t uvalue = (uint64_t)new_value.j;
|
uint64_t uvalue = (uint64_t)new_value.j;
|
||||||
succeed = CommandLineFlags::uint64_tAtPut(name, &uvalue, Flag::MANAGEMENT);
|
succeed = CommandLineFlags::uint64_tAtPut(name, &uvalue, Flag::MANAGEMENT);
|
||||||
|
} else if (flag->is_size_t()) {
|
||||||
|
size_t svalue = (size_t)new_value.j;
|
||||||
|
succeed = CommandLineFlags::size_tAtPut(name, &svalue, Flag::MANAGEMENT);
|
||||||
} else if (flag->is_ccstr()) {
|
} else if (flag->is_ccstr()) {
|
||||||
oop str = JNIHandles::resolve_external_guard(new_value.l);
|
oop str = JNIHandles::resolve_external_guard(new_value.l);
|
||||||
if (str == NULL) {
|
if (str == NULL) {
|
||||||
|
|
|
@ -79,7 +79,12 @@ NMT_TrackingLevel MemTracker::init_tracking_level() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void MemTracker::init() {
|
void MemTracker::init() {
|
||||||
if (tracking_level() >= NMT_summary) {
|
NMT_TrackingLevel level = tracking_level();
|
||||||
|
if (level >= NMT_summary) {
|
||||||
|
if (!VirtualMemoryTracker::late_initialize(level)) {
|
||||||
|
shutdown();
|
||||||
|
return;
|
||||||
|
}
|
||||||
_query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock");
|
_query_lock = new (std::nothrow) Mutex(Monitor::max_nonleaf, "NMT_queryLock");
|
||||||
// Already OOM. It is unlikely, but still have to handle it.
|
// Already OOM. It is unlikely, but still have to handle it.
|
||||||
if (_query_lock == NULL) {
|
if (_query_lock == NULL) {
|
||||||
|
|
|
@ -34,7 +34,7 @@ void VirtualMemorySummary::initialize() {
|
||||||
::new ((void*)_snapshot) VirtualMemorySnapshot();
|
::new ((void*)_snapshot) VirtualMemorySnapshot();
|
||||||
}
|
}
|
||||||
|
|
||||||
SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base> VirtualMemoryTracker::_reserved_regions;
|
SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>* VirtualMemoryTracker::_reserved_regions;
|
||||||
|
|
||||||
int compare_committed_region(const CommittedMemoryRegion& r1, const CommittedMemoryRegion& r2) {
|
int compare_committed_region(const CommittedMemoryRegion& r1, const CommittedMemoryRegion& r2) {
|
||||||
return r1.compare(r2);
|
return r1.compare(r2);
|
||||||
|
@ -283,17 +283,26 @@ bool VirtualMemoryTracker::initialize(NMT_TrackingLevel level) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool VirtualMemoryTracker::late_initialize(NMT_TrackingLevel level) {
|
||||||
|
if (level >= NMT_summary) {
|
||||||
|
_reserved_regions = new (std::nothrow, ResourceObj::C_HEAP, mtNMT)
|
||||||
|
SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>();
|
||||||
|
return (_reserved_regions != NULL);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size,
|
bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size,
|
||||||
const NativeCallStack& stack, MEMFLAGS flag, bool all_committed) {
|
const NativeCallStack& stack, MEMFLAGS flag, bool all_committed) {
|
||||||
assert(base_addr != NULL, "Invalid address");
|
assert(base_addr != NULL, "Invalid address");
|
||||||
assert(size > 0, "Invalid size");
|
assert(size > 0, "Invalid size");
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
ReservedMemoryRegion rgn(base_addr, size, stack, flag);
|
ReservedMemoryRegion rgn(base_addr, size, stack, flag);
|
||||||
ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
|
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
|
||||||
LinkedListNode<ReservedMemoryRegion>* node;
|
LinkedListNode<ReservedMemoryRegion>* node;
|
||||||
if (reserved_rgn == NULL) {
|
if (reserved_rgn == NULL) {
|
||||||
VirtualMemorySummary::record_reserved_memory(size, flag);
|
VirtualMemorySummary::record_reserved_memory(size, flag);
|
||||||
node = _reserved_regions.add(rgn);
|
node = _reserved_regions->add(rgn);
|
||||||
if (node != NULL) {
|
if (node != NULL) {
|
||||||
node->data()->set_all_committed(all_committed);
|
node->data()->set_all_committed(all_committed);
|
||||||
return true;
|
return true;
|
||||||
|
@ -338,9 +347,10 @@ bool VirtualMemoryTracker::add_reserved_region(address base_addr, size_t size,
|
||||||
|
|
||||||
void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) {
|
void VirtualMemoryTracker::set_reserved_region_type(address addr, MEMFLAGS flag) {
|
||||||
assert(addr != NULL, "Invalid address");
|
assert(addr != NULL, "Invalid address");
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
|
|
||||||
ReservedMemoryRegion rgn(addr, 1);
|
ReservedMemoryRegion rgn(addr, 1);
|
||||||
ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
|
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
|
||||||
if (reserved_rgn != NULL) {
|
if (reserved_rgn != NULL) {
|
||||||
assert(reserved_rgn->contain_address(addr), "Containment");
|
assert(reserved_rgn->contain_address(addr), "Containment");
|
||||||
if (reserved_rgn->flag() != flag) {
|
if (reserved_rgn->flag() != flag) {
|
||||||
|
@ -354,8 +364,10 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size,
|
||||||
const NativeCallStack& stack) {
|
const NativeCallStack& stack) {
|
||||||
assert(addr != NULL, "Invalid address");
|
assert(addr != NULL, "Invalid address");
|
||||||
assert(size > 0, "Invalid size");
|
assert(size > 0, "Invalid size");
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
|
|
||||||
ReservedMemoryRegion rgn(addr, size);
|
ReservedMemoryRegion rgn(addr, size);
|
||||||
ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
|
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
|
||||||
|
|
||||||
assert(reserved_rgn != NULL, "No reserved region");
|
assert(reserved_rgn != NULL, "No reserved region");
|
||||||
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
||||||
|
@ -365,8 +377,10 @@ bool VirtualMemoryTracker::add_committed_region(address addr, size_t size,
|
||||||
bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) {
|
bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size) {
|
||||||
assert(addr != NULL, "Invalid address");
|
assert(addr != NULL, "Invalid address");
|
||||||
assert(size > 0, "Invalid size");
|
assert(size > 0, "Invalid size");
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
|
|
||||||
ReservedMemoryRegion rgn(addr, size);
|
ReservedMemoryRegion rgn(addr, size);
|
||||||
ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
|
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
|
||||||
assert(reserved_rgn != NULL, "No reserved region");
|
assert(reserved_rgn != NULL, "No reserved region");
|
||||||
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
||||||
return reserved_rgn->remove_uncommitted_region(addr, size);
|
return reserved_rgn->remove_uncommitted_region(addr, size);
|
||||||
|
@ -375,9 +389,10 @@ bool VirtualMemoryTracker::remove_uncommitted_region(address addr, size_t size)
|
||||||
bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
|
bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
|
||||||
assert(addr != NULL, "Invalid address");
|
assert(addr != NULL, "Invalid address");
|
||||||
assert(size > 0, "Invalid size");
|
assert(size > 0, "Invalid size");
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
|
|
||||||
ReservedMemoryRegion rgn(addr, size);
|
ReservedMemoryRegion rgn(addr, size);
|
||||||
ReservedMemoryRegion* reserved_rgn = _reserved_regions.find(rgn);
|
ReservedMemoryRegion* reserved_rgn = _reserved_regions->find(rgn);
|
||||||
|
|
||||||
assert(reserved_rgn != NULL, "No reserved region");
|
assert(reserved_rgn != NULL, "No reserved region");
|
||||||
|
|
||||||
|
@ -390,7 +405,7 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
|
||||||
VirtualMemorySummary::record_released_memory(size, reserved_rgn->flag());
|
VirtualMemorySummary::record_released_memory(size, reserved_rgn->flag());
|
||||||
|
|
||||||
if (reserved_rgn->same_region(addr, size)) {
|
if (reserved_rgn->same_region(addr, size)) {
|
||||||
return _reserved_regions.remove(rgn);
|
return _reserved_regions->remove(rgn);
|
||||||
} else {
|
} else {
|
||||||
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
assert(reserved_rgn->contain_region(addr, size), "Not completely contained");
|
||||||
if (reserved_rgn->base() == addr ||
|
if (reserved_rgn->base() == addr ||
|
||||||
|
@ -405,7 +420,7 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
|
||||||
|
|
||||||
// use original region for lower region
|
// use original region for lower region
|
||||||
reserved_rgn->exclude_region(addr, top - addr);
|
reserved_rgn->exclude_region(addr, top - addr);
|
||||||
LinkedListNode<ReservedMemoryRegion>* new_rgn = _reserved_regions.add(high_rgn);
|
LinkedListNode<ReservedMemoryRegion>* new_rgn = _reserved_regions->add(high_rgn);
|
||||||
if (new_rgn == NULL) {
|
if (new_rgn == NULL) {
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
|
@ -418,8 +433,9 @@ bool VirtualMemoryTracker::remove_released_region(address addr, size_t size) {
|
||||||
|
|
||||||
|
|
||||||
bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) {
|
bool VirtualMemoryTracker::walk_virtual_memory(VirtualMemoryWalker* walker) {
|
||||||
|
assert(_reserved_regions != NULL, "Sanity check");
|
||||||
ThreadCritical tc;
|
ThreadCritical tc;
|
||||||
LinkedListNode<ReservedMemoryRegion>* head = _reserved_regions.head();
|
LinkedListNode<ReservedMemoryRegion>* head = _reserved_regions->head();
|
||||||
while (head != NULL) {
|
while (head != NULL) {
|
||||||
const ReservedMemoryRegion* rgn = head->peek();
|
const ReservedMemoryRegion* rgn = head->peek();
|
||||||
if (!walker->do_allocation_site(rgn)) {
|
if (!walker->do_allocation_site(rgn)) {
|
||||||
|
@ -439,7 +455,10 @@ bool VirtualMemoryTracker::transition(NMT_TrackingLevel from, NMT_TrackingLevel
|
||||||
assert(from == NMT_summary || from == NMT_detail, "Just check");
|
assert(from == NMT_summary || from == NMT_detail, "Just check");
|
||||||
// Clean up virtual memory tracking data structures.
|
// Clean up virtual memory tracking data structures.
|
||||||
ThreadCritical tc;
|
ThreadCritical tc;
|
||||||
_reserved_regions.clear();
|
if (_reserved_regions != NULL) {
|
||||||
|
delete _reserved_regions;
|
||||||
|
_reserved_regions = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -414,6 +414,9 @@ class VirtualMemoryTracker : AllStatic {
|
||||||
public:
|
public:
|
||||||
static bool initialize(NMT_TrackingLevel level);
|
static bool initialize(NMT_TrackingLevel level);
|
||||||
|
|
||||||
|
// Late phase initialization
|
||||||
|
static bool late_initialize(NMT_TrackingLevel level);
|
||||||
|
|
||||||
static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack,
|
static bool add_reserved_region (address base_addr, size_t size, const NativeCallStack& stack,
|
||||||
MEMFLAGS flag = mtNone, bool all_committed = false);
|
MEMFLAGS flag = mtNone, bool all_committed = false);
|
||||||
|
|
||||||
|
@ -428,7 +431,7 @@ class VirtualMemoryTracker : AllStatic {
|
||||||
static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to);
|
static bool transition(NMT_TrackingLevel from, NMT_TrackingLevel to);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base> _reserved_regions;
|
static SortedLinkedList<ReservedMemoryRegion, compare_reserved_region_base>* _reserved_regions;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -567,7 +567,7 @@ class TestBitMap : public AllStatic {
|
||||||
}
|
}
|
||||||
|
|
||||||
static void testResizeNonResource() {
|
static void testResizeNonResource() {
|
||||||
const uintx bitmap_bytes = BITMAP_SIZE / BitsPerByte;
|
const size_t bitmap_bytes = BITMAP_SIZE / BitsPerByte;
|
||||||
|
|
||||||
// Test the default behavior
|
// Test the default behavior
|
||||||
testResize(false);
|
testResize(false);
|
||||||
|
@ -575,13 +575,13 @@ class TestBitMap : public AllStatic {
|
||||||
{
|
{
|
||||||
// Make sure that AllocatorMallocLimit is larger than our allocation request
|
// Make sure that AllocatorMallocLimit is larger than our allocation request
|
||||||
// forcing it to call standard malloc()
|
// forcing it to call standard malloc()
|
||||||
UIntFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes * 4);
|
SizeTFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes * 4);
|
||||||
testResize(false);
|
testResize(false);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
// Make sure that AllocatorMallocLimit is smaller than our allocation request
|
// Make sure that AllocatorMallocLimit is smaller than our allocation request
|
||||||
// forcing it to call mmap() (or equivalent)
|
// forcing it to call mmap() (or equivalent)
|
||||||
UIntFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes / 4);
|
SizeTFlagSetting fs(ArrayAllocatorMallocLimit, bitmap_bytes / 4);
|
||||||
testResize(false);
|
testResize(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -85,9 +85,13 @@ bool Exceptions::special_exception(Thread* thread, const char* file, int line, H
|
||||||
#endif // ASSERT
|
#endif // ASSERT
|
||||||
|
|
||||||
if (thread->is_VM_thread()
|
if (thread->is_VM_thread()
|
||||||
|| thread->is_Compiler_thread() ) {
|
|| thread->is_Compiler_thread()
|
||||||
|
|| DumpSharedSpaces ) {
|
||||||
// We do not care what kind of exception we get for the vm-thread or a thread which
|
// We do not care what kind of exception we get for the vm-thread or a thread which
|
||||||
// is compiling. We just install a dummy exception object
|
// is compiling. We just install a dummy exception object
|
||||||
|
//
|
||||||
|
// We also cannot throw a proper exception when dumping, because we cannot run
|
||||||
|
// Java bytecodes now. A dummy exception will suffice.
|
||||||
thread->set_pending_exception(Universe::vm_exception(), file, line);
|
thread->set_pending_exception(Universe::vm_exception(), file, line);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -108,9 +112,13 @@ bool Exceptions::special_exception(Thread* thread, const char* file, int line, S
|
||||||
}
|
}
|
||||||
|
|
||||||
if (thread->is_VM_thread()
|
if (thread->is_VM_thread()
|
||||||
|| thread->is_Compiler_thread() ) {
|
|| thread->is_Compiler_thread()
|
||||||
|
|| DumpSharedSpaces ) {
|
||||||
// We do not care what kind of exception we get for the vm-thread or a thread which
|
// We do not care what kind of exception we get for the vm-thread or a thread which
|
||||||
// is compiling. We just install a dummy exception object
|
// is compiling. We just install a dummy exception object
|
||||||
|
//
|
||||||
|
// We also cannot throw a proper exception when dumping, because we cannot run
|
||||||
|
// Java bytecodes now. A dummy exception will suffice.
|
||||||
thread->set_pending_exception(Universe::vm_exception(), file, line);
|
thread->set_pending_exception(Universe::vm_exception(), file, line);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -352,6 +352,7 @@ stringStream::~stringStream() {}
|
||||||
xmlStream* xtty;
|
xmlStream* xtty;
|
||||||
outputStream* tty;
|
outputStream* tty;
|
||||||
outputStream* gclog_or_tty;
|
outputStream* gclog_or_tty;
|
||||||
|
CDS_ONLY(fileStream* classlist_file;) // Only dump the classes that can be stored into the CDS archive
|
||||||
extern Mutex* tty_lock;
|
extern Mutex* tty_lock;
|
||||||
|
|
||||||
#define EXTRACHARLEN 32
|
#define EXTRACHARLEN 32
|
||||||
|
@ -463,7 +464,8 @@ static const char* make_log_name_internal(const char* log_name, const char* forc
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
// log_name comes from -XX:LogFile=log_name or -Xloggc:log_name
|
// log_name comes from -XX:LogFile=log_name, -Xloggc:log_name or
|
||||||
|
// -XX:DumpLoadedClassList=<file_name>
|
||||||
// in log_name, %p => pid1234 and
|
// in log_name, %p => pid1234 and
|
||||||
// %t => YYYY-MM-DD_HH-MM-SS
|
// %t => YYYY-MM-DD_HH-MM-SS
|
||||||
static const char* make_log_name(const char* log_name, const char* force_directory) {
|
static const char* make_log_name(const char* log_name, const char* force_directory) {
|
||||||
|
@ -1103,6 +1105,16 @@ void ostream_init_log() {
|
||||||
gclog_or_tty = gclog;
|
gclog_or_tty = gclog;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
// For -XX:DumpLoadedClassList=<file> option
|
||||||
|
if (DumpLoadedClassList != NULL) {
|
||||||
|
const char* list_name = make_log_name(DumpLoadedClassList, NULL);
|
||||||
|
classlist_file = new(ResourceObj::C_HEAP, mtInternal)
|
||||||
|
fileStream(list_name);
|
||||||
|
FREE_C_HEAP_ARRAY(char, list_name, mtInternal);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
// If we haven't lazily initialized the logfile yet, do it now,
|
// If we haven't lazily initialized the logfile yet, do it now,
|
||||||
// to avoid the possibility of lazy initialization during a VM
|
// to avoid the possibility of lazy initialization during a VM
|
||||||
// crash, which can affect the stability of the fatal error handler.
|
// crash, which can affect the stability of the fatal error handler.
|
||||||
|
@ -1115,6 +1127,11 @@ void ostream_exit() {
|
||||||
static bool ostream_exit_called = false;
|
static bool ostream_exit_called = false;
|
||||||
if (ostream_exit_called) return;
|
if (ostream_exit_called) return;
|
||||||
ostream_exit_called = true;
|
ostream_exit_called = true;
|
||||||
|
#if INCLUDE_CDS
|
||||||
|
if (classlist_file != NULL) {
|
||||||
|
delete classlist_file;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
if (gclog_or_tty != tty) {
|
if (gclog_or_tty != tty) {
|
||||||
delete gclog_or_tty;
|
delete gclog_or_tty;
|
||||||
}
|
}
|
||||||
|
|
|
@ -214,6 +214,8 @@ class fileStream : public outputStream {
|
||||||
void flush();
|
void flush();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
CDS_ONLY(extern fileStream* classlist_file;)
|
||||||
|
|
||||||
// unlike fileStream, fdStream does unbuffered I/O by calling
|
// unlike fileStream, fdStream does unbuffered I/O by calling
|
||||||
// open() and write() directly. It is async-safe, but output
|
// open() and write() directly. It is async-safe, but output
|
||||||
// from multiple thread may be mixed together. Used by fatal
|
// from multiple thread may be mixed together. Used by fatal
|
||||||
|
|
43
hotspot/src/share/vm/utilities/stringUtils.cpp
Normal file
43
hotspot/src/share/vm/utilities/stringUtils.cpp
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "precompiled.hpp"
|
||||||
|
#include "utilities/stringUtils.hpp"
|
||||||
|
|
||||||
|
int StringUtils::replace_no_expand(char* string, const char* from, const char* to) {
|
||||||
|
int replace_count = 0;
|
||||||
|
size_t from_len = strlen(from);
|
||||||
|
size_t to_len = strlen(to);
|
||||||
|
assert(from_len >= to_len, "must not expand input");
|
||||||
|
|
||||||
|
for (char* dst = string; *dst && (dst = strstr(dst, from)) != NULL;) {
|
||||||
|
char* left_over = dst + from_len;
|
||||||
|
memmove(dst, to, to_len); // does not copy trailing 0 of <to>
|
||||||
|
dst += to_len; // skip over the replacement.
|
||||||
|
memmove(dst, left_over, strlen(left_over) + 1); // copies the trailing 0 of <left_over>
|
||||||
|
++ replace_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return replace_count;
|
||||||
|
}
|
42
hotspot/src/share/vm/utilities/stringUtils.hpp
Normal file
42
hotspot/src/share/vm/utilities/stringUtils.hpp
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
|
*
|
||||||
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License version 2 only, as
|
||||||
|
* published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* version 2 for more details (a copy is included in the LICENSE file that
|
||||||
|
* accompanied this code).
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License version
|
||||||
|
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||||
|
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
*
|
||||||
|
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||||
|
* or visit www.oracle.com if you need additional information or have any
|
||||||
|
* questions.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SHARE_VM_UTILITIES_STRINGUTILS_HPP
|
||||||
|
#define SHARE_VM_UTILITIES_STRINGUTILS_HPP
|
||||||
|
|
||||||
|
#include "memory/allocation.hpp"
|
||||||
|
|
||||||
|
class StringUtils : AllStatic {
|
||||||
|
public:
|
||||||
|
// Replace the substring <from> with another string <to>. <to> must be
|
||||||
|
// no longer than <from>. The input string is modified in-place.
|
||||||
|
//
|
||||||
|
// Replacement is done in a single pass left-to-right. So replace_no_expand("aaa", "aa", "a")
|
||||||
|
// will result in "aa", not "a".
|
||||||
|
//
|
||||||
|
// Returns the count of substrings that have been replaced.
|
||||||
|
static int replace_no_expand(char* string, const char* from, const char* to);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SHARE_VM_UTILITIES_STRINGUTILS_HPP
|
|
@ -328,6 +328,21 @@ hotspot_gc = \
|
||||||
sanity/ExecuteInternalVMTests.java
|
sanity/ExecuteInternalVMTests.java
|
||||||
|
|
||||||
hotspot_runtime = \
|
hotspot_runtime = \
|
||||||
|
runtime/ \
|
||||||
|
-runtime/6888954/vmerrors.sh \
|
||||||
|
-runtime/RedefineObject/TestRedefineObject.java \
|
||||||
|
-runtime/8003720/Test8003720.java \
|
||||||
|
-runtime/Metaspace/FragmentMetaspace.java \
|
||||||
|
-runtime/Metaspace/FragmentMetaspaceSimple.java \
|
||||||
|
-runtime/Thread/TestThreadDumpMonitorContention.java \
|
||||||
|
-runtime/SharedArchiveFile/SharedBaseAddress.java \
|
||||||
|
-runtime/memory/ReserveMemory.java \
|
||||||
|
-runtime/Unsafe/RangeCheck.java \
|
||||||
|
-runtime/SharedArchiveFile/CdsSameObjectAlignment.java \
|
||||||
|
-runtime/SharedArchiveFile/DefaultUseWithClient.java \
|
||||||
|
-runtime/Thread/CancellableThreadTest.java
|
||||||
|
|
||||||
|
hotspot_runtime_closed = \
|
||||||
sanity/ExecuteInternalVMTests.java
|
sanity/ExecuteInternalVMTests.java
|
||||||
|
|
||||||
hotspot_serviceability = \
|
hotspot_serviceability = \
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -31,6 +31,7 @@ import java.lang.reflect.Method;
|
||||||
* @summary Deoptimization on sparc doesn't set Llast_SP correctly in the interpreter frames it creates
|
* @summary Deoptimization on sparc doesn't set Llast_SP correctly in the interpreter frames it creates
|
||||||
* @build Test8009761
|
* @build Test8009761
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=exclude,Test8009761::m2 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xss256K Test8009761
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:CompileCommand=exclude,Test8009761::m2 -XX:-UseOnStackReplacement -XX:-BackgroundCompilation -Xss256K Test8009761
|
||||||
*/
|
*/
|
||||||
public class Test8009761 {
|
public class Test8009761 {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -28,6 +28,7 @@
|
||||||
* @library /testlibrary/whitebox /testlibrary
|
* @library /testlibrary/whitebox /testlibrary
|
||||||
* @build Test8010927
|
* @build Test8010927
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. -Xmx64m -XX:NewSize=20971520 -XX:MaxNewSize=32m -XX:-UseTLAB -XX:-UseParNewGC -XX:-UseAdaptiveSizePolicy Test8010927
|
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. -Xmx64m -XX:NewSize=20971520 -XX:MaxNewSize=32m -XX:-UseTLAB -XX:-UseParNewGC -XX:-UseAdaptiveSizePolicy Test8010927
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @build TestUseBMI1InstructionsOnSupportedCPU
|
* @build TestUseBMI1InstructionsOnSupportedCPU
|
||||||
* BMISupportedCPUTest
|
* BMISupportedCPUTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestUseBMI1InstructionsOnSupportedCPU
|
* -XX:+WhiteBoxAPI TestUseBMI1InstructionsOnSupportedCPU
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @build TestUseBMI1InstructionsOnUnsupportedCPU
|
* @build TestUseBMI1InstructionsOnUnsupportedCPU
|
||||||
* BMIUnsupportedCPUTest
|
* BMIUnsupportedCPUTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestUseBMI1InstructionsOnUnsupportedCPU
|
* -XX:+WhiteBoxAPI TestUseBMI1InstructionsOnUnsupportedCPU
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @build TestUseCountLeadingZerosInstructionOnSupportedCPU
|
* @build TestUseCountLeadingZerosInstructionOnSupportedCPU
|
||||||
* BMISupportedCPUTest
|
* BMISupportedCPUTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI
|
* -XX:+WhiteBoxAPI
|
||||||
* TestUseCountLeadingZerosInstructionOnSupportedCPU
|
* TestUseCountLeadingZerosInstructionOnSupportedCPU
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @build TestUseCountLeadingZerosInstructionOnUnsupportedCPU
|
* @build TestUseCountLeadingZerosInstructionOnUnsupportedCPU
|
||||||
* BMIUnsupportedCPUTest
|
* BMIUnsupportedCPUTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI
|
* -XX:+WhiteBoxAPI
|
||||||
* TestUseCountLeadingZerosInstructionOnUnsupportedCPU
|
* TestUseCountLeadingZerosInstructionOnUnsupportedCPU
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @build TestUseCountTrailingZerosInstructionOnSupportedCPU
|
* @build TestUseCountTrailingZerosInstructionOnSupportedCPU
|
||||||
* BMISupportedCPUTest
|
* BMISupportedCPUTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI
|
* -XX:+WhiteBoxAPI
|
||||||
* TestUseCountTrailingZerosInstructionOnSupportedCPU
|
* TestUseCountTrailingZerosInstructionOnSupportedCPU
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @build TestUseCountTrailingZerosInstructionOnUnsupportedCPU
|
* @build TestUseCountTrailingZerosInstructionOnUnsupportedCPU
|
||||||
* BMIUnsupportedCPUTest
|
* BMIUnsupportedCPUTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI
|
* -XX:+WhiteBoxAPI
|
||||||
* TestUseCountTrailingZerosInstructionOnUnsupportedCPU
|
* TestUseCountTrailingZerosInstructionOnUnsupportedCPU
|
||||||
|
|
|
@ -35,6 +35,7 @@ import java.net.URLClassLoader;
|
||||||
* @build TestMethodUnloading
|
* @build TestMethodUnloading
|
||||||
* @build WorkerClass
|
* @build WorkerClass
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseCompressedOops -XX:+UseParallelGC -XX:CompileOnly=TestMethodUnloading::doWork TestMethodUnloading
|
* @run main/othervm -Xbootclasspath/a:. -XX:+IgnoreUnrecognizedVMOptions -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -XX:-BackgroundCompilation -XX:-UseCompressedOops -XX:+UseParallelGC -XX:CompileOnly=TestMethodUnloading::doWork TestMethodUnloading
|
||||||
*/
|
*/
|
||||||
public class TestMethodUnloading {
|
public class TestMethodUnloading {
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestAndnI BMITestRunner Expr
|
* @build TestAndnI BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestAndnI
|
* -XX:+WhiteBoxAPI TestAndnI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestAndnL BMITestRunner Expr
|
* @build TestAndnL BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestAndnL
|
* -XX:+WhiteBoxAPI TestAndnL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestBlsiI BMITestRunner Expr
|
* @build TestBlsiI BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestBlsiI
|
* -XX:+WhiteBoxAPI TestBlsiI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestBlsiL BMITestRunner Expr
|
* @build TestBlsiL BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestBlsiL
|
* -XX:+WhiteBoxAPI TestBlsiL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestBlsmskI BMITestRunner Expr
|
* @build TestBlsmskI BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestBlsmskI
|
* -XX:+WhiteBoxAPI TestBlsmskI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestBlsmskL BMITestRunner Expr
|
* @build TestBlsmskL BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestBlsmskL
|
* -XX:+WhiteBoxAPI TestBlsmskL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestBlsrI BMITestRunner Expr
|
* @build TestBlsrI BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestBlsrI
|
* -XX:+WhiteBoxAPI TestBlsrI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestBlsrL BMITestRunner Expr
|
* @build TestBlsrL BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestBlsrL
|
* -XX:+WhiteBoxAPI TestBlsrL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestLzcntI BMITestRunner Expr
|
* @build TestLzcntI BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestLzcntI
|
* -XX:+WhiteBoxAPI TestLzcntI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestLzcntL BMITestRunner Expr
|
* @build TestLzcntL BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestLzcntL
|
* -XX:+WhiteBoxAPI TestLzcntL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestTzcntI BMITestRunner Expr
|
* @build TestTzcntI BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestTzcntI
|
* -XX:+WhiteBoxAPI TestTzcntI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox
|
* @library /testlibrary /testlibrary/whitebox
|
||||||
* @build TestTzcntL BMITestRunner Expr
|
* @build TestTzcntL BMITestRunner Expr
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+WhiteBoxAPI TestTzcntL
|
* -XX:+WhiteBoxAPI TestTzcntL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build AddnTestI
|
* @build AddnTestI
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions AddnTestI
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions AddnTestI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build AddnTestL
|
* @build AddnTestL
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions AddnTestL
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions AddnTestL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build BlsiTestI
|
* @build BlsiTestI
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsiTestI
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsiTestI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build BlsiTestL
|
* @build BlsiTestL
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsiTestL
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsiTestL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build BlsmskTestI
|
* @build BlsmskTestI
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsmskTestI
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsmskTestI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build BlsmskTestL
|
* @build BlsmskTestL
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsmskTestL
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsmskTestL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build BlsrTestI
|
* @build BlsrTestI
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsrTestI
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsrTestI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build BlsrTestL
|
* @build BlsrTestL
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsrTestL
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseBMI1Instructions BlsrTestL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build LZcntTestI
|
* @build LZcntTestI
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountLeadingZerosInstruction LZcntTestI
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountLeadingZerosInstruction LZcntTestI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build LZcntTestL
|
* @build LZcntTestL
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountLeadingZerosInstruction LZcntTestL
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountLeadingZerosInstruction LZcntTestL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build TZcntTestI
|
* @build TZcntTestI
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountTrailingZerosInstruction TZcntTestI
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountTrailingZerosInstruction TZcntTestI
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox ..
|
||||||
* @build TZcntTestL
|
* @build TZcntTestL
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
* @run main/othervm -Xbootclasspath/a:. -Xbatch -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountTrailingZerosInstruction TZcntTestL
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+UseCountTrailingZerosInstruction TZcntTestL
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
||||||
* @build AddExactIntTest
|
* @build AddExactIntTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
||||||
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
||||||
* @build AddExactLongTest
|
* @build AddExactLongTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
||||||
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
||||||
* @build DecrementExactIntTest
|
* @build DecrementExactIntTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
||||||
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
||||||
* @build DecrementExactLongTest
|
* @build DecrementExactLongTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
||||||
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
||||||
* @build IncrementExactIntTest
|
* @build IncrementExactIntTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
||||||
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
||||||
* @build IncrementExactLongTest
|
* @build IncrementExactLongTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
||||||
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2013, 2014, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
* @library /testlibrary /testlibrary/whitebox /compiler/whitebox
|
||||||
* @build MultiplyExactIntTest
|
* @build MultiplyExactIntTest
|
||||||
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
* @run main ClassFileInstaller sun.hotspot.WhiteBox
|
||||||
|
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||||
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
* @run main/othervm -Xbootclasspath/a:. -XX:+UnlockDiagnosticVMOptions
|
||||||
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
* -XX:+IgnoreUnrecognizedVMOptions -XX:+WhiteBoxAPI -XX:+LogCompilation
|
||||||
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
* -XX:CompileCommand=compileonly,MathIntrinsic*::execMathMethod
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue