Merge
This commit is contained in:
commit
7cd48c89d3
hotspot
make
src/share/vm
classfile
classLoaderData.cppclassLoaderData.hppcompactHashtable.cppmoduleEntry.cppmoduleEntry.hppmodules.cpppackageEntry.cpppackageEntry.hppsystemDictionary.cppsystemDictionary.hpp
gc/shared
interpreter
runtime
utilities
test
TEST.groups
gc/g1/humongousObjects
native/runtime
runtime
Final
SharedArchiveFile
modules/ModuleStress
@ -45,7 +45,8 @@ ifeq ($(call check-jvm-feature, dtrace), true)
|
||||
$(DTRACE_GENSRC_DIR)/%.h: $(DTRACE_SOURCE_DIR)/%.d
|
||||
$(call LogInfo, Generating dtrace header file $(@F))
|
||||
$(call MakeDir, $(@D) $(DTRACE_SUPPORT_DIR))
|
||||
$(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).d, $(CC) -E $(DTRACE_CPP_FLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).d)
|
||||
$(call ExecuteWithLog, $(DTRACE_SUPPORT_DIR)/$(@F).d, \
|
||||
( $(CC) -E $(DTRACE_CPP_FLAGS) $< > $(DTRACE_SUPPORT_DIR)/$(@F).d ) )
|
||||
$(call ExecuteWithLog, $@, $(DTRACE) $(DTRACE_FLAGS) -h -o $@ -s $(DTRACE_SUPPORT_DIR)/$(@F).d)
|
||||
|
||||
# Process all .d files in DTRACE_SOURCE_DIR. They are:
|
||||
|
@ -68,7 +68,7 @@ ifeq ($(call check-jvm-feature, dtrace), true)
|
||||
$1: $$(BUILD_DTRACE_GEN_OFFSETS)
|
||||
$$(call LogInfo, Generating dtrace $2 file $$(@F))
|
||||
$$(call MakeDir, $$(@D))
|
||||
$$(call ExecuteWithLog, $$@, $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $$@)
|
||||
$$(call ExecuteWithLog, $$@, ( $$(DTRACE_GEN_OFFSETS_TOOL) -$$(strip $2) > $$@ ) )
|
||||
|
||||
TARGETS += $1
|
||||
endef
|
||||
|
@ -501,13 +501,26 @@ ClassLoaderData::~ClassLoaderData() {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if this class loader data is for the platform class loader.
|
||||
*/
|
||||
// Returns true if this class loader data is for the system class loader.
|
||||
bool ClassLoaderData::is_system_class_loader_data() const {
|
||||
return SystemDictionary::is_system_class_loader(class_loader());
|
||||
}
|
||||
|
||||
// Returns true if this class loader data is for the platform class loader.
|
||||
bool ClassLoaderData::is_platform_class_loader_data() const {
|
||||
return SystemDictionary::is_platform_class_loader(class_loader());
|
||||
}
|
||||
|
||||
// Returns true if this class loader data is one of the 3 builtin
|
||||
// (boot, application/system or platform) class loaders. Note, the
|
||||
// builtin loaders are not freed by a GC.
|
||||
bool ClassLoaderData::is_builtin_class_loader_data() const {
|
||||
Handle classLoaderHandle = class_loader();
|
||||
return (is_the_null_class_loader_data() ||
|
||||
SystemDictionary::is_system_class_loader(classLoaderHandle) ||
|
||||
SystemDictionary::is_platform_class_loader(classLoaderHandle));
|
||||
}
|
||||
|
||||
Metaspace* ClassLoaderData::metaspace_non_null() {
|
||||
assert(!DumpSharedSpaces, "wrong metaspace!");
|
||||
// If the metaspace has not been allocated, create a new one. Might want
|
||||
@ -957,12 +970,6 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure,
|
||||
data = _head;
|
||||
while (data != NULL) {
|
||||
if (data->is_alive(is_alive_closure)) {
|
||||
if (data->packages_defined()) {
|
||||
data->packages()->purge_all_package_exports();
|
||||
}
|
||||
if (data->modules_defined()) {
|
||||
data->modules()->purge_all_module_reads();
|
||||
}
|
||||
// clean metaspace
|
||||
if (walk_all_metadata) {
|
||||
data->classes_do(InstanceKlass::purge_previous_versions);
|
||||
@ -990,6 +997,23 @@ bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure,
|
||||
}
|
||||
|
||||
if (seen_dead_loader) {
|
||||
// Walk a ModuleEntry's reads and a PackageEntry's exports lists
|
||||
// to determine if there are modules on those lists that are now
|
||||
// dead and should be removed. A module's life cycle is equivalent
|
||||
// to its defining class loader's life cycle. Since a module is
|
||||
// considered dead if its class loader is dead, these walks must
|
||||
// occur after each class loader's aliveness is determined.
|
||||
data = _head;
|
||||
while (data != NULL) {
|
||||
if (data->packages_defined()) {
|
||||
data->packages()->purge_all_package_exports();
|
||||
}
|
||||
if (data->modules_defined()) {
|
||||
data->modules()->purge_all_module_reads();
|
||||
}
|
||||
data = data->next();
|
||||
}
|
||||
|
||||
post_class_unload_events();
|
||||
}
|
||||
|
||||
|
@ -270,7 +270,9 @@ class ClassLoaderData : public CHeapObj<mtClass> {
|
||||
bool is_the_null_class_loader_data() const {
|
||||
return this == _the_null_class_loader_data;
|
||||
}
|
||||
bool is_system_class_loader_data() const;
|
||||
bool is_platform_class_loader_data() const;
|
||||
bool is_builtin_class_loader_data() const;
|
||||
|
||||
// The Metaspace is created lazily so may be NULL. This
|
||||
// method will allocate a Metaspace if needed.
|
||||
|
@ -248,7 +248,7 @@ inline void SimpleCompactHashtable::iterate(const I& iterator) {
|
||||
} else {
|
||||
u4*entry_max = _entries + BUCKET_OFFSET(_buckets[i + 1]);
|
||||
while (entry < entry_max) {
|
||||
iterator.do_value(_base_address, entry[0]);
|
||||
iterator.do_value(_base_address, entry[1]);
|
||||
entry += 2;
|
||||
}
|
||||
}
|
||||
|
@ -40,7 +40,6 @@
|
||||
|
||||
ModuleEntry* ModuleEntryTable::_javabase_module = NULL;
|
||||
|
||||
|
||||
void ModuleEntry::set_location(Symbol* location) {
|
||||
if (_location != NULL) {
|
||||
// _location symbol's refcounts are managed by ModuleEntry,
|
||||
@ -115,10 +114,35 @@ void ModuleEntry::add_read(ModuleEntry* m) {
|
||||
// Lazily create a module's reads list
|
||||
_reads = new (ResourceObj::C_HEAP, mtModule)GrowableArray<ModuleEntry*>(MODULE_READS_SIZE, true);
|
||||
}
|
||||
|
||||
// Determine, based on this newly established read edge to module m,
|
||||
// if this module's read list should be walked at a GC safepoint.
|
||||
set_read_walk_required(m->loader_data());
|
||||
|
||||
// Establish readability to module m
|
||||
_reads->append_if_missing(m);
|
||||
}
|
||||
}
|
||||
|
||||
// If the module's loader, that a read edge is being established to, is
|
||||
// not the same loader as this module's and is not one of the 3 builtin
|
||||
// class loaders, then this module's reads list must be walked at GC
|
||||
// safepoint. Modules have the same life cycle as their defining class
|
||||
// loaders and should be removed if dead.
|
||||
void ModuleEntry::set_read_walk_required(ClassLoaderData* m_loader_data) {
|
||||
assert_locked_or_safepoint(Module_lock);
|
||||
if (!_must_walk_reads &&
|
||||
loader_data() != m_loader_data &&
|
||||
!m_loader_data->is_builtin_class_loader_data()) {
|
||||
_must_walk_reads = true;
|
||||
if (log_is_enabled(Trace, modules)) {
|
||||
ResourceMark rm;
|
||||
log_trace(modules)("ModuleEntry::set_read_walk_required(): module %s reads list must be walked",
|
||||
(name() != NULL) ? name()->as_C_string() : UNNAMED_MODULE);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ModuleEntry::has_reads() const {
|
||||
assert_locked_or_safepoint(Module_lock);
|
||||
return ((_reads != NULL) && !_reads->is_empty());
|
||||
@ -127,14 +151,28 @@ bool ModuleEntry::has_reads() const {
|
||||
// Purge dead module entries out of reads list.
|
||||
void ModuleEntry::purge_reads() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
|
||||
if (has_reads()) {
|
||||
|
||||
if (_must_walk_reads && has_reads()) {
|
||||
// This module's _must_walk_reads flag will be reset based
|
||||
// on the remaining live modules on the reads list.
|
||||
_must_walk_reads = false;
|
||||
|
||||
if (log_is_enabled(Trace, modules)) {
|
||||
ResourceMark rm;
|
||||
log_trace(modules)("ModuleEntry::purge_reads(): module %s reads list being walked",
|
||||
(name() != NULL) ? name()->as_C_string() : UNNAMED_MODULE);
|
||||
}
|
||||
|
||||
// Go backwards because this removes entries that are dead.
|
||||
int len = _reads->length();
|
||||
for (int idx = len - 1; idx >= 0; idx--) {
|
||||
ModuleEntry* module_idx = _reads->at(idx);
|
||||
ClassLoaderData* cld = module_idx->loader();
|
||||
if (cld->is_unloading()) {
|
||||
ClassLoaderData* cld_idx = module_idx->loader_data();
|
||||
if (cld_idx->is_unloading()) {
|
||||
_reads->delete_at(idx);
|
||||
} else {
|
||||
// Update the need to walk this module's reads based on live modules
|
||||
set_read_walk_required(cld_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -248,7 +286,7 @@ ModuleEntry* ModuleEntryTable::new_entry(unsigned int hash, Handle module_handle
|
||||
entry->set_module(loader_data->add_handle(module_handle));
|
||||
}
|
||||
|
||||
entry->set_loader(loader_data);
|
||||
entry->set_loader_data(loader_data);
|
||||
entry->set_version(version);
|
||||
entry->set_location(location);
|
||||
|
||||
@ -375,11 +413,11 @@ void ModuleEntryTable::print(outputStream* st) {
|
||||
|
||||
void ModuleEntry::print(outputStream* st) {
|
||||
ResourceMark rm;
|
||||
st->print_cr("entry "PTR_FORMAT" name %s module "PTR_FORMAT" loader %s version %s location %s strict %s next "PTR_FORMAT,
|
||||
st->print_cr("entry " PTR_FORMAT " name %s module " PTR_FORMAT " loader %s version %s location %s strict %s next " PTR_FORMAT,
|
||||
p2i(this),
|
||||
name() == NULL ? UNNAMED_MODULE : name()->as_C_string(),
|
||||
p2i(module()),
|
||||
loader()->loader_name(),
|
||||
loader_data()->loader_name(),
|
||||
version() != NULL ? version()->as_C_string() : "NULL",
|
||||
location() != NULL ? location()->as_C_string() : "NULL",
|
||||
BOOL_TO_STR(!can_read_all_unnamed()), p2i(next()));
|
||||
@ -401,5 +439,5 @@ void ModuleEntryTable::verify() {
|
||||
}
|
||||
|
||||
void ModuleEntry::verify() {
|
||||
guarantee(loader() != NULL, "A module entry must be associated with a loader.");
|
||||
guarantee(loader_data() != NULL, "A module entry must be associated with a loader.");
|
||||
}
|
||||
|
@ -43,6 +43,7 @@ class ModuleClosure;
|
||||
// It contains:
|
||||
// - Symbol* containing the module's name.
|
||||
// - pointer to the java.lang.reflect.Module for this module.
|
||||
// - pointer to the java.security.ProtectionDomain shared by classes defined to this module.
|
||||
// - ClassLoaderData*, class loader of this module.
|
||||
// - a growable array containg other module entries that this module can read.
|
||||
// - a flag indicating if this module can read all unnamed modules.
|
||||
@ -54,56 +55,58 @@ private:
|
||||
jobject _module; // java.lang.reflect.Module
|
||||
jobject _pd; // java.security.ProtectionDomain, cached
|
||||
// for shared classes from this module
|
||||
ClassLoaderData* _loader;
|
||||
ClassLoaderData* _loader_data;
|
||||
GrowableArray<ModuleEntry*>* _reads; // list of modules that are readable by this module
|
||||
Symbol* _version; // module version number
|
||||
Symbol* _location; // module location
|
||||
bool _can_read_all_unnamed;
|
||||
bool _has_default_read_edges; // JVMTI redefine/retransform support
|
||||
bool _must_walk_reads; // walk module's reads list at GC safepoints to purge out dead modules
|
||||
TRACE_DEFINE_TRACE_ID_FIELD;
|
||||
enum {MODULE_READS_SIZE = 101}; // Initial size of list of modules that the module can read.
|
||||
|
||||
public:
|
||||
void init() {
|
||||
_module = NULL;
|
||||
_loader = NULL;
|
||||
_loader_data = NULL;
|
||||
_pd = NULL;
|
||||
_reads = NULL;
|
||||
_version = NULL;
|
||||
_location = NULL;
|
||||
_can_read_all_unnamed = false;
|
||||
_has_default_read_edges = false;
|
||||
_must_walk_reads = false;
|
||||
}
|
||||
|
||||
Symbol* name() const { return literal(); }
|
||||
void set_name(Symbol* n) { set_literal(n); }
|
||||
Symbol* name() const { return literal(); }
|
||||
void set_name(Symbol* n) { set_literal(n); }
|
||||
|
||||
jobject module() const { return _module; }
|
||||
void set_module(jobject j) { _module = j; }
|
||||
jobject module() const { return _module; }
|
||||
void set_module(jobject j) { _module = j; }
|
||||
|
||||
// The shared ProtectionDomain reference is set once the VM loads a shared class
|
||||
// originated from the current Module. The referenced ProtectionDomain object is
|
||||
// created by the ClassLoader when loading a class (shared or non-shared) from the
|
||||
// Module for the first time. This ProtectionDomain object is used for all
|
||||
// classes from the Module loaded by the same ClassLoader.
|
||||
Handle shared_protection_domain();
|
||||
void set_shared_protection_domain(ClassLoaderData *loader_data,
|
||||
Handle pd);
|
||||
Handle shared_protection_domain();
|
||||
void set_shared_protection_domain(ClassLoaderData *loader_data, Handle pd);
|
||||
|
||||
ClassLoaderData* loader() const { return _loader; }
|
||||
void set_loader(ClassLoaderData* l) { _loader = l; }
|
||||
ClassLoaderData* loader_data() const { return _loader_data; }
|
||||
void set_loader_data(ClassLoaderData* l) { _loader_data = l; }
|
||||
|
||||
Symbol* version() const { return _version; }
|
||||
void set_version(Symbol* version);
|
||||
Symbol* version() const { return _version; }
|
||||
void set_version(Symbol* version);
|
||||
|
||||
Symbol* location() const { return _location; }
|
||||
void set_location(Symbol* location);
|
||||
Symbol* location() const { return _location; }
|
||||
void set_location(Symbol* location);
|
||||
|
||||
bool can_read(ModuleEntry* m) const;
|
||||
bool has_reads() const;
|
||||
void add_read(ModuleEntry* m);
|
||||
bool can_read(ModuleEntry* m) const;
|
||||
bool has_reads() const;
|
||||
void add_read(ModuleEntry* m);
|
||||
void set_read_walk_required(ClassLoaderData* m_loader_data);
|
||||
|
||||
bool is_named() const { return (literal() != NULL); }
|
||||
bool is_named() const { return (name() != NULL); }
|
||||
|
||||
bool can_read_all_unnamed() const {
|
||||
assert(is_named() || _can_read_all_unnamed == true,
|
||||
@ -178,7 +181,7 @@ private:
|
||||
ModuleEntry* _unnamed_module;
|
||||
|
||||
ModuleEntry* new_entry(unsigned int hash, Handle module_handle, Symbol* name, Symbol* version,
|
||||
Symbol* location, ClassLoaderData* class_loader);
|
||||
Symbol* location, ClassLoaderData* loader_data);
|
||||
void add_entry(int index, ModuleEntry* new_entry);
|
||||
|
||||
int entry_size() const { return BasicHashtable<mtModule>::entry_size(); }
|
||||
|
@ -113,7 +113,7 @@ static PackageEntry* get_package_entry(ModuleEntry* module_entry, jstring packag
|
||||
const char *package_name = java_lang_String::as_utf8_string(JNIHandles::resolve_non_null(package));
|
||||
if (package_name == NULL) return NULL;
|
||||
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK_NULL);
|
||||
PackageEntryTable* package_entry_table = module_entry->loader()->packages();
|
||||
PackageEntryTable* package_entry_table = module_entry->loader_data()->packages();
|
||||
assert(package_entry_table != NULL, "Unexpected null package entry table");
|
||||
return package_entry_table->lookup_only(pkg_symbol);
|
||||
}
|
||||
@ -868,7 +868,7 @@ void Modules::add_module_package(jobject module, jstring package, TRAPS) {
|
||||
package_name, module_entry->name()->as_C_string());
|
||||
|
||||
TempNewSymbol pkg_symbol = SymbolTable::new_symbol(package_name, CHECK);
|
||||
PackageEntryTable* package_table = module_entry->loader()->packages();
|
||||
PackageEntryTable* package_table = module_entry->loader_data()->packages();
|
||||
assert(package_table != NULL, "Missing package_table");
|
||||
|
||||
bool pkg_exists = false;
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "precompiled.hpp"
|
||||
#include "classfile/moduleEntry.hpp"
|
||||
#include "classfile/packageEntry.hpp"
|
||||
#include "logging/log.hpp"
|
||||
#include "memory/resourceArea.hpp"
|
||||
#include "oops/symbol.hpp"
|
||||
#include "runtime/handles.inline.hpp"
|
||||
@ -53,12 +54,40 @@ void PackageEntry::add_qexport(ModuleEntry* m) {
|
||||
if (!has_qual_exports_list()) {
|
||||
// Lazily create a package's qualified exports list.
|
||||
// Initial size is small, do not anticipate export lists to be large.
|
||||
_qualified_exports =
|
||||
new (ResourceObj::C_HEAP, mtModule) GrowableArray<ModuleEntry*>(QUAL_EXP_SIZE, true);
|
||||
_qualified_exports = new (ResourceObj::C_HEAP, mtModule) GrowableArray<ModuleEntry*>(QUAL_EXP_SIZE, true);
|
||||
}
|
||||
|
||||
// Determine, based on this newly established export to module m,
|
||||
// if this package's export list should be walked at a GC safepoint.
|
||||
set_export_walk_required(m->loader_data());
|
||||
|
||||
// Establish exportability to module m
|
||||
_qualified_exports->append_if_missing(m);
|
||||
}
|
||||
|
||||
// If the module's loader, that an export is being established to, is
|
||||
// not the same loader as this module's and is not one of the 3 builtin
|
||||
// class loaders, then this package's export list must be walked at GC
|
||||
// safepoint. Modules have the same life cycle as their defining class
|
||||
// loaders and should be removed if dead.
|
||||
void PackageEntry::set_export_walk_required(ClassLoaderData* m_loader_data) {
|
||||
assert_locked_or_safepoint(Module_lock);
|
||||
ModuleEntry* this_pkg_mod = module();
|
||||
if (!_must_walk_exports &&
|
||||
(this_pkg_mod == NULL || this_pkg_mod->loader_data() != m_loader_data) &&
|
||||
!m_loader_data->is_builtin_class_loader_data()) {
|
||||
_must_walk_exports = true;
|
||||
if (log_is_enabled(Trace, modules)) {
|
||||
ResourceMark rm;
|
||||
assert(name() != NULL, "PackageEntry without a valid name");
|
||||
log_trace(modules)("PackageEntry::set_export_walk_required(): package %s defined in module %s, exports list must be walked",
|
||||
name()->as_C_string(),
|
||||
(this_pkg_mod == NULL || this_pkg_mod->name() == NULL) ?
|
||||
UNNAMED_MODULE : this_pkg_mod->name()->as_C_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Set the package's exported states based on the value of the ModuleEntry.
|
||||
void PackageEntry::set_exported(ModuleEntry* m) {
|
||||
MutexLocker m1(Module_lock);
|
||||
@ -96,14 +125,34 @@ void PackageEntry::set_is_exported_allUnnamed() {
|
||||
// Remove dead module entries within the package's exported list.
|
||||
void PackageEntry::purge_qualified_exports() {
|
||||
assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
|
||||
if (_qualified_exports != NULL) {
|
||||
if (_must_walk_exports &&
|
||||
_qualified_exports != NULL &&
|
||||
!_qualified_exports->is_empty()) {
|
||||
ModuleEntry* pkg_module = module();
|
||||
|
||||
// This package's _must_walk_exports flag will be reset based
|
||||
// on the remaining live modules on the exports list.
|
||||
_must_walk_exports = false;
|
||||
|
||||
if (log_is_enabled(Trace, modules)) {
|
||||
ResourceMark rm;
|
||||
assert(name() != NULL, "PackageEntry without a valid name");
|
||||
ModuleEntry* pkg_mod = module();
|
||||
log_trace(modules)("PackageEntry::purge_qualified_exports(): package %s defined in module %s, exports list being walked",
|
||||
name()->as_C_string(),
|
||||
(pkg_mod == NULL || pkg_mod->name() == NULL) ? UNNAMED_MODULE : pkg_mod->name()->as_C_string());
|
||||
}
|
||||
|
||||
// Go backwards because this removes entries that are dead.
|
||||
int len = _qualified_exports->length();
|
||||
for (int idx = len - 1; idx >= 0; idx--) {
|
||||
ModuleEntry* module_idx = _qualified_exports->at(idx);
|
||||
ClassLoaderData* cld = module_idx->loader();
|
||||
if (cld->is_unloading()) {
|
||||
ClassLoaderData* cld_idx = module_idx->loader_data();
|
||||
if (cld_idx->is_unloading()) {
|
||||
_qualified_exports->delete_at(idx);
|
||||
} else {
|
||||
// Update the need to walk this package's exports based on live modules
|
||||
set_export_walk_required(cld_idx);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -297,8 +346,8 @@ void PackageEntryTable::print(outputStream* st) {
|
||||
|
||||
void PackageEntry::print(outputStream* st) {
|
||||
ResourceMark rm;
|
||||
st->print_cr("package entry "PTR_FORMAT" name %s module %s classpath_index "
|
||||
INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next "PTR_FORMAT,
|
||||
st->print_cr("package entry " PTR_FORMAT " name %s module %s classpath_index "
|
||||
INT32_FORMAT " is_exported_unqualified %d is_exported_allUnnamed %d " "next " PTR_FORMAT,
|
||||
p2i(this), name()->as_C_string(),
|
||||
(module()->is_named() ? module()->name()->as_C_string() : UNNAMED_MODULE),
|
||||
_classpath_index, _is_exported_unqualified, _is_exported_allUnnamed, p2i(next()));
|
||||
|
@ -69,6 +69,7 @@ private:
|
||||
s2 _classpath_index;
|
||||
bool _is_exported_unqualified;
|
||||
bool _is_exported_allUnnamed;
|
||||
bool _must_walk_exports;
|
||||
GrowableArray<ModuleEntry*>* _exported_pending_delete; // transitioned from qualified to unqualified, delete at safepoint
|
||||
GrowableArray<ModuleEntry*>* _qualified_exports;
|
||||
TRACE_DEFINE_TRACE_ID_FIELD;
|
||||
@ -82,6 +83,7 @@ public:
|
||||
_classpath_index = -1;
|
||||
_is_exported_unqualified = false;
|
||||
_is_exported_allUnnamed = false;
|
||||
_must_walk_exports = false;
|
||||
_exported_pending_delete = NULL;
|
||||
_qualified_exports = NULL;
|
||||
}
|
||||
@ -147,6 +149,7 @@ public:
|
||||
|
||||
// add the module to the package's qualified exports
|
||||
void add_qexport(ModuleEntry* m);
|
||||
void set_export_walk_required(ClassLoaderData* m_loader_data);
|
||||
|
||||
PackageEntry* next() const {
|
||||
return (PackageEntry*)HashtableEntry<Symbol*, mtModule>::next();
|
||||
|
@ -175,9 +175,18 @@ bool SystemDictionary::is_parallelDefine(Handle class_loader) {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the passed class loader is the platform class loader.
|
||||
*/
|
||||
// Returns true if the passed class loader is the builtin application class loader
|
||||
// or a custom system class loader. A customer system class loader can be
|
||||
// specified via -Djava.system.class.loader.
|
||||
bool SystemDictionary::is_system_class_loader(Handle class_loader) {
|
||||
if (class_loader.is_null()) {
|
||||
return false;
|
||||
}
|
||||
return (class_loader->klass() == SystemDictionary::jdk_internal_loader_ClassLoaders_AppClassLoader_klass() ||
|
||||
class_loader() == _java_system_loader);
|
||||
}
|
||||
|
||||
// Returns true if the passed class loader is the platform class loader.
|
||||
bool SystemDictionary::is_platform_class_loader(Handle class_loader) {
|
||||
if (class_loader.is_null()) {
|
||||
return false;
|
||||
|
@ -660,6 +660,7 @@ public:
|
||||
static instanceKlassHandle load_shared_class(Symbol* class_name,
|
||||
Handle class_loader,
|
||||
TRAPS);
|
||||
static bool is_system_class_loader(Handle class_loader);
|
||||
static bool is_platform_class_loader(Handle class_loader);
|
||||
|
||||
protected:
|
||||
|
@ -48,10 +48,10 @@ void PreservedMarks::restore_and_increment(volatile size_t* const total_size_add
|
||||
|
||||
#ifndef PRODUCT
|
||||
void PreservedMarks::assert_empty() {
|
||||
assert(_stack.is_empty(), "stack expected to be empty, size = "SIZE_FORMAT,
|
||||
assert(_stack.is_empty(), "stack expected to be empty, size = " SIZE_FORMAT,
|
||||
_stack.size());
|
||||
assert(_stack.cache_size() == 0,
|
||||
"stack expected to have no cached segments, cache size = "SIZE_FORMAT,
|
||||
"stack expected to have no cached segments, cache size = " SIZE_FORMAT,
|
||||
_stack.cache_size());
|
||||
}
|
||||
#endif // ndef PRODUCT
|
||||
|
@ -419,21 +419,20 @@ void Rewriter::scan_method(Method* method, bool reverse, bool* invokespecial_err
|
||||
InstanceKlass* klass = method->method_holder();
|
||||
u2 bc_index = Bytes::get_Java_u2(bcp + prefix_length + 1);
|
||||
constantPoolHandle cp(method->constants());
|
||||
Symbol* field_name = cp->name_ref_at(bc_index);
|
||||
Symbol* field_sig = cp->signature_ref_at(bc_index);
|
||||
Symbol* ref_class_name = cp->klass_name_at(cp->klass_ref_index_at(bc_index));
|
||||
|
||||
if (klass->name() == ref_class_name) {
|
||||
Symbol* field_name = cp->name_ref_at(bc_index);
|
||||
Symbol* field_sig = cp->signature_ref_at(bc_index);
|
||||
|
||||
fieldDescriptor fd;
|
||||
klass->find_field(field_name, field_sig, &fd);
|
||||
if (fd.access_flags().is_final()) {
|
||||
if (fd.access_flags().is_static()) {
|
||||
assert(c == Bytecodes::_putstatic, "must be putstatic");
|
||||
if (!method->is_static_initializer()) {
|
||||
fd.set_has_initialized_final_update(true);
|
||||
}
|
||||
} else {
|
||||
assert(c == Bytecodes::_putfield, "must be putfield");
|
||||
if (!method->is_object_initializer()) {
|
||||
fd.set_has_initialized_final_update(true);
|
||||
}
|
||||
|
@ -584,27 +584,26 @@ static bool verify_special_jvm_flags() {
|
||||
// Parses a size specification string.
|
||||
bool Arguments::atojulong(const char *s, julong* result) {
|
||||
julong n = 0;
|
||||
int args_read = 0;
|
||||
bool is_hex = false;
|
||||
// Skip leading 0[xX] for hexadecimal
|
||||
if (*s =='0' && (*(s+1) == 'x' || *(s+1) == 'X')) {
|
||||
s += 2;
|
||||
is_hex = true;
|
||||
args_read = sscanf(s, JULONG_FORMAT_X, &n);
|
||||
} else {
|
||||
args_read = sscanf(s, JULONG_FORMAT, &n);
|
||||
}
|
||||
if (args_read != 1) {
|
||||
|
||||
// First char must be a digit. Don't allow negative numbers or leading spaces.
|
||||
if (!isdigit(*s)) {
|
||||
return false;
|
||||
}
|
||||
while (*s != '\0' && (isdigit(*s) || (is_hex && isxdigit(*s)))) {
|
||||
s++;
|
||||
}
|
||||
// 4705540: illegal if more characters are found after the first non-digit
|
||||
if (strlen(s) > 1) {
|
||||
|
||||
bool is_hex = (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'));
|
||||
char* remainder;
|
||||
errno = 0;
|
||||
n = strtoull(s, &remainder, (is_hex ? 16 : 10));
|
||||
if (errno != 0) {
|
||||
return false;
|
||||
}
|
||||
switch (*s) {
|
||||
|
||||
// Fail if no number was read at all or if the remainder contains more than a single non-digit character.
|
||||
if (remainder == s || strlen(remainder) > 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (*remainder) {
|
||||
case 'T': case 't':
|
||||
*result = n * G * K;
|
||||
// Check for overflow.
|
||||
|
@ -205,16 +205,39 @@ void VMError::print_stack_trace(outputStream* st, JavaThread* jt,
|
||||
static void print_oom_reasons(outputStream* st) {
|
||||
st->print_cr("# Possible reasons:");
|
||||
st->print_cr("# The system is out of physical RAM or swap space");
|
||||
st->print_cr("# In 32 bit mode, the process size limit was hit");
|
||||
if (UseCompressedOops) {
|
||||
st->print_cr("# The process is running with CompressedOops enabled, and the Java Heap may be blocking the growth of the native heap");
|
||||
}
|
||||
if (LogBytesPerWord == 2) {
|
||||
st->print_cr("# In 32 bit mode, the process size limit was hit");
|
||||
}
|
||||
st->print_cr("# Possible solutions:");
|
||||
st->print_cr("# Reduce memory load on the system");
|
||||
st->print_cr("# Increase physical memory or swap space");
|
||||
st->print_cr("# Check if swap backing store is full");
|
||||
st->print_cr("# Use 64 bit Java on a 64 bit OS");
|
||||
if (LogBytesPerWord == 2) {
|
||||
st->print_cr("# Use 64 bit Java on a 64 bit OS");
|
||||
}
|
||||
st->print_cr("# Decrease Java heap size (-Xmx/-Xms)");
|
||||
st->print_cr("# Decrease number of Java threads");
|
||||
st->print_cr("# Decrease Java thread stack sizes (-Xss)");
|
||||
st->print_cr("# Set larger code cache with -XX:ReservedCodeCacheSize=");
|
||||
if (UseCompressedOops) {
|
||||
switch (Universe::narrow_oop_mode()) {
|
||||
case Universe::UnscaledNarrowOop:
|
||||
st->print_cr("# JVM is running with Unscaled Compressed Oops mode in which the Java heap is");
|
||||
st->print_cr("# placed in the first 4GB address space. The Java Heap base address is the");
|
||||
st->print_cr("# maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress");
|
||||
st->print_cr("# to set the Java Heap base and to place the Java Heap above 4GB virtual address.");
|
||||
break;
|
||||
case Universe::ZeroBasedNarrowOop:
|
||||
st->print_cr("# JVM is running with Zero Based Compressed Oops mode in which the Java heap is");
|
||||
st->print_cr("# placed in the first 32GB address space. The Java Heap base address is the");
|
||||
st->print_cr("# maximum limit for the native heap growth. Please use -XX:HeapBaseMinAddress");
|
||||
st->print_cr("# to set the Java Heap base and to place the Java Heap above 32GB virtual address.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
st->print_cr("# This output file may be truncated or incomplete.");
|
||||
}
|
||||
|
||||
|
@ -395,6 +395,17 @@ hotspot_jprt = \
|
||||
:hotspot_fast_gc_gcold \
|
||||
:hotspot_fast_runtime \
|
||||
:hotspot_fast_serviceability
|
||||
|
||||
hotspot_runtime_tier2 = \
|
||||
runtime/ \
|
||||
serviceability/ \
|
||||
-:hotspot_fast_runtime \
|
||||
-:hotspot_fast_serviceability \
|
||||
-:hotspot_runtime_tier2_platform_agnostic
|
||||
|
||||
hotspot_runtime_tier2_platform_agnostic = \
|
||||
runtime/SelectionResolution \
|
||||
-:hotspot_fast_runtime
|
||||
|
||||
#All tests that depends on nashorn extension.
|
||||
#
|
||||
|
@ -0,0 +1,234 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
|
||||
package gc.g1.humongousObjects;
|
||||
|
||||
import jdk.test.lib.Utils;
|
||||
import sun.hotspot.WhiteBox;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @test TestNoAllocationsInHRegions
|
||||
* @summary Checks that no additional allocations are made in humongous regions
|
||||
* @requires vm.gc.G1
|
||||
* @library /testlibrary /test/lib /
|
||||
* @modules java.management java.base/jdk.internal.misc
|
||||
* @build sun.hotspot.WhiteBox
|
||||
* gc.testlibrary.Helpers
|
||||
* gc.g1.humongousObjects.TestNoAllocationsInHRegions
|
||||
*
|
||||
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
*
|
||||
* @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:G1HeapRegionSize=1M -Xms200m -Xmx200m -XX:MaxTenuringThreshold=0
|
||||
* -Xlog:gc=trace:file=TestNoAllocationsInHRegions10.log
|
||||
* gc.g1.humongousObjects.TestNoAllocationsInHRegions 30 10
|
||||
*
|
||||
* @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:G1HeapRegionSize=1M -Xms200m -Xmx200m -XX:MaxTenuringThreshold=0
|
||||
* -Xlog:gc=trace:file=TestNoAllocationsInHRegions50.log
|
||||
* gc.g1.humongousObjects.TestNoAllocationsInHRegions 30 50
|
||||
*
|
||||
* @run main/othervm -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:G1HeapRegionSize=1M -Xms200m -Xmx200m -XX:MaxTenuringThreshold=0
|
||||
* -Xlog:gc=trace:file=TestNoAllocationsInHRegions70.log
|
||||
* gc.g1.humongousObjects.TestNoAllocationsInHRegions 30 70
|
||||
*/
|
||||
public class TestNoAllocationsInHRegions {
|
||||
private static final WhiteBox WB = WhiteBox.getWhiteBox();
|
||||
private static final Random RND = Utils.getRandomInstance();
|
||||
private static final int G1_REGION_SIZE = WB.g1RegionSize();
|
||||
private static final int[] HUMONGOUS_SIZES = {G1_REGION_SIZE / 2, G1_REGION_SIZE + 1, G1_REGION_SIZE * 2 + 1};
|
||||
private static final int ALLOC_THREAD_COUNT = 5;
|
||||
|
||||
// We fill specified part of heap with humongous objects - we need public static to prevent escape analysis to
|
||||
// collect this field
|
||||
public static LinkedList<byte[]> humongousAllocations = new LinkedList<>();
|
||||
|
||||
private static volatile boolean shouldStop = false;
|
||||
private static volatile Error error = null;
|
||||
|
||||
static class Allocator implements Runnable {
|
||||
|
||||
private final List<byte[]> liveObjects = new LinkedList<>();
|
||||
private int usedMemory = 0;
|
||||
public final Runnable[] actions;
|
||||
|
||||
/**
|
||||
* Maximum size of simple allocation
|
||||
*/
|
||||
private static final int MAX_ALLOCATION_SIZE = (int) (G1_REGION_SIZE / 2 * 0.9);
|
||||
|
||||
/**
|
||||
* Maximum size of dead (i.e. one which is made unreachable right after allocation) object
|
||||
*/
|
||||
private static final int DEAD_OBJECT_MAX_SIZE = G1_REGION_SIZE / 10;
|
||||
|
||||
public Allocator(int maxAllocationMemory) {
|
||||
|
||||
actions = new Runnable[]{
|
||||
// Allocation
|
||||
() -> {
|
||||
if (maxAllocationMemory - usedMemory != 0) {
|
||||
int arraySize = RND.nextInt(Math.min(maxAllocationMemory - usedMemory,
|
||||
MAX_ALLOCATION_SIZE));
|
||||
|
||||
if (arraySize != 0) {
|
||||
byte[] allocation = new byte[arraySize];
|
||||
liveObjects.add(allocation);
|
||||
usedMemory += arraySize;
|
||||
|
||||
// Sanity check
|
||||
if (WB.g1IsHumongous(allocation)) {
|
||||
String errorMessage = String.format("Test Bug: Byte array of size"
|
||||
+ " %d is expected to be non-humongous but it is humongous",
|
||||
allocation.length);
|
||||
|
||||
System.out.println(errorMessage);
|
||||
error = new Error(errorMessage);
|
||||
shouldStop = true;
|
||||
}
|
||||
|
||||
// Test check
|
||||
if (WB.g1BelongsToHumongousRegion(WB.getObjectAddress(allocation))) {
|
||||
String errorMessage = String.format("Non-humongous allocation of byte array of "
|
||||
+ "length %d and size %d with address %d was made in Humongous Region",
|
||||
allocation.length, WB.getObjectSize(allocation),
|
||||
WB.getObjectAddress(allocation));
|
||||
|
||||
System.out.println(errorMessage);
|
||||
error = new Error(errorMessage);
|
||||
shouldStop = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Deallocation
|
||||
() -> {
|
||||
if (liveObjects.size() != 0) {
|
||||
int elementNum = RND.nextInt(liveObjects.size());
|
||||
int shouldFree = liveObjects.get(elementNum).length;
|
||||
liveObjects.remove(elementNum);
|
||||
usedMemory -= shouldFree;
|
||||
}
|
||||
},
|
||||
|
||||
// Dead object allocation
|
||||
() -> {
|
||||
int size = RND.nextInt(DEAD_OBJECT_MAX_SIZE);
|
||||
byte[] deadObject = new byte[size];
|
||||
},
|
||||
|
||||
// Check
|
||||
() -> {
|
||||
List<byte[]> wrongHumongousAllocations = liveObjects.stream()
|
||||
.filter(WB::g1IsHumongous)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (wrongHumongousAllocations.size() > 0) {
|
||||
wrongHumongousAllocations.stream().forEach(a ->
|
||||
System.out.format("Non-humongous allocation of byte array of length %d and"
|
||||
+ " size %d with address %d was made in Humongous Region",
|
||||
a.length, WB.getObjectSize(a), WB.getObjectAddress(a)));
|
||||
error = new Error("Some non-humongous allocations were made to humongous region");
|
||||
shouldStop = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
while (!shouldStop) {
|
||||
actions[RND.nextInt(actions.length)].run();
|
||||
Thread.yield();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
if (args.length != 2) {
|
||||
throw new Error("Test Bug: Expected duration (in seconds) and percent of allocated regions were not "
|
||||
+ "provided as command line argument");
|
||||
}
|
||||
|
||||
// test duration
|
||||
long duration = Integer.parseInt(args[0]) * 1000L;
|
||||
// part of heap preallocated with humongous objects (in percents)
|
||||
int percentOfAllocatedHeap = Integer.parseInt(args[1]);
|
||||
|
||||
long startTime = System.currentTimeMillis();
|
||||
|
||||
long initialFreeRegionsCount = WB.g1NumFreeRegions();
|
||||
int regionsToAllocate = (int) ((double) initialFreeRegionsCount / 100.0 * percentOfAllocatedHeap);
|
||||
long freeRegionLeft = initialFreeRegionsCount - regionsToAllocate;
|
||||
|
||||
System.out.println("Regions to allocate: " + regionsToAllocate + "; regions to left free: " + freeRegionLeft);
|
||||
|
||||
int maxMemoryPerAllocThread = (int) ((Runtime.getRuntime().freeMemory() / 100.0
|
||||
* (100 - percentOfAllocatedHeap)) / ALLOC_THREAD_COUNT * 0.5);
|
||||
|
||||
System.out.println("Using " + maxMemoryPerAllocThread / 1024 + "KB for each of " + ALLOC_THREAD_COUNT
|
||||
+ " allocation threads");
|
||||
|
||||
while (WB.g1NumFreeRegions() > freeRegionLeft) {
|
||||
try {
|
||||
humongousAllocations.add(new byte[HUMONGOUS_SIZES[RND.nextInt(HUMONGOUS_SIZES.length)]]);
|
||||
} catch (OutOfMemoryError oom) {
|
||||
//We got OOM trying to fill heap with humongous objects
|
||||
//It probably means that heap is fragmented which is strange since the test logic should avoid it
|
||||
System.out.println("Warning: OOM while allocating humongous objects - it likely means "
|
||||
+ "that heap is fragmented");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("Initial free regions " + initialFreeRegionsCount + "; Free regions left "
|
||||
+ WB.g1NumFreeRegions());
|
||||
|
||||
LinkedList<Thread> threads = new LinkedList<>();
|
||||
|
||||
for (int i = 0; i < ALLOC_THREAD_COUNT; i++) {
|
||||
threads.add(new Thread(new Allocator(maxMemoryPerAllocThread)));
|
||||
}
|
||||
|
||||
threads.stream().forEach(Thread::start);
|
||||
|
||||
while ((System.currentTimeMillis() - startTime < duration) && error == null) {
|
||||
Thread.yield();
|
||||
}
|
||||
|
||||
shouldStop = true;
|
||||
System.out.println("Finished test");
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
@ -138,6 +138,41 @@ public enum GC {
|
||||
}
|
||||
},
|
||||
|
||||
MIXED_GC {
|
||||
@Override
|
||||
public Runnable get() {
|
||||
return () -> {
|
||||
WHITE_BOX.youngGC();
|
||||
Helpers.waitTillCMCFinished(WHITE_BOX, 0);
|
||||
WHITE_BOX.youngGC();
|
||||
Helpers.waitTillCMCFinished(WHITE_BOX, 0);
|
||||
|
||||
WHITE_BOX.g1StartConcMarkCycle();
|
||||
Helpers.waitTillCMCFinished(WHITE_BOX, 0);
|
||||
|
||||
WHITE_BOX.youngGC();
|
||||
Helpers.waitTillCMCFinished(WHITE_BOX, 0);
|
||||
// Provoking Mixed GC
|
||||
WHITE_BOX.youngGC();// second evacuation pause will be mixed
|
||||
Helpers.waitTillCMCFinished(WHITE_BOX, 0);
|
||||
};
|
||||
}
|
||||
|
||||
public Consumer<ReferenceInfo<Object[]>> getChecker() {
|
||||
return getCheckerImpl(true, false, true, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> shouldContain() {
|
||||
return Arrays.asList(GCTokens.WB_INITIATED_CMC);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> shouldNotContain() {
|
||||
return Arrays.asList(GCTokens.YOUNG_GC);
|
||||
}
|
||||
},
|
||||
|
||||
FULL_GC_MEMORY_PRESSURE {
|
||||
@Override
|
||||
public Runnable get() {
|
||||
|
@ -38,6 +38,9 @@ The test checks that after different type of GC unreachable objects behave as ex
|
||||
non-humongous and humongous objects are not collected since we make 2 Young GC to promote all
|
||||
weak references to Old Gen.
|
||||
|
||||
6. Mixed GC - weakly referenced non-humongous and humongous objects are collected, softly referenced non-humongous and
|
||||
humongous objects are not collected.
|
||||
|
||||
The test gets gc type as a command line argument.
|
||||
Then the test allocates object graph in heap (currently testing scenarios are pre-generated and stored in
|
||||
TestcaseData.getPregeneratedTestcases()) with TestObjectGraphAfterGC::allocateObjectGraph.
|
||||
|
@ -66,6 +66,12 @@ import java.util.stream.Collectors;
|
||||
* sun.hotspot.WhiteBox$WhiteBoxPermission
|
||||
*
|
||||
* @run main/othervm -Xms200M -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:+UnlockExperimentalVMOptions -XX:MaxGCPauseMillis=30000 -XX:G1MixedGCLiveThresholdPercent=100 -XX:G1HeapWastePercent=0
|
||||
* -XX:G1HeapRegionSize=1M -Xlog:gc=info:file=TestObjectGraphAfterGC_MIXED_GC.gc.log -XX:MaxTenuringThreshold=1
|
||||
* -XX:G1MixedGCCountTarget=1 -XX:G1OldCSetRegionThresholdPercent=100 -XX:SurvivorRatio=1 -XX:InitiatingHeapOccupancyPercent=0
|
||||
* gc.g1.humongousObjects.objectGraphTest.TestObjectGraphAfterGC MIXED_GC
|
||||
*
|
||||
* @run main/othervm -Xms200M -XX:+UseG1GC -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:.
|
||||
* -XX:G1HeapRegionSize=1M -Xlog:gc*=debug:file=TestObjectGraphAfterGC_YOUNG_GC.gc.log
|
||||
* gc.g1.humongousObjects.objectGraphTest.TestObjectGraphAfterGC YOUNG_GC
|
||||
*
|
||||
|
71
hotspot/test/native/runtime/test_arguments.cpp
Normal file
71
hotspot/test/native/runtime/test_arguments.cpp
Normal file
@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*
|
||||
*/
|
||||
#include "precompiled.hpp"
|
||||
#include "runtime/arguments.hpp"
|
||||
#include "unittest.hpp"
|
||||
#include "utilities/globalDefinitions.hpp"
|
||||
|
||||
TEST(arguments, atojulong) {
|
||||
char ullong_max[32];
|
||||
int ret = jio_snprintf(ullong_max, sizeof(ullong_max), JULONG_FORMAT, ULLONG_MAX);
|
||||
ASSERT_NE(-1, ret);
|
||||
|
||||
julong value;
|
||||
const char* invalid_strings[] = {
|
||||
"", "-1", "-100", " 1", "2 ", "3 2", "1.0",
|
||||
"0x4.5", "0x", "0x0x1" "0.001", "4e10", "e"
|
||||
"K", "M", "G", "1MB", "1KM", "AA", "0B",
|
||||
"18446744073709551615K", "17179869184G",
|
||||
"999999999999999999999999999999"
|
||||
};
|
||||
for (uint i = 0; i < ARRAY_SIZE(invalid_strings); i++) {
|
||||
ASSERT_FALSE(Arguments::atojulong(invalid_strings[i], &value))
|
||||
<< "Invalid string '" << invalid_strings[i] << "' parsed without error.";
|
||||
}
|
||||
|
||||
struct {
|
||||
const char* str;
|
||||
julong expected_value;
|
||||
} valid_strings[] = {
|
||||
{ "0", 0 },
|
||||
{ "4711", 4711 },
|
||||
{ "1K", 1ULL * K },
|
||||
{ "1k", 1ULL * K },
|
||||
{ "2M", 2ULL * M },
|
||||
{ "2m", 2ULL * M },
|
||||
{ "4G", 4ULL * G },
|
||||
{ "4g", 4ULL * G },
|
||||
{ "0K", 0 },
|
||||
{ ullong_max, ULLONG_MAX },
|
||||
{ "0xcafebabe", 0xcafebabe },
|
||||
{ "0XCAFEBABE", 0xcafebabe },
|
||||
{ "0XCAFEbabe", 0xcafebabe },
|
||||
{ "0x10K", 0x10 * K }
|
||||
};
|
||||
for (uint i = 0; i < ARRAY_SIZE(valid_strings); i++) {
|
||||
ASSERT_TRUE(Arguments::atojulong(valid_strings[i].str, &value))
|
||||
<< "Valid string '" << valid_strings[i].str << "' did not parse.";
|
||||
ASSERT_EQ(valid_strings[i].expected_value, value);
|
||||
}
|
||||
}
|
55
hotspot/test/runtime/Final/Bad.jasm
Normal file
55
hotspot/test/runtime/Final/Bad.jasm
Normal file
@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/* Recoded in jasm to provoke an ICCE assigning a non-static final field with putstatic.
|
||||
class Bad {
|
||||
public static final int i; //rewritten
|
||||
//rewritten to: public final int i;
|
||||
static { i = 5; } // putstatic instruction
|
||||
}
|
||||
*/
|
||||
|
||||
super class Bad
|
||||
version 53:0
|
||||
{
|
||||
|
||||
// Remove 'static' keyword
|
||||
public final Field i:I;
|
||||
|
||||
Method "<init>":"()V"
|
||||
stack 1 locals 1
|
||||
{
|
||||
aload_0;
|
||||
invokespecial Method java/lang/Object."<init>":"()V";
|
||||
return;
|
||||
}
|
||||
|
||||
static Method "<clinit>":"()V"
|
||||
stack 1 locals 0
|
||||
{
|
||||
iconst_5;
|
||||
putstatic Field i:"I";
|
||||
return;
|
||||
}
|
||||
|
||||
} // end Class Bad
|
42
hotspot/test/runtime/Final/PutfieldError.java
Normal file
42
hotspot/test/runtime/Final/PutfieldError.java
Normal file
@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test PutfieldError
|
||||
* @bug 8160551
|
||||
* @summary Throw ICCE rather than crashing for nonstatic final field in static initializer
|
||||
* @compile Bad.jasm
|
||||
* @run main PutfieldError
|
||||
*/
|
||||
|
||||
public class PutfieldError {
|
||||
public static void main(java.lang.String[] unused) {
|
||||
try {
|
||||
Bad b = new Bad();
|
||||
System.out.println("Bad.i = " + 5);
|
||||
throw new RuntimeException("ICCE NOT thrown as expected");
|
||||
} catch (IncompatibleClassChangeError icce) {
|
||||
System.out.println("ICCE thrown as expected");
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test SharedStringsDedup
|
||||
* @summary Test -Xshare:auto with shared strings and -XX:+UseStringDeduplication
|
||||
* Feature support: G1GC only, compressed oops/kptrs, 64-bit os, not on windows
|
||||
* @requires (sun.arch.data.model != "32") & (os.family != "windows")
|
||||
* @requires (vm.opt.UseCompressedOops == null) | (vm.opt.UseCompressedOops == true)
|
||||
* @requires vm.gc.G1
|
||||
* @library /testlibrary
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* java.management
|
||||
* @run main SharedStringsDedup
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
import java.io.File;
|
||||
|
||||
// The main purpose is to test the interaction between shared strings
|
||||
// and -XX:+UseStringDeduplication. We run in -Xshare:auto mode so
|
||||
// we don't need to worry about CDS archive mapping failure (which
|
||||
// doesn't happen often so it won't impact coverage).
|
||||
public class SharedStringsDedup {
|
||||
public static void main(String[] args) throws Exception {
|
||||
// Dump
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:SharedArchiveFile=./SharedStringsDedup.jsa",
|
||||
"-XX:+UseCompressedOops", "-XX:+UseG1GC",
|
||||
"-XX:+PrintSharedSpaces",
|
||||
"-Xshare:dump");
|
||||
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldContain("Loading classes to share")
|
||||
.shouldContain("Shared string table stats")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// Run with -Xshare:auto
|
||||
pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-XX:+UnlockDiagnosticVMOptions",
|
||||
"-XX:SharedArchiveFile=./SharedStringsDedup.jsa",
|
||||
"-XX:+UseCompressedOops", "-XX:+UseG1GC",
|
||||
"-XX:+UseStringDeduplication",
|
||||
"-Xshare:auto",
|
||||
"-version");
|
||||
|
||||
new OutputAnalyzer(pb.start())
|
||||
.shouldMatch("(java|openjdk) version")
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* A custom system ClassLoader to define the module "m2" to during iterations of
|
||||
* differing test runs within the test ModuleStress.java
|
||||
*/
|
||||
public class CustomSystemClassLoader extends ClassLoader {
|
||||
public CustomSystemClassLoader() {
|
||||
super();
|
||||
}
|
||||
public CustomSystemClassLoader(ClassLoader parent) {
|
||||
super(parent);
|
||||
}
|
||||
}
|
@ -0,0 +1,129 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import static jdk.test.lib.Asserts.*;
|
||||
|
||||
import java.lang.reflect.Layer;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
//
|
||||
// ClassLoader1 --> defines m1 --> packages p1
|
||||
// ClassLoader2 --> defines m2 --> packages p2
|
||||
// Java System Class Loader --> defines m3 --> packages p3
|
||||
//
|
||||
// m1 can read m2
|
||||
// package p2 in m2 is exported to m1 and m3
|
||||
//
|
||||
// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
|
||||
// Access allowed since m1 can read m2 and package p2 is exported to m1.
|
||||
//
|
||||
public class ModuleNonBuiltinCLMain {
|
||||
|
||||
// Create a Layer over the boot layer.
|
||||
// Define modules within this layer to test access between
|
||||
// publically defined classes within packages of those modules.
|
||||
public void createLayerOnBoot() throws Throwable {
|
||||
|
||||
// Define module: m1
|
||||
// Can read: java.base, m2
|
||||
// Packages: p1
|
||||
// Packages exported: p1 is exported to unqualifiedly
|
||||
ModuleDescriptor descriptor_m1 =
|
||||
new ModuleDescriptor.Builder("m1")
|
||||
.requires("java.base")
|
||||
.requires("m2")
|
||||
.exports("p1")
|
||||
.build();
|
||||
|
||||
// Define module: m2
|
||||
// Can read: java.base, m3
|
||||
// Packages: p2
|
||||
// Packages exported: package p2 is exported to m1 and m3
|
||||
Set<String> targets = new HashSet<>();
|
||||
targets.add("m1");
|
||||
targets.add("m3");
|
||||
ModuleDescriptor descriptor_m2 =
|
||||
new ModuleDescriptor.Builder("m2")
|
||||
.requires("java.base")
|
||||
.requires("m3")
|
||||
.exports("p2", targets)
|
||||
.build();
|
||||
|
||||
// Define module: m3
|
||||
// Can read: java.base
|
||||
// Packages: p3
|
||||
// Packages exported: none
|
||||
ModuleDescriptor descriptor_m3 =
|
||||
new ModuleDescriptor.Builder("m3")
|
||||
.requires("java.base")
|
||||
.build();
|
||||
|
||||
// Set up a ModuleFinder containing all modules for this layer.
|
||||
ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2, descriptor_m3);
|
||||
|
||||
// Resolves "m1"
|
||||
Configuration cf = Layer.boot()
|
||||
.configuration()
|
||||
.resolveRequires(finder, ModuleFinder.of(), Set.of("m1"));
|
||||
|
||||
// map each module to differing user defined class loaders for this test
|
||||
Map<String, ClassLoader> map = new HashMap<>();
|
||||
Loader1 cl1 = new Loader1();
|
||||
Loader2 cl2 = new Loader2();
|
||||
ClassLoader cl3 = ClassLoader.getSystemClassLoader();
|
||||
map.put("m1", cl1);
|
||||
map.put("m2", cl2);
|
||||
map.put("m3", cl3);
|
||||
|
||||
// Create Layer that contains m1 & m2
|
||||
Layer layer = Layer.boot().defineModules(cf, map::get);
|
||||
assertTrue(layer.findLoader("m1") == cl1);
|
||||
assertTrue(layer.findLoader("m2") == cl2);
|
||||
assertTrue(layer.findLoader("m3") == cl3);
|
||||
assertTrue(layer.findLoader("java.base") == null);
|
||||
|
||||
// now use the same loader to load class p1.c1
|
||||
Class p1_c1_class = cl1.loadClass("p1.c1");
|
||||
try {
|
||||
p1_c1_class.newInstance();
|
||||
} catch (IllegalAccessError e) {
|
||||
throw new RuntimeException("Test Failed, an IAE should not be thrown since p2 is exported qualifiedly to m1");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Throwable {
|
||||
ModuleNonBuiltinCLMain test = new ModuleNonBuiltinCLMain();
|
||||
test.createLayerOnBoot();
|
||||
}
|
||||
|
||||
static class Loader1 extends ClassLoader { }
|
||||
static class Loader2 extends ClassLoader { }
|
||||
}
|
109
hotspot/test/runtime/modules/ModuleStress/ModuleSameCLMain.java
Normal file
109
hotspot/test/runtime/modules/ModuleStress/ModuleSameCLMain.java
Normal file
@ -0,0 +1,109 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
import static jdk.test.lib.Asserts.*;
|
||||
|
||||
import java.lang.reflect.Layer;
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleDescriptor;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
//
|
||||
// ClassLoader1 --> defines m1 --> packages p1
|
||||
// ClassLoader1 --> defines m2 --> packages p2
|
||||
//
|
||||
// m1 can read m2
|
||||
// package p2 in m2 is exported to m1
|
||||
//
|
||||
// class p1.c1 defined in m1 tries to access p2.c2 defined in m2
|
||||
// Access allowed since m1 can read m2 and package p2 is exported to m1.
|
||||
//
|
||||
public class ModuleSameCLMain {
|
||||
|
||||
// Create a Layer over the boot layer.
|
||||
// Define modules within this layer to test access between
|
||||
// publically defined classes within packages of those modules.
|
||||
public void createLayerOnBoot() throws Throwable {
|
||||
|
||||
// Define module: m1
|
||||
// Can read: java.base, m2
|
||||
// Packages: p1
|
||||
// Packages exported: p1 is exported to unqualifiedly
|
||||
ModuleDescriptor descriptor_m1 =
|
||||
new ModuleDescriptor.Builder("m1")
|
||||
.requires("java.base")
|
||||
.requires("m2")
|
||||
.exports("p1")
|
||||
.build();
|
||||
|
||||
// Define module: m2
|
||||
// Can read: java.base
|
||||
// Packages: p2
|
||||
// Packages exported: package p2 is exported to m1
|
||||
ModuleDescriptor descriptor_m2 =
|
||||
new ModuleDescriptor.Builder("m2")
|
||||
.requires("java.base")
|
||||
.exports("p2", "m1")
|
||||
.build();
|
||||
|
||||
// Set up a ModuleFinder containing all modules for this layer.
|
||||
ModuleFinder finder = ModuleLibrary.of(descriptor_m1, descriptor_m2);
|
||||
|
||||
// Resolves "m1"
|
||||
Configuration cf = Layer.boot()
|
||||
.configuration()
|
||||
.resolveRequires(finder, ModuleFinder.of(), Set.of("m1"));
|
||||
|
||||
// map each module to the same class loader for this test
|
||||
Map<String, ClassLoader> map = new HashMap<>();
|
||||
Loader1 cl1 = new Loader1();
|
||||
map.put("m1", cl1);
|
||||
map.put("m2", cl1);
|
||||
|
||||
// Create Layer that contains m1 & m2
|
||||
Layer layer = Layer.boot().defineModules(cf, map::get);
|
||||
assertTrue(layer.findLoader("m1") == cl1);
|
||||
assertTrue(layer.findLoader("m2") == cl1);
|
||||
assertTrue(layer.findLoader("java.base") == null);
|
||||
|
||||
// now use the same loader to load class p1.c1
|
||||
Class p1_c1_class = cl1.loadClass("p1.c1");
|
||||
try {
|
||||
p1_c1_class.newInstance();
|
||||
} catch (IllegalAccessError e) {
|
||||
throw new RuntimeException("Test Failed, an IAE should not be thrown since p2 is exported qualifiedly to m1");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String args[]) throws Throwable {
|
||||
ModuleSameCLMain test = new ModuleSameCLMain();
|
||||
test.createLayerOnBoot();
|
||||
}
|
||||
|
||||
static class Loader1 extends ClassLoader { }
|
||||
}
|
131
hotspot/test/runtime/modules/ModuleStress/ModuleStress.java
Normal file
131
hotspot/test/runtime/modules/ModuleStress/ModuleStress.java
Normal file
@ -0,0 +1,131 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation. Oracle designates this
|
||||
* particular file as subject to the "Classpath" exception as provided
|
||||
* by Oracle in the LICENSE file that accompanied this code.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 8159262
|
||||
* @summary Test differing scenarios where a module's readability list and a package's exportability list should be walked
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary /test/lib
|
||||
* @compile ../AccessCheck/ModuleLibrary.java
|
||||
* @compile ModuleSameCLMain.java
|
||||
* @compile ModuleNonBuiltinCLMain.java
|
||||
* @compile CustomSystemClassLoader.java
|
||||
* @build ModuleStress
|
||||
* @run main/othervm ModuleStress
|
||||
*/
|
||||
|
||||
import jdk.test.lib.*;
|
||||
import java.io.File;
|
||||
|
||||
public class ModuleStress {
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
// Test #1: java -version
|
||||
// All modules' readability lists and packages' exportability
|
||||
// lists should contain only modules defined to the 3 builtin
|
||||
// loaders (boot, application, platform). Thus there is
|
||||
// not a need to walk those lists at a GC safepoint since
|
||||
// those loaders never die.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xbootclasspath/a:.",
|
||||
"-Xlog:modules=trace",
|
||||
"-version");
|
||||
|
||||
OutputAnalyzer oa = new OutputAnalyzer(pb.start());
|
||||
oa.shouldNotContain("must be walked")
|
||||
.shouldNotContain("being walked")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// Next 2 tests involve the use of class p1.c1 and p2.c2
|
||||
String source1 = "package p1;" +
|
||||
"import p2.c2;" +
|
||||
"public class c1 {" +
|
||||
" public c1() {" +
|
||||
" p2.c2 c2_obj = new p2.c2();" +
|
||||
" c2_obj.method2();" +
|
||||
" }" +
|
||||
"}";
|
||||
|
||||
String source2 = "package p2;" +
|
||||
"public class c2 {" +
|
||||
" public void method2() { }" +
|
||||
"}";
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("p2/c2",
|
||||
InMemoryJavaCompiler.compile("p2.c2", source2), System.getProperty("test.classes"));
|
||||
|
||||
ClassFileInstaller.writeClassToDisk("p1/c1",
|
||||
InMemoryJavaCompiler.compile("p1.c1", source1), System.getProperty("test.classes"));
|
||||
|
||||
// Test #2: Load two modules defined to the same customer class loader.
|
||||
// m1's module readability list and package p2's exportability should
|
||||
// not be walked at a GC safepoint since both modules are defined to
|
||||
// the same loader and thus have the exact same life cycle.
|
||||
pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xbootclasspath/a:.",
|
||||
"-Xlog:modules=trace",
|
||||
"ModuleSameCLMain");
|
||||
|
||||
oa = new OutputAnalyzer(pb.start());
|
||||
oa.shouldNotContain("must be walked")
|
||||
.shouldNotContain("being walked")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// Test #3: Load two modules in differing custom class loaders.
|
||||
// m1's module readability list and package p2's exportability list must
|
||||
// be walked at a GC safepoint since both modules are defined to non-builtin
|
||||
// class loaders which could die and thus be unloaded.
|
||||
pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xbootclasspath/a:.",
|
||||
"-Xlog:modules=trace",
|
||||
"ModuleNonBuiltinCLMain");
|
||||
|
||||
oa = new OutputAnalyzer(pb.start());
|
||||
oa.shouldContain("module m1 reads list must be walked")
|
||||
.shouldContain("package p2 defined in module m2, exports list must be walked")
|
||||
.shouldNotContain("module m2 reads list must be walked")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
// Test #4: Load two modules in differing custom class loaders,
|
||||
// of which one has been designated as the custom system class loader
|
||||
// via -Djava.system.class.loader=CustomSystemClassLoader. Since
|
||||
// m3 is defined to the system class loader, m2's module readability
|
||||
// list does not have to be walked at a GC safepoint, but package p2's
|
||||
// exportability list does.
|
||||
pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Djava.system.class.loader=CustomSystemClassLoader",
|
||||
"-Xbootclasspath/a:.",
|
||||
"-Xlog:modules=trace",
|
||||
"ModuleNonBuiltinCLMain");
|
||||
|
||||
oa = new OutputAnalyzer(pb.start());
|
||||
oa.shouldContain("package p2 defined in module m2, exports list must be walked")
|
||||
.shouldNotContain("module m2 reads list must be walked")
|
||||
.shouldHaveExitValue(0);
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @test
|
||||
* @bug 8159262
|
||||
* @summary layers over the boot layer are repeatedly created, during this iteration, GCs are forced to verify correct walk of module and package lists.
|
||||
* @modules java.base/jdk.internal.misc
|
||||
* @library /testlibrary /test/lib
|
||||
* @compile ../CompilerUtils.java
|
||||
* @build ModuleStressGC
|
||||
* @run main/othervm ModuleStressGC
|
||||
*/
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import jdk.test.lib.*;
|
||||
|
||||
public class ModuleStressGC {
|
||||
|
||||
private static final String TEST_SRC = System.getProperty("test.src");
|
||||
private static final String TEST_CLASSES = System.getProperty("test.classes");
|
||||
|
||||
private static final Path SRC_DIR = Paths.get(TEST_SRC, "src");
|
||||
private static final Path MODS_DIR = Paths.get(TEST_CLASSES, "mods");
|
||||
|
||||
/**
|
||||
* Compile two module definitions used by the test, jdk.test and jdk.translet.
|
||||
*/
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
boolean compiled;
|
||||
// Compile module jdk.test declaration
|
||||
compiled = CompilerUtils.compile(
|
||||
SRC_DIR.resolve("jdk.test"),
|
||||
MODS_DIR.resolve("jdk.test"));
|
||||
if (!compiled) {
|
||||
throw new RuntimeException("Test failed to compile module jdk.test");
|
||||
}
|
||||
|
||||
// Compile module jdk.translet declaration
|
||||
compiled = CompilerUtils.compile(
|
||||
SRC_DIR.resolve("jdk.translet"),
|
||||
MODS_DIR.resolve("jdk.translet"),
|
||||
"-XaddExports:jdk.test/test=jdk.translet",
|
||||
"-mp", MODS_DIR.toString());
|
||||
if (!compiled) {
|
||||
throw new RuntimeException("Test failed to compile module jdk.translet");
|
||||
}
|
||||
|
||||
// Sanity check that the test, jdk.test/test/MainGC.java,
|
||||
// correctly walks module jdk.test's reads list and package
|
||||
// test's, defined to module jdk.translet, export list at
|
||||
// GC safepoints.
|
||||
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
|
||||
"-Xlog:modules=trace",
|
||||
"-mp", MODS_DIR.toString(),
|
||||
"-m", "jdk.test/test.MainGC");
|
||||
OutputAnalyzer oa = new OutputAnalyzer(pb.start());
|
||||
oa.shouldContain("package test defined in module jdk.test, exports list being walked")
|
||||
.shouldContain("module jdk.test reads list being walked")
|
||||
.shouldHaveExitValue(0);
|
||||
}
|
||||
}
|
@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package test;
|
||||
|
||||
import java.lang.module.Configuration;
|
||||
import java.lang.module.ModuleFinder;
|
||||
import java.lang.reflect.Layer;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Module;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
|
||||
public class MainGC {
|
||||
|
||||
private static final Path MODS_DIR = Paths.get(System.getProperty("jdk.module.path"));
|
||||
static final String MODULE_NAME = "jdk.translet";
|
||||
|
||||
public static void main(String[] args) throws Exception {
|
||||
|
||||
ModuleFinder finder = ModuleFinder.of(MODS_DIR);
|
||||
Layer layerBoot = Layer.boot();
|
||||
|
||||
Configuration cf = layerBoot
|
||||
.configuration()
|
||||
.resolveRequires(ModuleFinder.of(), finder, Set.of(MODULE_NAME));
|
||||
|
||||
Module testModule = MainGC.class.getModule();
|
||||
ClassLoader scl = ClassLoader.getSystemClassLoader();
|
||||
|
||||
// Create an unique module/class loader in a layer above the boot layer.
|
||||
// Export this module to the jdk.test/test package.
|
||||
// Add a read edge from module jdk.test to this module.
|
||||
Callable<Void> task = new Callable<Void>() {
|
||||
@Override
|
||||
public Void call() throws Exception {
|
||||
Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl);
|
||||
Module transletModule = layer.findModule(MODULE_NAME).get();
|
||||
testModule.addExports("test", transletModule);
|
||||
testModule.addReads(transletModule);
|
||||
Class<?> c = layer.findLoader(MODULE_NAME).loadClass("translet.MainGC");
|
||||
Method method = c.getDeclaredMethod("go");
|
||||
method.invoke(null);
|
||||
return null;
|
||||
}
|
||||
};
|
||||
|
||||
List<Future<Void>> results = new ArrayList<>();
|
||||
|
||||
// Repeatedly create the layer above stressing the exportation of
|
||||
// package jdk.test/test to several different modules.
|
||||
ExecutorService pool = Executors.newFixedThreadPool(Math.min(100, Runtime.getRuntime().availableProcessors()*10));
|
||||
try {
|
||||
for (int i = 0; i < 10000; i++) {
|
||||
results.add(pool.submit(task));
|
||||
// At specified intervals, force a GC. This provides an
|
||||
// opportunity to verify that both the module jdk.test's reads
|
||||
// and the package test's, which is defined to jdk.test, exports
|
||||
// lists are being walked.
|
||||
if (i == 3000 || i == 6000 || i == 9000) {
|
||||
System.gc();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
pool.shutdown();
|
||||
}
|
||||
|
||||
int passed = 0;
|
||||
int failed = 0;
|
||||
|
||||
// The failed state should be 0, the created modules in layers above the
|
||||
// boot layer should be allowed access to the contents of the jdk.test/test
|
||||
// package since that package was exported to the transletModule above.
|
||||
for (Future<Void> result : results) {
|
||||
try {
|
||||
result.get();
|
||||
passed++;
|
||||
} catch (Throwable x) {
|
||||
x.printStackTrace();
|
||||
failed++;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println("passed: " + passed);
|
||||
System.out.println("failed: " + failed);
|
||||
}
|
||||
|
||||
public static void callback() { }
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
package translet;
|
||||
|
||||
public class MainGC {
|
||||
public static void go() {
|
||||
test.MainGC.callback();
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user