8198698: Support Lambda proxy classes in dynamic CDS archive

Added archving of hidden classes of type lambda proxy classes.

Co-authored-by: Ioi Lam <ioi.lam@oracle.com>
Reviewed-by: mchung, iklam, dholmes
This commit is contained in:
Calvin Cheung 2020-06-10 15:50:26 +00:00
parent 268d870187
commit 847a3baca8
57 changed files with 3724 additions and 39 deletions

View File

@ -143,6 +143,8 @@ JVM_InternString
JVM_Interrupt
JVM_InvokeMethod
JVM_IsArrayClass
JVM_IsCDSDumpingEnabled
JVM_IsCDSSharingEnabled
JVM_IsConstructorIx
JVM_IsHiddenClass
JVM_IsInterface
@ -155,6 +157,7 @@ JVM_IsVMGeneratedMethodIx
JVM_LatestUserDefinedLoader
JVM_LoadLibrary
JVM_LookupDefineClass
JVM_LookupLambdaProxyClassFromArchive
JVM_MaxMemory
JVM_MaxObjectInspectionAge
JVM_MonitorNotify
@ -171,6 +174,7 @@ JVM_RawMonitorCreate
JVM_RawMonitorDestroy
JVM_RawMonitorEnter
JVM_RawMonitorExit
JVM_RegisterLambdaProxyClassForArchiving
JVM_RegisterSignal
JVM_ReleaseUTF
JVM_ResumeThread

View File

@ -703,7 +703,7 @@ InstanceKlass* SystemDictionary::handle_parallel_super_load(
return NULL;
}
static void post_class_load_event(EventClassLoad* event, const InstanceKlass* k, const ClassLoaderData* init_cld) {
void SystemDictionary::post_class_load_event(EventClassLoad* event, const InstanceKlass* k, const ClassLoaderData* init_cld) {
assert(event != NULL, "invariant");
assert(k != NULL, "invariant");
assert(event->should_commit(), "invariant");
@ -1369,6 +1369,37 @@ bool SystemDictionary::check_shared_class_super_types(InstanceKlass* ik, Handle
return true;
}
InstanceKlass* SystemDictionary::load_shared_lambda_proxy_class(InstanceKlass* ik,
Handle class_loader,
Handle protection_domain,
PackageEntry* pkg_entry,
TRAPS) {
InstanceKlass* shared_nest_host = SystemDictionaryShared::get_shared_nest_host(ik);
assert(shared_nest_host->is_shared(), "nest host must be in CDS archive");
Symbol* cn = shared_nest_host->name();
Klass *s = resolve_or_fail(cn, class_loader, protection_domain, true, CHECK_NULL);
if (s != shared_nest_host) {
// The dynamically resolved nest_host is not the same as the one we used during dump time,
// so we cannot use ik.
return NULL;
} else {
assert(s->is_shared(), "must be");
}
// The lambda proxy class and its nest host have the same class loader and class loader data,
// as verified in SystemDictionaryShared::add_lambda_proxy_class()
assert(shared_nest_host->class_loader() == class_loader(), "mismatched class loader");
assert(shared_nest_host->class_loader_data() == ClassLoaderData::class_loader_data(class_loader()), "mismatched class loader data");
ik->set_nest_host(shared_nest_host, THREAD);
InstanceKlass* loaded_ik = load_shared_class(ik, class_loader, protection_domain, NULL, pkg_entry, CHECK_NULL);
assert(shared_nest_host->is_same_class_package(ik),
"lambda proxy class and its nest host must be in the same package");
return loaded_ik;
}
InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
Handle class_loader,
Handle protection_domain,
@ -1389,8 +1420,13 @@ InstanceKlass* SystemDictionary::load_shared_class(InstanceKlass* ik,
return NULL;
}
InstanceKlass* new_ik = KlassFactory::check_shared_class_file_load_hook(
InstanceKlass* new_ik = NULL;
// CFLH check is skipped for VM hidden or anonymous classes (see KlassFactory::create_from_stream).
// It will be skipped for shared VM hidden lambda proxy classes.
if (!SystemDictionaryShared::is_hidden_lambda_proxy(ik)) {
new_ik = KlassFactory::check_shared_class_file_load_hook(
ik, class_name, class_loader, protection_domain, cfs, CHECK_NULL);
}
if (new_ik != NULL) {
// The class is changed by CFLH. Return the new class. The shared class is
// not used.

View File

@ -132,6 +132,7 @@ class SymbolPropertyTable;
class ProtectionDomainCacheTable;
class ProtectionDomainCacheEntry;
class GCTimer;
class EventClassLoad;
#define WK_KLASS_ENUM_NAME(kname) kname##_knum
@ -606,6 +607,7 @@ protected:
static LoaderConstraintTable* constraints() { return _loader_constraints; }
static ResolutionErrorTable* resolution_errors() { return _resolution_errors; }
static SymbolPropertyTable* invoke_method_table() { return _invoke_method_table; }
static void post_class_load_event(EventClassLoad* event, const InstanceKlass* k, const ClassLoaderData* init_cld);
// Basic loading operations
static InstanceKlass* resolve_instance_class_or_null_helper(Symbol* name,
@ -632,6 +634,11 @@ protected:
bool is_superclass, TRAPS);
static bool check_shared_class_super_types(InstanceKlass* ik, Handle class_loader,
Handle protection_domain, TRAPS);
static InstanceKlass* load_shared_lambda_proxy_class(InstanceKlass* ik,
Handle class_loader,
Handle protection_domain,
PackageEntry* pkg_entry,
TRAPS);
static InstanceKlass* load_shared_class(InstanceKlass* ik,
Handle class_loader,
Handle protection_domain,

View File

@ -36,9 +36,11 @@
#include "classfile/systemDictionaryShared.hpp"
#include "classfile/verificationType.hpp"
#include "classfile/vmSymbols.hpp"
#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
#include "memory/allocation.hpp"
#include "memory/archiveUtils.hpp"
#include "memory/dynamicArchive.hpp"
#include "memory/filemap.hpp"
#include "memory/heapShared.hpp"
#include "memory/metadataFactory.hpp"
@ -46,7 +48,6 @@
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.hpp"
#include "memory/dynamicArchive.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.inline.hpp"
#include "oops/objArrayOop.inline.hpp"
@ -96,6 +97,7 @@ public:
InstanceKlass* _klass;
bool _failed_verification;
bool _is_archived_lambda_proxy;
int _id;
int _clsfile_size;
int _clsfile_crc32;
@ -106,6 +108,7 @@ public:
DumpTimeSharedClassInfo() {
_klass = NULL;
_failed_verification = false;
_is_archived_lambda_proxy = false;
_id = -1;
_clsfile_size = -1;
_clsfile_crc32 = -1;
@ -242,6 +245,159 @@ public:
}
};
class LambdaProxyClassKey {
template <typename T> static void original_to_target(T& field) {
if (field != NULL) {
field = DynamicArchive::original_to_target(field);
ArchivePtrMarker::mark_pointer(&field);
}
}
InstanceKlass* _caller_ik;
Symbol* _invoked_name;
Symbol* _invoked_type;
Symbol* _method_type;
Method* _member_method;
Symbol* _instantiated_method_type;
public:
LambdaProxyClassKey(InstanceKlass* caller_ik,
Symbol* invoked_name,
Symbol* invoked_type,
Symbol* method_type,
Method* member_method,
Symbol* instantiated_method_type) :
_caller_ik(caller_ik),
_invoked_name(invoked_name),
_invoked_type(invoked_type),
_method_type(method_type),
_member_method(member_method),
_instantiated_method_type(instantiated_method_type) {}
void original_to_target() {
original_to_target(_caller_ik);
original_to_target(_instantiated_method_type);
original_to_target(_invoked_name);
original_to_target(_invoked_type);
original_to_target(_member_method);
original_to_target(_method_type);
}
bool equals(LambdaProxyClassKey const& other) const {
return _caller_ik == other._caller_ik &&
_invoked_name == other._invoked_name &&
_invoked_type == other._invoked_type &&
_method_type == other._method_type &&
_member_method == other._member_method &&
_instantiated_method_type == other._instantiated_method_type;
}
unsigned int hash() const {
return SystemDictionaryShared::hash_for_shared_dictionary(_caller_ik) +
SystemDictionaryShared::hash_for_shared_dictionary(_invoked_name) +
SystemDictionaryShared::hash_for_shared_dictionary(_invoked_type) +
SystemDictionaryShared::hash_for_shared_dictionary(_method_type) +
SystemDictionaryShared::hash_for_shared_dictionary(_instantiated_method_type);
}
unsigned int dumptime_hash() const {
return primitive_hash<InstanceKlass*>(_caller_ik) +
primitive_hash<Symbol*>(_invoked_name) +
primitive_hash<Symbol*>(_invoked_type) +
primitive_hash<Symbol*>(_method_type) +
primitive_hash<Symbol*>(_instantiated_method_type);
}
static inline unsigned int DUMPTIME_HASH(LambdaProxyClassKey const& key) {
return (key.dumptime_hash());
}
static inline bool DUMPTIME_EQUALS(
LambdaProxyClassKey const& k1, LambdaProxyClassKey const& k2) {
return (k1.equals(k2));
}
};
class DumpTimeLambdaProxyClassInfo {
public:
GrowableArray<InstanceKlass*>* _proxy_klasses;
DumpTimeLambdaProxyClassInfo() : _proxy_klasses(NULL) {}
void add_proxy_klass(InstanceKlass* proxy_klass) {
if (_proxy_klasses == NULL) {
_proxy_klasses = new (ResourceObj::C_HEAP, mtInternal)GrowableArray<InstanceKlass*>(5, true);
}
assert(_proxy_klasses != NULL, "sanity");
_proxy_klasses->append(proxy_klass);
}
};
class RunTimeLambdaProxyClassInfo {
LambdaProxyClassKey _key;
InstanceKlass* _proxy_klass_head;
public:
RunTimeLambdaProxyClassInfo(LambdaProxyClassKey key, InstanceKlass* proxy_klass) :
_key(key), _proxy_klass_head(proxy_klass) {}
InstanceKlass* proxy_klass_head() const { return _proxy_klass_head; }
// Used by LambdaProxyClassDictionary to implement OffsetCompactHashtable::EQUALS
static inline bool EQUALS(
const RunTimeLambdaProxyClassInfo* value, LambdaProxyClassKey* key, int len_unused) {
return (value->_key.equals(*key));
}
void init(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) {
_key = key;
_key.original_to_target();
_proxy_klass_head = DynamicArchive::original_to_target(info._proxy_klasses->at(0));
ArchivePtrMarker::mark_pointer(&_proxy_klass_head);
}
unsigned int hash() const {
return _key.hash();
}
};
class LambdaProxyClassDictionary : public OffsetCompactHashtable<
LambdaProxyClassKey*,
const RunTimeLambdaProxyClassInfo*,
RunTimeLambdaProxyClassInfo::EQUALS> {};
LambdaProxyClassDictionary _lambda_proxy_class_dictionary;
class DumpTimeLambdaProxyClassDictionary
: public ResourceHashtable<LambdaProxyClassKey,
DumpTimeLambdaProxyClassInfo,
LambdaProxyClassKey::DUMPTIME_HASH,
LambdaProxyClassKey::DUMPTIME_EQUALS,
137, // prime number
ResourceObj::C_HEAP> {
public:
int _count;
};
DumpTimeLambdaProxyClassDictionary* _dumptime_lambda_proxy_class_dictionary = NULL;
static void add_to_dump_time_lambda_proxy_class_dictionary(LambdaProxyClassKey key,
InstanceKlass* proxy_klass) {
assert(DumpTimeTable_lock->owned_by_self(), "sanity");
if (_dumptime_lambda_proxy_class_dictionary == NULL) {
_dumptime_lambda_proxy_class_dictionary =
new (ResourceObj::C_HEAP, mtClass)DumpTimeLambdaProxyClassDictionary();
}
DumpTimeLambdaProxyClassInfo* lambda_info = _dumptime_lambda_proxy_class_dictionary->get(key);
if (lambda_info == NULL) {
DumpTimeLambdaProxyClassInfo info;
info.add_proxy_klass(proxy_klass);
_dumptime_lambda_proxy_class_dictionary->put(key, info);
//lambda_info = _dumptime_lambda_proxy_class_dictionary->get(key);
//assert(lambda_info->_proxy_klass == proxy_klass, "must be"); // debug only -- remove
++_dumptime_lambda_proxy_class_dictionary->_count;
} else {
lambda_info->add_proxy_klass(proxy_klass);
}
}
class RunTimeSharedClassInfo {
public:
struct CrcInfo {
@ -272,6 +428,7 @@ public:
int _num_loader_constraints;
// optional CrcInfo _crc; (only for UNREGISTERED classes)
// optional InstanceKlass* _nest_host
// optional RTLoaderConstraint _loader_constraint_types[_num_loader_constraints]
// optional RTVerifierConstraint _verifier_constraints[_num_verifier_constraints]
// optional char _verifier_constraint_flags[_num_verifier_constraints]
@ -296,11 +453,19 @@ private:
static size_t loader_constraints_size(int num_loader_constraints) {
return sizeof(RTLoaderConstraint) * num_loader_constraints;
}
static size_t nest_host_size(InstanceKlass* klass) {
if (klass->is_hidden()) {
return sizeof(InstanceKlass*);
} else {
return 0;
}
}
public:
static size_t byte_size(InstanceKlass* klass, int num_verifier_constraints, int num_loader_constraints) {
return header_size_size() +
crc_size(klass) +
nest_host_size(klass) +
loader_constraints_size(num_loader_constraints) +
verifier_constraints_size(num_verifier_constraints) +
verifier_constraint_flags_size(num_verifier_constraints);
@ -311,8 +476,12 @@ private:
return header_size_size();
}
size_t nest_host_offset() const {
return crc_offset() + crc_size(_klass);
}
size_t loader_constraints_offset() const {
return crc_offset() + crc_size(_klass);
return nest_host_offset() + nest_host_size(_klass);
}
size_t verifier_constraints_offset() const {
return loader_constraints_offset() + loader_constraints_size(_num_loader_constraints);
@ -348,6 +517,18 @@ public:
return (char*)(address(this) + verifier_constraint_flags_offset());
}
InstanceKlass** nest_host_addr() {
assert(_klass->is_hidden(), "sanity");
return (InstanceKlass**)(address(this) + nest_host_offset());
}
InstanceKlass* nest_host() {
return *nest_host_addr();
}
void set_nest_host(InstanceKlass* k) {
*nest_host_addr() = k;
ArchivePtrMarker::mark_pointer((address*)nest_host_addr());
}
RTLoaderConstraint* loader_constraints() {
assert(_num_loader_constraints > 0, "sanity");
return (RTLoaderConstraint*)(address(this) + loader_constraints_offset());
@ -396,6 +577,12 @@ public:
}
}
if (DynamicDumpSharedSpaces) {
if (_klass->is_hidden()) {
Thread* THREAD = Thread::current();
InstanceKlass* n_h = _klass->nest_host(THREAD);
n_h = DynamicArchive::original_to_target(n_h);
set_nest_host(n_h);
}
_klass = DynamicArchive::original_to_target(info._klass);
}
ArchivePtrMarker::mark_pointer(&_klass);
@ -426,6 +613,7 @@ private:
public:
static RunTimeSharedClassInfo* get_for(InstanceKlass* klass) {
assert(klass->is_shared(), "don't call for non-shared class");
return *info_pointer_addr(klass);
}
static void set_for(InstanceKlass* klass, RunTimeSharedClassInfo* record) {
@ -1148,16 +1336,32 @@ bool SystemDictionaryShared::is_jfr_event_class(InstanceKlass *k) {
return false;
}
bool SystemDictionaryShared::is_registered_lambda_proxy_class(InstanceKlass* ik) {
DumpTimeSharedClassInfo* info = _dumptime_table->get(ik);
return (info != NULL) ? info->_is_archived_lambda_proxy : false;
}
bool SystemDictionaryShared::is_hidden_lambda_proxy(InstanceKlass* ik) {
assert(ik->is_shared(), "applicable to only a shared class");
if (ik->is_hidden()) {
return true;
} else {
return false;
}
}
void SystemDictionaryShared::warn_excluded(InstanceKlass* k, const char* reason) {
ResourceMark rm;
log_warning(cds)("Skipping %s: %s", k->name()->as_C_string(), reason);
}
bool SystemDictionaryShared::should_be_excluded(InstanceKlass* k) {
if (k->is_hidden() || k->is_unsafe_anonymous()) {
warn_excluded(k, "Hidden or Unsafe anonymous class");
return true; // hidden and unsafe anonymous classes are not archived, skip
if (k->is_unsafe_anonymous()) {
warn_excluded(k, "Unsafe anonymous class");
return true; // unsafe anonymous classes are not archived, skip
}
if (k->is_in_error_state()) {
warn_excluded(k, "In error state");
return true;
@ -1166,7 +1370,7 @@ bool SystemDictionaryShared::should_be_excluded(InstanceKlass* k) {
warn_excluded(k, "Has been redefined");
return true;
}
if (k->shared_classpath_index() < 0 && is_builtin(k)) {
if (!k->is_hidden() && k->shared_classpath_index() < 0 && is_builtin(k)) {
// These are classes loaded from unsupported locations (such as those loaded by JVMTI native
// agent during dump time).
warn_excluded(k, "Unsupported location");
@ -1219,6 +1423,11 @@ bool SystemDictionaryShared::should_be_excluded(InstanceKlass* k) {
return true;
}
if (k->is_hidden() && !is_registered_lambda_proxy_class(k)) {
warn_excluded(k, "Hidden class");
return true;
}
Array<InstanceKlass*>* interfaces = k->local_interfaces();
int len = interfaces->length();
for (int i = 0; i < len; i++) {
@ -1241,8 +1450,12 @@ void SystemDictionaryShared::validate_before_archiving(InstanceKlass* k) {
guarantee(info != NULL, "Class %s must be entered into _dumptime_table", name);
guarantee(!info->is_excluded(), "Should not attempt to archive excluded class %s", name);
if (is_builtin(k)) {
if (k->is_hidden()) {
assert(is_registered_lambda_proxy_class(k), "unexpected hidden class %s", name);
}
guarantee(!k->is_shared_unregistered_class(),
"Class loader type must be set for BUILTIN class %s", name);
} else {
guarantee(k->is_shared_unregistered_class(),
"Class loader type must not be set for UNREGISTERED class %s", name);
@ -1358,12 +1571,138 @@ void DumpTimeSharedClassInfo::add_verification_constraint(InstanceKlass* k, Symb
if (log_is_enabled(Trace, cds, verification)) {
ResourceMark rm;
log_trace(cds, verification)("add_verification_constraint: %s: %s must be subclass of %s [0x%x]",
log_trace(cds, verification)("add_verification_constraint: %s: %s must be subclass of %s [0x%x] array len %d flags len %d",
k->external_name(), from_name->as_klass_external_name(),
name->as_klass_external_name(), c);
name->as_klass_external_name(), c, vc_array->length(), vcflags_array->length());
}
}
void SystemDictionaryShared::add_lambda_proxy_class(InstanceKlass* caller_ik,
InstanceKlass* lambda_ik,
Symbol* invoked_name,
Symbol* invoked_type,
Symbol* method_type,
Method* member_method,
Symbol* instantiated_method_type) {
assert(caller_ik->class_loader() == lambda_ik->class_loader(), "mismatched class loader");
assert(caller_ik->class_loader_data() == lambda_ik->class_loader_data(), "mismatched class loader data");
assert(java_lang_Class::class_data(lambda_ik->java_mirror()) == NULL, "must not have class data");
MutexLocker ml(DumpTimeTable_lock, Mutex::_no_safepoint_check_flag);
lambda_ik->assign_class_loader_type();
lambda_ik->set_shared_classpath_index(caller_ik->shared_classpath_index());
DumpTimeSharedClassInfo* info = _dumptime_table->get(lambda_ik);
if (info != NULL && !lambda_ik->is_non_strong_hidden() && is_builtin(lambda_ik) && is_builtin(caller_ik)) {
// Set _is_archived_lambda_proxy in DumpTimeSharedClassInfo so that the lambda_ik
// won't be excluded during dumping of shared archive. See ExcludeDumpTimeSharedClasses.
info->_is_archived_lambda_proxy = true;
LambdaProxyClassKey key(caller_ik,
invoked_name,
invoked_type,
method_type,
member_method,
instantiated_method_type);
add_to_dump_time_lambda_proxy_class_dictionary(key, lambda_ik);
}
}
InstanceKlass* SystemDictionaryShared::get_shared_lambda_proxy_class(InstanceKlass* caller_ik,
Symbol* invoked_name,
Symbol* invoked_type,
Symbol* method_type,
Method* member_method,
Symbol* instantiated_method_type) {
MutexLocker ml(CDSLambda_lock, Mutex::_no_safepoint_check_flag);
LambdaProxyClassKey key(caller_ik, invoked_name, invoked_type,
method_type, member_method, instantiated_method_type);
const RunTimeLambdaProxyClassInfo* info = _lambda_proxy_class_dictionary.lookup(&key, key.hash(), 0);
InstanceKlass* proxy_klass = NULL;
if (info != NULL) {
InstanceKlass* curr_klass = info->proxy_klass_head();
InstanceKlass* prev_klass = curr_klass;
if (curr_klass->lambda_proxy_is_available()) {
while (curr_klass->next_link() != NULL) {
prev_klass = curr_klass;
curr_klass = InstanceKlass::cast(curr_klass->next_link());
}
assert(curr_klass->is_hidden(), "must be");
assert(curr_klass->lambda_proxy_is_available(), "must be");
prev_klass->set_next_link(NULL);
proxy_klass = curr_klass;
proxy_klass->clear_lambda_proxy_is_available();
if (log_is_enabled(Debug, cds)) {
ResourceMark rm;
log_debug(cds)("Loaded lambda proxy: %s", proxy_klass->external_name());
}
} else {
if (log_is_enabled(Debug, cds)) {
ResourceMark rm;
log_debug(cds)("Used all archived lambda proxy classes for: %s %s%s",
caller_ik->external_name(), invoked_name->as_C_string(), invoked_type->as_C_string());
}
}
}
return proxy_klass;
}
InstanceKlass* SystemDictionaryShared::get_shared_nest_host(InstanceKlass* lambda_ik) {
assert(!DumpSharedSpaces && UseSharedSpaces, "called at run time with CDS enabled only");
RunTimeSharedClassInfo* record = RunTimeSharedClassInfo::get_for(lambda_ik);
return record->nest_host();
}
InstanceKlass* SystemDictionaryShared::prepare_shared_lambda_proxy_class(InstanceKlass* lambda_ik,
InstanceKlass* caller_ik,
bool initialize, TRAPS) {
Handle class_loader(THREAD, caller_ik->class_loader());
Handle protection_domain;
PackageEntry* pkg_entry = get_package_entry_from_class_name(class_loader, caller_ik->name());
if (caller_ik->class_loader() != NULL) {
protection_domain = SystemDictionaryShared::init_security_info(class_loader, caller_ik, pkg_entry, CHECK_NULL);
}
InstanceKlass* shared_nest_host = get_shared_nest_host(lambda_ik);
assert(shared_nest_host != NULL, "unexpected NULL _nest_host");
InstanceKlass* loaded_lambda =
SystemDictionary::load_shared_lambda_proxy_class(lambda_ik, class_loader, protection_domain, pkg_entry, CHECK_NULL);
// Ensures the nest host is the same as the lambda proxy's
// nest host recorded at dump time.
InstanceKlass* nest_host = caller_ik->nest_host(THREAD);
assert(nest_host == shared_nest_host, "mismatched nest host");
EventClassLoad class_load_start_event;
{
MutexLocker mu_r(THREAD, Compile_lock);
// Add to class hierarchy, initialize vtables, and do possible
// deoptimizations.
SystemDictionary::add_to_hierarchy(loaded_lambda, CHECK_NULL); // No exception, but can block
// But, do not add to dictionary.
}
loaded_lambda->link_class(CHECK_NULL);
// notify jvmti
if (JvmtiExport::should_post_class_load()) {
assert(THREAD->is_Java_thread(), "thread->is_Java_thread()");
JvmtiExport::post_class_load((JavaThread *) THREAD, loaded_lambda);
}
if (class_load_start_event.should_commit()) {
SystemDictionary::post_class_load_event(&class_load_start_event, loaded_lambda, ClassLoaderData::class_loader_data(class_loader()));
}
if (initialize) {
loaded_lambda->initialize(CHECK_NULL);
}
return loaded_lambda;
}
static char get_loader_type_by(oop loader) {
assert(SystemDictionary::is_builtin_class_loader(loader), "Must be built-in loader");
if (SystemDictionary::is_boot_class_loader(loader)) {
@ -1594,11 +1933,67 @@ public:
size_t SystemDictionaryShared::estimate_size_for_archive() {
EstimateSizeForArchive est;
_dumptime_table->iterate(&est);
return est.total() +
size_t total_size = est.total() +
CompactHashtableWriter::estimate_size(_dumptime_table->count_of(true)) +
CompactHashtableWriter::estimate_size(_dumptime_table->count_of(false));
if (_dumptime_lambda_proxy_class_dictionary != NULL) {
total_size +=
(sizeof(RunTimeLambdaProxyClassInfo) * _dumptime_lambda_proxy_class_dictionary->_count) +
CompactHashtableWriter::estimate_size(_dumptime_lambda_proxy_class_dictionary->_count);
} else {
total_size += CompactHashtableWriter::estimate_size(0);
}
return total_size;
}
class CopyLambdaProxyClassInfoToArchive : StackObj {
CompactHashtableWriter* _writer;
public:
CopyLambdaProxyClassInfoToArchive(CompactHashtableWriter* writer)
: _writer(writer) {}
bool do_entry(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) {
if (SystemDictionaryShared::is_excluded_class(info._proxy_klasses->at(0))) {
return true;
}
ResourceMark rm;
log_info(cds,dynamic)("Archiving hidden %s", info._proxy_klasses->at(0)->external_name());
size_t byte_size = sizeof(RunTimeLambdaProxyClassInfo);
RunTimeLambdaProxyClassInfo* runtime_info =
(RunTimeLambdaProxyClassInfo*)MetaspaceShared::read_only_space_alloc(byte_size);
runtime_info->init(key, info);
unsigned int hash = runtime_info->hash(); // Fields in runtime_info->_key already point to target space.
u4 delta = MetaspaceShared::object_delta_u4(DynamicArchive::buffer_to_target(runtime_info));
_writer->add(hash, delta);
return true;
}
};
class AdjustLambdaProxyClassInfo : StackObj {
public:
AdjustLambdaProxyClassInfo() {}
bool do_entry(LambdaProxyClassKey& key, DumpTimeLambdaProxyClassInfo& info) {
if (SystemDictionaryShared::is_excluded_class(info._proxy_klasses->at(0))) {
return true;
}
int len = info._proxy_klasses->length();
if (len > 1) {
for (int i = 0; i < len-1; i++) {
InstanceKlass* ok0 = info._proxy_klasses->at(i+0); // this is original klass
InstanceKlass* ok1 = info._proxy_klasses->at(i+1); // this is original klass
InstanceKlass* bk0 = DynamicArchive::original_to_buffer(ok0);
InstanceKlass* bk1 = DynamicArchive::original_to_buffer(ok1);
assert(bk0->next_link() == 0, "must be called after Klass::remove_unshareable_info()");
assert(bk1->next_link() == 0, "must be called after Klass::remove_unshareable_info()");
bk0->set_next_link(bk1);
bk1->set_lambda_proxy_is_available();
ArchivePtrMarker::mark_pointer(bk0->next_link_addr());
}
}
DynamicArchive::original_to_buffer(info._proxy_klasses->at(0))->set_lambda_proxy_is_available();
return true;
}
};
class CopySharedClassInfoToArchive : StackObj {
CompactHashtableWriter* _writer;
bool _is_builtin;
@ -1627,7 +2022,11 @@ public:
} else {
delta = MetaspaceShared::object_delta_u4(record);
}
_writer->add(hash, delta);
if (_is_builtin && info._klass->is_hidden()) {
// skip
} else {
_writer->add(hash, delta);
}
if (log_is_enabled(Trace, cds, hashtables)) {
ResourceMark rm;
log_trace(cds,hashtables)("%s dictionary: %s", (_is_builtin ? "builtin" : "unregistered"), info._klass->external_name());
@ -1640,6 +2039,15 @@ public:
}
};
void SystemDictionaryShared::write_lambda_proxy_class_dictionary(LambdaProxyClassDictionary *dictionary) {
CompactHashtableStats stats;
dictionary->reset();
CompactHashtableWriter writer(_dumptime_lambda_proxy_class_dictionary->_count, &stats);
CopyLambdaProxyClassInfoToArchive copy(&writer);
_dumptime_lambda_proxy_class_dictionary->iterate(&copy);
writer.dump(dictionary, "lambda proxy class dictionary");
}
void SystemDictionaryShared::write_dictionary(RunTimeSharedDictionary* dictionary,
bool is_builtin,
bool is_static_archive) {
@ -1659,6 +2067,16 @@ void SystemDictionaryShared::write_to_archive(bool is_static_archive) {
write_dictionary(&_dynamic_builtin_dictionary, true);
write_dictionary(&_dynamic_unregistered_dictionary, false);
}
if (_dumptime_lambda_proxy_class_dictionary != NULL) {
write_lambda_proxy_class_dictionary(&_lambda_proxy_class_dictionary);
}
}
void SystemDictionaryShared::adjust_lambda_proxy_class_dictionary() {
if (_dumptime_lambda_proxy_class_dictionary != NULL) {
AdjustLambdaProxyClassInfo adjuster;
_dumptime_lambda_proxy_class_dictionary->iterate(&adjuster);
}
}
void SystemDictionaryShared::serialize_dictionary_headers(SerializeClosure* soc,
@ -1669,6 +2087,7 @@ void SystemDictionaryShared::serialize_dictionary_headers(SerializeClosure* soc,
} else {
_dynamic_builtin_dictionary.serialize_header(soc);
_dynamic_unregistered_dictionary.serialize_header(soc);
_lambda_proxy_class_dictionary.serialize_header(soc);
}
}
@ -1703,6 +2122,7 @@ SystemDictionaryShared::find_record(RunTimeSharedDictionary* static_dict, RunTim
InstanceKlass* SystemDictionaryShared::find_builtin_class(Symbol* name) {
const RunTimeSharedClassInfo* record = find_record(&_builtin_dictionary, &_dynamic_builtin_dictionary, name);
if (record != NULL) {
assert(!record->_klass->is_hidden(), "hidden class cannot be looked up by name");
return record->_klass;
} else {
return NULL;
@ -1727,6 +2147,23 @@ public:
}
};
class SharedLambdaDictionaryPrinter : StackObj {
outputStream* _st;
int _index;
public:
SharedLambdaDictionaryPrinter(outputStream* st) : _st(st), _index(0) {}
void do_value(const RunTimeLambdaProxyClassInfo* record) {
ResourceMark rm;
_st->print_cr("%4d: %s", (_index++), record->proxy_klass_head()->external_name());
Klass* k = record->proxy_klass_head()->next_link();
while (k != NULL) {
_st->print_cr("%4d: %s", (_index++), k->external_name());
k = k->next_link();
}
}
};
void SystemDictionaryShared::print_on(outputStream* st) {
if (UseSharedSpaces) {
st->print_cr("Shared Dictionary");
@ -1736,6 +2173,11 @@ void SystemDictionaryShared::print_on(outputStream* st) {
if (DynamicArchive::is_mapped()) {
_dynamic_builtin_dictionary.iterate(&p);
_unregistered_dictionary.iterate(&p);
if (!_lambda_proxy_class_dictionary.empty()) {
st->print_cr("Shared Lambda Dictionary");
SharedLambdaDictionaryPrinter ldp(st);
_lambda_proxy_class_dictionary.iterate(&ldp);
}
}
}
}
@ -1747,6 +2189,7 @@ void SystemDictionaryShared::print_table_statistics(outputStream* st) {
if (DynamicArchive::is_mapped()) {
_dynamic_builtin_dictionary.print_table_statistics(st, "Dynamic Builtin Shared Dictionary");
_dynamic_unregistered_dictionary.print_table_statistics(st, "Unregistered Shared Dictionary");
_lambda_proxy_class_dictionary.print_table_statistics(st, "Lambda Shared Dictionary");
}
}
}

View File

@ -105,6 +105,7 @@
class ClassFileStream;
class DumpTimeSharedClassInfo;
class DumpTimeSharedClassTable;
class LambdaProxyClassDictionary;
class RunTimeSharedClassInfo;
class RunTimeSharedDictionary;
@ -178,7 +179,6 @@ private:
TRAPS);
static Handle get_shared_protection_domain(Handle class_loader,
ModuleEntry* mod, TRAPS);
static Handle init_security_info(Handle class_loader, InstanceKlass* ik, PackageEntry* pkg_entry, TRAPS);
static void atomic_set_array_index(OopHandle array, int index, oop o) {
// Benign race condition: array.obj_at(index) may already be filled in.
@ -213,13 +213,17 @@ private:
static void write_dictionary(RunTimeSharedDictionary* dictionary,
bool is_builtin,
bool is_static_archive = true);
static void write_lambda_proxy_class_dictionary(LambdaProxyClassDictionary* dictionary);
static bool is_jfr_event_class(InstanceKlass *k);
static bool is_registered_lambda_proxy_class(InstanceKlass* ik);
static void warn_excluded(InstanceKlass* k, const char* reason);
static bool should_be_excluded(InstanceKlass* k);
DEBUG_ONLY(static bool _no_class_loading_should_happen;)
public:
static bool is_hidden_lambda_proxy(InstanceKlass* ik);
static Handle init_security_info(Handle class_loader, InstanceKlass* ik, PackageEntry* pkg_entry, TRAPS);
static InstanceKlass* find_builtin_class(Symbol* class_name);
static const RunTimeSharedClassInfo* find_record(RunTimeSharedDictionary* static_dict,
@ -284,6 +288,23 @@ public:
TRAPS) NOT_CDS_RETURN;
static void set_class_has_failed_verification(InstanceKlass* ik) NOT_CDS_RETURN;
static bool has_class_failed_verification(InstanceKlass* ik) NOT_CDS_RETURN_(false);
static void add_lambda_proxy_class(InstanceKlass* caller_ik,
InstanceKlass* lambda_ik,
Symbol* invoked_name,
Symbol* invoked_type,
Symbol* method_type,
Method* member_method,
Symbol* instantiated_method_type) NOT_CDS_RETURN;
static InstanceKlass* get_shared_lambda_proxy_class(InstanceKlass* caller_ik,
Symbol* invoked_name,
Symbol* invoked_type,
Symbol* method_type,
Method* member_method,
Symbol* instantiated_method_type) NOT_CDS_RETURN_(NULL);
static InstanceKlass* get_shared_nest_host(InstanceKlass* lambda_ik) NOT_CDS_RETURN_(NULL);
static InstanceKlass* prepare_shared_lambda_proxy_class(InstanceKlass* lambda_ik,
InstanceKlass* caller_ik,
bool initialize, TRAPS) NOT_CDS_RETURN_(NULL);
static bool check_linking_constraints(InstanceKlass* klass, TRAPS) NOT_CDS_RETURN_(false);
static void record_linking_constraint(Symbol* name, InstanceKlass* klass,
Handle loader1, Handle loader2, TRAPS) NOT_CDS_RETURN;
@ -296,6 +317,7 @@ public:
static void dumptime_classes_do(class MetaspaceClosure* it);
static size_t estimate_size_for_archive();
static void write_to_archive(bool is_static_archive = true);
static void adjust_lambda_proxy_class_dictionary();
static void serialize_dictionary_headers(class SerializeClosure* soc,
bool is_static_archive = true);
static void serialize_well_known_klasses(class SerializeClosure* soc);

View File

@ -176,6 +176,30 @@ JVM_GetVmArguments(JNIEnv *env);
JNIEXPORT void JNICALL
JVM_InitializeFromArchive(JNIEnv* env, jclass cls);
JNIEXPORT void JNICALL
JVM_RegisterLambdaProxyClassForArchiving(JNIEnv* env, jclass caller,
jstring invokedName,
jobject invokedType,
jobject methodType,
jobject implMethodMember,
jobject instantiatedMethodType,
jclass lambdaProxyClass);
JNIEXPORT jclass JNICALL
JVM_LookupLambdaProxyClassFromArchive(JNIEnv* env, jclass caller,
jstring invokedName,
jobject invokedType,
jobject methodType,
jobject implMethodMember,
jobject instantiatedMethodType,
jboolean initialize);
JNIEXPORT jboolean JNICALL
JVM_IsCDSDumpingEnabled(JNIEnv* env);
JNIEXPORT jboolean JNICALL
JVM_IsCDSSharingEnabled(JNIEnv* env);
JNIEXPORT jlong JNICALL
JVM_GetRandomSeedForCDSDump();

View File

@ -659,6 +659,11 @@ public:
make_trampolines();
make_klasses_shareable();
{
log_info(cds)("Adjust lambda proxy class dictionary");
SystemDictionaryShared::adjust_lambda_proxy_class_dictionary();
}
{
log_info(cds)("Final relocation of pointers ... ");
ResourceMark rm;
@ -838,16 +843,7 @@ void DynamicArchiveBuilder::make_klasses_shareable() {
for (i = 0; i < count; i++) {
InstanceKlass* ik = _klasses->at(i);
ClassLoaderData *cld = ik->class_loader_data();
if (cld->is_boot_class_loader_data()) {
ik->set_shared_class_loader_type(ClassLoader::BOOT_LOADER);
}
else if (cld->is_platform_class_loader_data()) {
ik->set_shared_class_loader_type(ClassLoader::PLATFORM_LOADER);
}
else if (cld->is_system_class_loader_data()) {
ik->set_shared_class_loader_type(ClassLoader::APP_LOADER);
}
ik->assign_class_loader_type();
MetaspaceShared::rewrite_nofast_bytecodes_and_calculate_fingerprints(Thread::current(), ik);
ik->remove_unshareable_info();

View File

@ -414,13 +414,21 @@ void ConstantPool::remove_unshareable_info() {
// during dump time. We need to restore it back to an UnresolvedClass,
// so that the proper class loading and initialization can happen
// at runtime.
CPKlassSlot kslot = klass_slot_at(index);
int resolved_klass_index = kslot.resolved_klass_index();
int name_index = kslot.name_index();
assert(tag_at(name_index).is_symbol(), "sanity");
resolved_klasses()->at_put(resolved_klass_index, NULL);
tag_at_put(index, JVM_CONSTANT_UnresolvedClass);
assert(klass_name_at(index) == symbol_at(name_index), "sanity");
bool clear_it = true;
if (pool_holder()->is_hidden() && index == pool_holder()->this_class_index()) {
// All references to a hidden class's own field/methods are through this
// index. We cannot clear it. See comments in ClassFileParser::fill_instance_klass.
clear_it = false;
}
if (clear_it) {
CPKlassSlot kslot = klass_slot_at(index);
int resolved_klass_index = kslot.resolved_klass_index();
int name_index = kslot.name_index();
assert(tag_at(name_index).is_symbol(), "sanity");
resolved_klasses()->at_put(resolved_klass_index, NULL);
tag_at_put(index, JVM_CONSTANT_UnresolvedClass);
assert(klass_name_at(index) == symbol_at(name_index), "sanity");
}
}
}
if (cache() != NULL) {

View File

@ -2602,6 +2602,19 @@ void InstanceKlass::set_shared_class_loader_type(s2 loader_type) {
}
}
void InstanceKlass::assign_class_loader_type() {
ClassLoaderData *cld = class_loader_data();
if (cld->is_boot_class_loader_data()) {
set_shared_class_loader_type(ClassLoader::BOOT_LOADER);
}
else if (cld->is_platform_class_loader_data()) {
set_shared_class_loader_type(ClassLoader::PLATFORM_LOADER);
}
else if (cld->is_system_class_loader_data()) {
set_shared_class_loader_type(ClassLoader::APP_LOADER);
}
}
#if INCLUDE_JVMTI
static void clear_all_breakpoints(Method* m) {
m->clear_all_breakpoints();

View File

@ -368,6 +368,8 @@ class InstanceKlass: public Klass {
void set_shared_class_loader_type(s2 loader_type);
void assign_class_loader_type();
bool has_nonstatic_fields() const {
return (_misc_flags & _misc_has_nonstatic_fields) != 0;
}

View File

@ -176,7 +176,8 @@ private:
// Flags of the current shared class.
u2 _shared_class_flags;
enum {
_has_raw_archived_mirror = 1
_has_raw_archived_mirror = 1,
_archived_lambda_proxy_is_available = 2
};
#endif
@ -293,6 +294,7 @@ protected:
void set_next_link(Klass* k) { _next_link = k; }
Klass* next_link() const { return _next_link; } // The next klass defined by the class loader.
Klass** next_link_addr() { return &_next_link; }
// class loader data
ClassLoaderData* class_loader_data() const { return _class_loader_data; }
@ -317,6 +319,17 @@ protected:
NOT_CDS(return false;)
}
void set_lambda_proxy_is_available() {
CDS_ONLY(_shared_class_flags |= _archived_lambda_proxy_is_available;)
}
void clear_lambda_proxy_is_available() {
CDS_ONLY(_shared_class_flags &= ~_archived_lambda_proxy_is_available;)
}
bool lambda_proxy_is_available() const {
CDS_ONLY(return (_shared_class_flags & _archived_lambda_proxy_is_available) != 0;)
NOT_CDS(return false;)
}
// Obtain the module or package for this class
virtual ModuleEntry* module() const = 0;
virtual PackageEntry* package() const = 0;

View File

@ -26,6 +26,7 @@
#include "jvm.h"
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaAssertions.hpp"
#include "classfile/javaClasses.inline.hpp"
@ -41,6 +42,7 @@
#include "interpreter/bytecodeUtils.hpp"
#include "jfr/jfrEvents.hpp"
#include "logging/log.hpp"
#include "memory/dynamicArchive.hpp"
#include "memory/heapShared.hpp"
#include "memory/oopFactory.hpp"
#include "memory/referenceType.hpp"
@ -3725,6 +3727,113 @@ JVM_ENTRY(void, JVM_InitializeFromArchive(JNIEnv* env, jclass cls))
HeapShared::initialize_from_archived_subgraph(k);
JVM_END
JVM_ENTRY(void, JVM_RegisterLambdaProxyClassForArchiving(JNIEnv* env,
jclass caller,
jstring invokedName,
jobject invokedType,
jobject methodType,
jobject implMethodMember,
jobject instantiatedMethodType,
jclass lambdaProxyClass))
JVMWrapper("JVM_RegisterLambdaProxyClassForArchiving");
if (!DynamicDumpSharedSpaces) {
return;
}
Klass* caller_k = java_lang_Class::as_Klass(JNIHandles::resolve(caller));
InstanceKlass* caller_ik = InstanceKlass::cast(caller_k);
if (caller_ik->is_hidden() || caller_ik->is_unsafe_anonymous()) {
// VM anonymous classes and hidden classes not of type lambda proxy classes are currently not being archived.
// If the caller_ik is of one of the above types, the corresponding lambda proxy class won't be
// registered for archiving.
return;
}
Klass* lambda_k = java_lang_Class::as_Klass(JNIHandles::resolve(lambdaProxyClass));
InstanceKlass* lambda_ik = InstanceKlass::cast(lambda_k);
assert(lambda_ik->is_hidden(), "must be a hidden class");
assert(!lambda_ik->is_non_strong_hidden(), "expected a strong hidden class");
Symbol* invoked_name = NULL;
if (invokedName != NULL) {
invoked_name = java_lang_String::as_symbol(JNIHandles::resolve_non_null(invokedName));
}
Handle invoked_type_oop(THREAD, JNIHandles::resolve_non_null(invokedType));
Symbol* invoked_type = java_lang_invoke_MethodType::as_signature(invoked_type_oop(), true);
Handle method_type_oop(THREAD, JNIHandles::resolve_non_null(methodType));
Symbol* method_type = java_lang_invoke_MethodType::as_signature(method_type_oop(), true);
Handle impl_method_member_oop(THREAD, JNIHandles::resolve_non_null(implMethodMember));
assert(java_lang_invoke_MemberName::is_method(impl_method_member_oop()), "must be");
Method* m = java_lang_invoke_MemberName::vmtarget(impl_method_member_oop());
Handle instantiated_method_type_oop(THREAD, JNIHandles::resolve_non_null(instantiatedMethodType));
Symbol* instantiated_method_type = java_lang_invoke_MethodType::as_signature(instantiated_method_type_oop(), true);
SystemDictionaryShared::add_lambda_proxy_class(caller_ik, lambda_ik, invoked_name, invoked_type,
method_type, m, instantiated_method_type);
JVM_END
JVM_ENTRY(jclass, JVM_LookupLambdaProxyClassFromArchive(JNIEnv* env,
jclass caller,
jstring invokedName,
jobject invokedType,
jobject methodType,
jobject implMethodMember,
jobject instantiatedMethodType,
jboolean initialize))
JVMWrapper("JVM_LookupLambdaProxyClassFromArchive");
if (!DynamicArchive::is_mapped()) {
return NULL;
}
if (invokedName == NULL || invokedType == NULL || methodType == NULL ||
implMethodMember == NULL || instantiatedMethodType == NULL) {
THROW_(vmSymbols::java_lang_NullPointerException(), NULL);
}
Klass* caller_k = java_lang_Class::as_Klass(JNIHandles::resolve(caller));
InstanceKlass* caller_ik = InstanceKlass::cast(caller_k);
if (!caller_ik->is_shared()) {
// there won't be a shared lambda class if the caller_ik is not in the shared archive.
return NULL;
}
Symbol* invoked_name = java_lang_String::as_symbol(JNIHandles::resolve_non_null(invokedName));
Handle invoked_type_oop(THREAD, JNIHandles::resolve_non_null(invokedType));
Symbol* invoked_type = java_lang_invoke_MethodType::as_signature(invoked_type_oop(), true);
Handle method_type_oop(THREAD, JNIHandles::resolve_non_null(methodType));
Symbol* method_type = java_lang_invoke_MethodType::as_signature(method_type_oop(), true);
Handle impl_method_member_oop(THREAD, JNIHandles::resolve_non_null(implMethodMember));
assert(java_lang_invoke_MemberName::is_method(impl_method_member_oop()), "must be");
Method* m = java_lang_invoke_MemberName::vmtarget(impl_method_member_oop());
Handle instantiated_method_type_oop(THREAD, JNIHandles::resolve_non_null(instantiatedMethodType));
Symbol* instantiated_method_type = java_lang_invoke_MethodType::as_signature(instantiated_method_type_oop(), true);
InstanceKlass* lambda_ik = SystemDictionaryShared::get_shared_lambda_proxy_class(caller_ik, invoked_name, invoked_type,
method_type, m, instantiated_method_type);
jclass jcls = NULL;
if (lambda_ik != NULL) {
InstanceKlass* loaded_lambda = SystemDictionaryShared::prepare_shared_lambda_proxy_class(lambda_ik, caller_ik, initialize, THREAD);
jcls = loaded_lambda == NULL ? NULL : (jclass) JNIHandles::make_local(env, loaded_lambda->java_mirror());
}
return jcls;
JVM_END
JVM_ENTRY(jboolean, JVM_IsCDSDumpingEnabled(JNIEnv* env))
JVMWrapper("JVM_IsCDSDumpingEnable");
return DynamicDumpSharedSpaces;
JVM_END
JVM_ENTRY(jboolean, JVM_IsCDSSharingEnabled(JNIEnv* env))
JVMWrapper("JVM_IsCDSSharingEnable");
return UseSharedSpaces;
JVM_END
JVM_ENTRY_NO_ENV(jlong, JVM_GetRandomSeedForCDSDump())
JVMWrapper("JVM_GetRandomSeedForCDSDump");
if (DumpSharedSpaces) {

View File

@ -150,6 +150,7 @@ Mutex* NMTQuery_lock = NULL;
Mutex* CDSClassFileStream_lock = NULL;
#endif
Mutex* DumpTimeTable_lock = NULL;
Mutex* CDSLambda_lock = NULL;
#endif // INCLUDE_CDS
#if INCLUDE_JVMCI
@ -344,6 +345,7 @@ void mutex_init() {
def(CDSClassFileStream_lock , PaddedMutex , max_nonleaf, false, _safepoint_check_always);
#endif
def(DumpTimeTable_lock , PaddedMutex , leaf - 1, true, _safepoint_check_never);
def(CDSLambda_lock , PaddedMutex , leaf, true, _safepoint_check_never);
#endif // INCLUDE_CDS
#if INCLUDE_JVMCI

View File

@ -129,6 +129,7 @@ extern Mutex* NMTQuery_lock; // serialize NMT Dcmd queries
extern Mutex* CDSClassFileStream_lock; // FileMapInfo::open_stream_for_jvmti
#endif
extern Mutex* DumpTimeTable_lock; // SystemDictionaryShared::find_or_allocate_info_for
extern Mutex* CDSLambda_lock; // SystemDictionaryShared::get_shared_lambda_proxy_class
#endif // INCLUDE_CDS
#if INCLUDE_JFR
extern Mutex* JfrStacktrace_lock; // used to guard access to the JFR stacktrace table

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2012, 2013, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2012, 2020, 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
@ -244,6 +244,47 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
}
}
/**
* Spins the lambda proxy class.
*
* This first checks if a lambda proxy class can be loaded from CDS archive.
* Otherwise, generate the lambda proxy class. If CDS dumping is enabled, it
* registers the lambda proxy class for including into the CDS archive.
*/
private Class<?> spinInnerClass() throws LambdaConversionException {
// include lambda proxy class in CDS archive at dump time
if (LambdaProxyClassArchive.isDumpArchive()) {
Class<?> innerClass = generateInnerClass();
LambdaProxyClassArchive.register(targetClass,
samMethodName,
invokedType,
samMethodType,
implMethod,
instantiatedMethodType,
isSerializable,
markerInterfaces,
additionalBridges,
innerClass);
return innerClass;
}
// load from CDS archive if present
Class<?> innerClass = LambdaProxyClassArchive.find(targetClass,
samMethodName,
invokedType,
samMethodType,
implMethod,
instantiatedMethodType,
isSerializable,
markerInterfaces,
additionalBridges,
!disableEagerInitialization);
if (innerClass == null) {
innerClass = generateInnerClass();
}
return innerClass;
}
/**
* Generate a class file which implements the functional
* interface, define and return the class.
@ -259,7 +300,7 @@ import static jdk.internal.org.objectweb.asm.Opcodes.*;
* @throws LambdaConversionException If properly formed functional interface
* is not found
*/
private Class<?> spinInnerClass() throws LambdaConversionException {
private Class<?> generateInnerClass() throws LambdaConversionException {
String[] interfaces;
String samIntf = samBase.getName().replace('.', '/');
boolean accidentallySerializable = !isSerializable && Serializable.class.isAssignableFrom(samBase);

View File

@ -0,0 +1,136 @@
/*
* Copyright (c) 2020, 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 java.lang.invoke;
import jdk.internal.loader.BuiltinClassLoader;
import jdk.internal.misc.VM;
final class LambdaProxyClassArchive {
private static final boolean dumpArchive;
private static final boolean sharingEnabled;
static {
dumpArchive = VM.isCDSDumpingEnabled();
sharingEnabled = VM.isCDSSharingEnabled();
}
/**
* Check if CDS dynamic dump is enabled.
*/
static boolean isDumpArchive() {
return dumpArchive;
}
/**
* Check if CDS sharing is enabled.
*/
static boolean isSharingEnabled() {
return sharingEnabled;
}
/**
* Check if the class is loaded by a built-in class loader.
*/
static boolean loadedByBuiltinLoader(Class<?> cls) {
ClassLoader cl = cls.getClassLoader();
return (cl == null || (cl instanceof BuiltinClassLoader)) ? true : false;
}
private static native void addToArchive(Class<?> caller,
String invokedName,
MethodType invokedType,
MethodType samMethodType,
MemberName implMethod,
MethodType instantiatedMethodType,
Class<?> lambdaProxyClass);
private static native Class<?> findFromArchive(Class<?> caller,
String invokedName,
MethodType invokedType,
MethodType samMethodType,
MemberName implMethod,
MethodType instantiatedMethodType,
boolean initialize);
/**
* Registers the lambdaProxyClass into CDS archive.
* The VM will store the lambdaProxyClass into a hash table
* using the first six argumennts as the key.
*
* CDS only archives lambda proxy class if it's not serializable
* and no marker interfaces and no additional bridges, and if it is
* loaded by a built-in class loader.
*/
static boolean register(Class<?> caller,
String invokedName,
MethodType invokedType,
MethodType samMethodType,
MethodHandle implMethod,
MethodType instantiatedMethodType,
boolean isSerializable,
Class<?>[] markerInterfaces,
MethodType[] additionalBridges,
Class<?> lambdaProxyClass) {
if (!isDumpArchive())
throw new IllegalStateException("should only register lambda proxy class at dump time");
if (loadedByBuiltinLoader(caller) &&
!isSerializable && markerInterfaces.length == 0 && additionalBridges.length == 0) {
addToArchive(caller, invokedName, invokedType, samMethodType,
implMethod.internalMemberName(), instantiatedMethodType,
lambdaProxyClass);
return true;
}
return false;
}
/**
* Lookup a lambda proxy class from the CDS archive using the first
* six arguments as the key.
*
* CDS only archives lambda proxy class if it's not serializable
* and no marker interfaces and no additional bridges, and if it is
* loaded by a built-in class loader.
*/
static Class<?> find(Class<?> caller,
String invokedName,
MethodType invokedType,
MethodType samMethodType,
MethodHandle implMethod,
MethodType instantiatedMethodType,
boolean isSerializable,
Class<?>[] markerInterfaces,
MethodType[] additionalBridges,
boolean initialize) {
if (isDumpArchive())
throw new IllegalStateException("cannot load class from CDS archive at dump time");
if (!loadedByBuiltinLoader(caller) ||
!isSharingEnabled() || isSerializable || markerInterfaces.length > 0 || additionalBridges.length > 0)
return null;
return findFromArchive(caller, invokedName, invokedType, samMethodType,
implMethod.internalMemberName(), instantiatedMethodType, initialize);
}
}

View File

@ -470,6 +470,16 @@ public class VM {
public static native long getRandomSeedForCDSDump();
/**
* Check if CDS dynamic dumping is enabled via the DynamicDumpSharedSpaces flag.
*/
public static native boolean isCDSDumpingEnabled();
/**
* Check if CDS sharing is enabled by via the UseSharedSpaces flag.
*/
public static native boolean isCDSSharingEnabled();
/**
* Provides access to information on buffer usage.
*/

View File

@ -0,0 +1,59 @@
/*
* Copyright (c) 2020, 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.
*/
#include "jni.h"
#include "jni_util.h"
#include "jlong.h"
#include "jvm.h"
#include "java_lang_invoke_LambdaProxyClassArchive.h"
JNIEXPORT void JNICALL
Java_java_lang_invoke_LambdaProxyClassArchive_addToArchive(JNIEnv *env, jclass ignore,
jclass caller,
jstring invokedName,
jobject invokedType,
jobject methodType,
jobject implMethodMember,
jobject instantiatedMethodType,
jclass lambdaProxyClass) {
JVM_RegisterLambdaProxyClassForArchiving(env, caller, invokedName, invokedType,
methodType, implMethodMember,
instantiatedMethodType, lambdaProxyClass);
}
JNIEXPORT jclass JNICALL
Java_java_lang_invoke_LambdaProxyClassArchive_findFromArchive(JNIEnv *env, jclass ignore,
jclass caller,
jstring invokedName,
jobject invokedType,
jobject methodType,
jobject implMethodMember,
jobject instantiatedMethodType,
jboolean initialize) {
return JVM_LookupLambdaProxyClassFromArchive(env, caller, invokedName, invokedType,
methodType, implMethodMember,
instantiatedMethodType, initialize);
}

View File

@ -66,3 +66,13 @@ JNIEXPORT jlong JNICALL
Java_jdk_internal_misc_VM_getRandomSeedForCDSDump(JNIEnv *env, jclass ignore) {
return JVM_GetRandomSeedForCDSDump();
}
JNIEXPORT jboolean JNICALL
Java_jdk_internal_misc_VM_isCDSDumpingEnabled(JNIEnv *env, jclass jcls) {
return JVM_IsCDSDumpingEnabled(env);
}
JNIEXPORT jboolean JNICALL
Java_jdk_internal_misc_VM_isCDSSharingEnabled(JNIEnv *env, jclass jcls) {
return JVM_IsCDSSharingEnabled(env);
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary Basic operations of Lambda class archiving.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @build BasicLambdaApp sun.hotspot.WhiteBox LambdaVerification
* @run driver ClassFileInstaller -jar basic_lambda_app.jar BasicLambdaApp LambdaVerification
* @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. BasicLambdaTest
*/
public class BasicLambdaTest extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(BasicLambdaTest::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("basic_lambda_app.jar");
String mainClass = "BasicLambdaApp";
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
dump(topArchiveName,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-Xlog:class+load=debug,class+unload=info,cds+dynamic=info",
use_whitebox_jar,
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldContain("Archiving hidden BasicLambdaApp$$Lambda$")
.shouldHaveExitValue(0);
});
run(topArchiveName,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
use_whitebox_jar,
"-Xlog:class+load=debug,class+resolve=debug,class+unload=info",
"-cp", appJar, mainClass, "run")
.assertNormalExit(output -> {
output.shouldHaveExitValue(0);
});
}
}

View File

@ -0,0 +1,91 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary Run the CustomFJPoolTest in dynamic CDSarchive mode.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @compile ../../../../../../jdk/java/util/stream/CustomFJPoolTest.java
* test-classes/TestStreamApp.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run testng/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. CDSStreamTestDriver
*/
import org.testng.annotations.Test;
import java.io.File;
import jtreg.SkippedException;
import sun.hotspot.gc.GC;
@Test
public class CDSStreamTestDriver extends DynamicArchiveTestBase {
@Test
public void testMain() throws Exception {
runTest(CDSStreamTestDriver::doTest);
}
private static final String classDir = System.getProperty("test.classes");
private static final String mainClass = "TestStreamApp";
private static final String javaClassPath = System.getProperty("java.class.path");
private static final String ps = System.getProperty("path.separator");
private static final String skippedException = "jtreg.SkippedException: Unable to map shared archive: test did not complete";
static void doTest() throws Exception {
String topArchiveName = getNewArchiveName();
JarBuilder.build("streamapp", new File(classDir), null);
String appJar = classDir + File.separator + "streamapp.jar";
String[] classPaths = javaClassPath.split(File.pathSeparator);
String testngJar = null;
for (String path : classPaths) {
if (path.endsWith("testng.jar")) {
testngJar = path;
break;
}
}
String[] testClassNames = { "CustomFJPoolTest" };
for (String className : testClassNames) {
try {
dumpAndRun(topArchiveName, "-Xlog:cds,cds+dynamic=debug,class+load=trace",
"-cp", appJar + ps + testngJar,
mainClass, className);
} catch (SkippedException s) {
if (GC.Z.isSelected() && s.toString().equals(skippedException)) {
System.out.println("Got " + s.toString() + " as expected.");
System.out.println("Because the test was run with ZGC with UseCompressedOops and UseCompressedClassPointers disabled,");
System.out.println("but the base archive was created with the options enabled");
} else {
throw new RuntimeException("Archive mapping should always succeed after JDK-8231610 (did the machine run out of memory?)");
}
}
}
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @compile ../../../../../../jdk/java/util/stream/TestDoubleSumAverage.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. DoubleSumAverageTest
*/
import java.io.File;
public class DoubleSumAverageTest extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(DoubleSumAverageTest::testImpl);
}
private static final String classDir = System.getProperty("test.classes");
private static final String mainClass = "TestDoubleSumAverage";
static void testImpl() throws Exception {
String topArchiveName = getNewArchiveName();
JarBuilder.build("stream", new File(classDir), null);
String appJar = classDir + File.separator + "stream.jar";
dumpAndRun(topArchiveName, "-Xlog:cds,cds+dynamic=debug,class+load=trace",
"-cp", appJar, mainClass);
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary Lambda proxy class loaded by a custom class loader will not be archived.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @build CustomLoaderApp LambHello sun.hotspot.WhiteBox
* @run driver ClassFileInstaller -jar custom_loader_app.jar CustomLoaderApp LambHello
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. LambdaCustomLoader
*/
public class LambdaCustomLoader extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(LambdaCustomLoader::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("custom_loader_app.jar");
String mainClass = "CustomLoaderApp";
dump(topArchiveName,
"-Xlog:class+load,cds,cds+dynamic",
"-cp", appJar, mainClass, appJar)
.assertNormalExit(output -> {
output.shouldMatch("Skipping.LambHello[$][$]Lambda[$].*0x.*:.Hidden.class")
.shouldHaveExitValue(0);
});
run(topArchiveName,
"-Xlog:class+load,class+unload=info",
"-cp", appJar, mainClass, appJar)
.assertNormalExit(output -> {
output.shouldMatch("class.load.*LambHello[$][$]Lambda[$].*0x.*source:.LambHello")
.shouldHaveExitValue(0);
});
}
}

View File

@ -0,0 +1,101 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary Archive an base app class in a base archive and its lambda proxy
* class in a dynamic archive. During runtime, the base app class
* should be loaded from the base archive and the lambda proxy class
* should be loaded from the dynamic archive.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @build SimpleApp sun.hotspot.WhiteBox
* @run driver ClassFileInstaller -jar simpleApp.jar SimpleApp MyClass MyInterface
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. LambdaForClassInBaseArchive
*/
import java.io.File;
import jdk.test.lib.process.OutputAnalyzer;
import jdk.test.lib.process.ProcessTools;
public class LambdaForClassInBaseArchive extends DynamicArchiveTestBase {
static final String classList = System.getProperty("test.classes") +
File.separator + "LambdaForClassInBaseArchive.list";
static final String appClass = "SimpleApp";
public static void main(String[] args) throws Exception {
runTest(LambdaForClassInBaseArchive::testCustomBase);
}
static void testCustomBase() throws Exception {
String topArchiveName = getNewArchiveName("top");
String baseArchiveName = getNewArchiveName("base");
doTestCustomBase(baseArchiveName, topArchiveName);
}
private static void doTestCustomBase(String baseArchiveName, String topArchiveName) throws Exception {
String appJar = ClassFileInstaller.getJarPath("simpleApp.jar");
// dump class list by running the SimpleApp
ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(
"-XX:DumpLoadedClassList=" + classList,
"-cp",
appJar,
appClass);
OutputAnalyzer output = TestCommon.executeAndLog(pb, "dumpClassList");
TestCommon.checkExecReturn(output, 0, true);
// create a custom base archive based on the class list
TestCommon.dumpBaseArchive(baseArchiveName,
"-XX:SharedClassListFile=" + classList,
"-cp", appJar, appClass);
// create a dynamic archive with the custom base archive.
// The SimpleApp class is in the base archive. Its interface
// will be accessed using a lambda expression and the lambda
// proxy class will be archived in the dynamic archive.
dump2(baseArchiveName, topArchiveName,
"-Xlog:cds,cds+dynamic",
"-cp", appJar,
appClass, "lambda")
.assertNormalExit(out -> {
out.shouldHaveExitValue(0)
.shouldContain("Archiving hidden SimpleApp$$Lambda$1");
});
// Run with both base and dynamic archives. The SimpleApp class
// should be loaded from the base archive. Its lambda proxy class
// should be loaded from the dynamic archive.
run2(baseArchiveName, topArchiveName,
"-Xlog:cds,cds+dynamic",
"-Xlog:class+load=trace",
"-cp", appJar,
appClass, "lambda")
.assertNormalExit(out -> {
out.shouldHaveExitValue(0)
.shouldContain("SimpleApp source: shared objects file")
.shouldMatch(".class.load. SimpleApp[$][$]Lambda[$]1/0x.*source:.*shared.*objects.*file.*(top)");
});
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary If the caller class of a lambda proxy class is a hidden class,
* the lambda proxy class will not be archived.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @modules java.base/jdk.internal.misc
* @compile test-classes/LambdaProxyCallerIsHiddenApp.java
* ../../../../../../lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller -jar callerishidden.jar LambdaProxyCallerIsHiddenApp
* jdk/test/lib/compiler/InMemoryJavaCompiler
* jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper$1
* jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper
* jdk/test/lib/compiler/InMemoryJavaCompiler$MemoryJavaFileObject
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. LambdaProxyCallerIsHidden
*/
public class LambdaProxyCallerIsHidden extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(LambdaProxyCallerIsHidden::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("callerishidden.jar");
String mainClass = "LambdaProxyCallerIsHiddenApp";
dump(topArchiveName,
"-Xlog:class+load,cds+dynamic,cds",
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldMatch("Skipping.LambdaHello_0x.*[$][$]Lambda[$].*:.Hidden.class")
.shouldMatch("Skipping.LambdaHello.0x.*:.Hidden.class")
.shouldHaveExitValue(0);
});
run(topArchiveName,
"-Xlog:class+load,cds+dynamic,cds",
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldMatch("class.load.*LambdaHello/0x.*source.*LambdaProxyCallerIsHiddenApp")
.shouldMatch("class.load.*LambdaHello_0x.*[$][$]Lambda[$].*source.*LambdaProxyCallerIsHiddenApp")
.shouldHaveExitValue(0);
});
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary Archive a lambda proxy class created from a nested class. This
* tests the scenario when the caller class is different from the
* nest host.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @build NestApp sun.hotspot.WhiteBox LambdaVerification
* @run driver ClassFileInstaller -jar nest_app.jar NestApp NestApp$InnerA NestApp$InnerB NestApp$InnerA$InnerInnerA
* @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. NestTest
*/
public class NestTest extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(NestTest::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("nest_app.jar");
String mainClass = "NestApp";
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
dump(topArchiveName,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
"-Xlog:class+load=debug,class+unload=info,cds+dynamic=info",
use_whitebox_jar,
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldContain("Archiving hidden NestApp$InnerA$InnerInnerA$$Lambda$")
.shouldHaveExitValue(0);
});
run(topArchiveName,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
use_whitebox_jar,
"-Xlog:class+load=debug,class+resolve=debug,class+unload=info",
"-cp", appJar, mainClass, "run")
.assertNormalExit(output -> {
output.shouldMatch(".class.load.* NestApp[$]InnerA[$]InnerInnerA[$][$]Lambda[$]1/0x.*source:.*shared.*objects.*file.*(top)")
.shouldHaveExitValue(0);
});
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary Test parallel loading of lambda proxy classes.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @build ParallelLambdaLoad sun.hotspot.WhiteBox LambdaVerification
* @run driver ClassFileInstaller -jar parallel_lambda.jar ParallelLambdaLoad ThreadUtil DoSomething LambdaVerification
* @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. ParallelLambdaLoadTest
*/
public class ParallelLambdaLoadTest extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(ParallelLambdaLoadTest::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("parallel_lambda.jar");
String mainClass = "ParallelLambdaLoad";
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
dump(topArchiveName,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI", "-Xlog:cds+dynamic=info",
use_whitebox_jar,
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldContain("Archiving hidden ParallelLambdaLoad$$Lambda$")
.shouldHaveExitValue(0);
});
run(topArchiveName,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
use_whitebox_jar,
"-cp", appJar, mainClass, "run")
.assertNormalExit(output -> {
output.shouldHaveExitValue(0);
});
}
}

View File

@ -0,0 +1,69 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @build PredicateApp sun.hotspot.WhiteBox LambdaVerification
* @run driver ClassFileInstaller -jar predicate_app.jar PredicateApp LambdaVerification
* @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. PredicateTest
*/
public class PredicateTest extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(PredicateTest::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("predicate_app.jar");
String mainClass = "PredicateApp";
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
dump(topArchiveName, "-XX:+UnlockDiagnosticVMOptions", "-XX:+ShowHiddenFrames",
"-XX:+WhiteBoxAPI",
"-Xlog:class+load=debug,cds+dynamic=info",
use_whitebox_jar,
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldContain("Archiving hidden PredicateApp$$Lambda$")
.shouldHaveExitValue(0);
});
run(topArchiveName, "-XX:+UnlockDiagnosticVMOptions", "-XX:+ShowHiddenFrames",
"-XX:+WhiteBoxAPI",
use_whitebox_jar,
"-Xlog:class+load=debug,class+resolve=debug",
"-cp", appJar, mainClass, "run")
.assertNormalExit(output -> {
output.shouldHaveExitValue(0);
});
}
}

View File

@ -0,0 +1,70 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary Hidden class not of type lambda proxy class will not be archived.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @compile ../../../HiddenClasses/InstantiateHiddenClass.java
* ../../../../../../lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller -jar hidden.jar InstantiateHiddenClass
* jdk/test/lib/compiler/InMemoryJavaCompiler
* jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper$1
* jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper
* jdk/test/lib/compiler/InMemoryJavaCompiler$MemoryJavaFileObject
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. RegularHiddenClass
*/
public class RegularHiddenClass extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(RegularHiddenClass::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("hidden.jar");
String mainClass = "InstantiateHiddenClass";
dump(topArchiveName,
"-Xlog:class+load=debug,cds+dynamic,cds",
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldMatch("cds.*Skipping.TestClass.0x.*Hidden.class")
.shouldNotMatch("cds.dynamic.*Archiving.hidden.TestClass.*")
.shouldHaveExitValue(0);
});
run(topArchiveName,
"-Xlog:class+load=debug,cds+dynamic,cds",
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldMatch("class.load.*TestClass.*source.*InstantiateHiddenClass")
.shouldHaveExitValue(0);
});
}
}

View File

@ -0,0 +1,67 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary Outer class is directly referenced during dump time but not during
* runtime. This test makes sure the nest host of a lambda proxy class
* could be loaded from the archive during runtime though it isn't being
* referenced directly.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @build StaticInnerApp sun.hotspot.WhiteBox LambdaVerification
* @run driver ClassFileInstaller -jar static_inner_app.jar StaticInnerApp HelloStaticInner HelloStaticInner$InnerHello
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. StaticInnerTest
*/
public class StaticInnerTest extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(StaticInnerTest::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("static_inner_app.jar");
String mainClass = "StaticInnerApp";
dump(topArchiveName,
"-Xlog:class+load=info,class+nestmates=trace,cds+dynamic=info",
"-cp", appJar, mainClass, "dump")
.assertNormalExit(output -> {
output.shouldContain("Archiving hidden HelloStaticInner$InnerHello$$Lambda$")
.shouldHaveExitValue(0);
});
run(topArchiveName,
"-Xlog:class+load=info",
"-cp", appJar, mainClass, "run")
.assertNormalExit(output -> {
output.shouldHaveExitValue(0)
.shouldContain("HelloStaticInner source: shared objects file (top)")
.shouldMatch(".class.load. HelloStaticInner[$]InnerHello[$][$]Lambda[$]1/0x.*source:.*shared.*objects.*file.*(top)");
});
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary LambdaMetafactory does not support VM anonymous classes.
* This is a sanity test to make sure CDS can handle this case and
* the VM anonymous class should not be archived.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @modules java.base/jdk.internal.misc
* @compile test-classes/UnsafeAndLambdaApp.java
* ../../../../../../lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller -jar unsafeandlambda.jar UnsafeAndLambdaApp
* jdk/test/lib/compiler/InMemoryJavaCompiler
* jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper$1
* jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper
* jdk/test/lib/compiler/InMemoryJavaCompiler$MemoryJavaFileObject
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. UnsafeAndLambda
*/
public class UnsafeAndLambda extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(UnsafeAndLambda::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("unsafeandlambda.jar");
String mainClass = "UnsafeAndLambdaApp";
dump(topArchiveName,
"-Xlog:class+load=debug,cds+dynamic,cds",
"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED",
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldContain("Skipping LambdaHello: Unsafe anonymous class")
.shouldHaveExitValue(0);
});
run(topArchiveName,
"-Xlog:class+load=debug,cds+dynamic,cds",
"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED",
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldMatch("class.load.*LambdaHello/0x.*source.*UnsafeAndLambdaApp")
.shouldHaveExitValue(0);
});
}
}

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary VM unsafe anonymous classes will not be archived.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @modules java.base/jdk.internal.misc
* @compile test-classes/UnsafeAnonymousApp.java
* ../../../../../../lib/jdk/test/lib/compiler/InMemoryJavaCompiler.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller -jar unsafe.jar UnsafeAnonymousApp
* jdk/test/lib/compiler/InMemoryJavaCompiler
* jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper$1
* jdk/test/lib/compiler/InMemoryJavaCompiler$FileManagerWrapper
* jdk/test/lib/compiler/InMemoryJavaCompiler$MemoryJavaFileObject
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. UnsafeAnonymous
*/
public class UnsafeAnonymous extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(UnsafeAnonymous::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("unsafe.jar");
String mainClass = "UnsafeAnonymousApp";
dump(topArchiveName,
"-Xlog:class+load=debug,cds+dynamic,cds",
"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED",
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldContain("Skipping TestClass: Unsafe anonymous class")
.shouldHaveExitValue(0);
});
run(topArchiveName,
"-Xlog:class+load=debug,cds+dynamic,cds",
"--add-exports", "java.base/jdk.internal.misc=ALL-UNNAMED",
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldMatch("class.load.*TestClass/0x.*source.*UnsafeAnonymousApp")
.shouldHaveExitValue(0);
});
}
}

View File

@ -0,0 +1,71 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
/*
* @test
* @summary Test exhaustive use of archived lambda proxy classes.
* @requires vm.cds
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @build UsedAllArchivedLambdasApp sun.hotspot.WhiteBox LambdaVerification
* @run driver ClassFileInstaller -jar used_all_lambda.jar UsedAllArchivedLambdasApp LambdaVerification
* @run driver ClassFileInstaller -jar WhiteBox.jar sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. UsedAllArchivedLambdas
*/
public class UsedAllArchivedLambdas extends DynamicArchiveTestBase {
public static void main(String[] args) throws Exception {
runTest(UsedAllArchivedLambdas::test);
}
static void test() throws Exception {
String topArchiveName = getNewArchiveName();
String appJar = ClassFileInstaller.getJarPath("used_all_lambda.jar");
String mainClass = "UsedAllArchivedLambdasApp";
String wbJar = ClassFileInstaller.getJarPath("WhiteBox.jar");
String use_whitebox_jar = "-Xbootclasspath/a:" + wbJar;
dump(topArchiveName,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI", "-Xlog:cds+dynamic=info",
use_whitebox_jar,
"-cp", appJar, mainClass)
.assertNormalExit(output -> {
output.shouldContain("Archiving hidden UsedAllArchivedLambdasApp$$Lambda$")
.shouldHaveExitValue(0);
});
run(topArchiveName,
"-XX:+UnlockDiagnosticVMOptions",
"-XX:+WhiteBoxAPI",
use_whitebox_jar,
"-Xlog:cds=debug",
"-cp", appJar, mainClass, "run")
.assertNormalExit(output -> {
output.shouldContain("Used all archived lambda proxy classes for: UsedAllArchivedLambdasApp run()Ljava/lang/Runnable;")
.shouldHaveExitValue(0);
});
}
}

View File

@ -0,0 +1,100 @@
#!/bin/bash
# Copyright (c) 2020, 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.
#
echo "// --- start auto-generated"
testnames=( MethodHandlesGeneralTest MethodHandlesAsCollectorTest MethodHandlesCastFailureTest MethodHandlesInvokersTest MethodHandlesPermuteArgumentsTest MethodHandlesSpreadArgumentsTest )
name_suffix='.java'
for i in "${testnames[@]}"
do
fname="$i$name_suffix"
cat << EOF > $fname
// this file is auto-generated by $0. Do not edit manually.
/*
* @test
* @summary Run the $fname test in dynamic CDS archive mode.
* @requires vm.cds & vm.compMode != "Xcomp"
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @compile ../../../../../../../jdk/java/lang/invoke/MethodHandlesTest.java
* ../../../../../../../lib/jdk/test/lib/Utils.java
* ../../../../../../../jdk/java/lang/invoke/$fname
* ../../../../../../../jdk/java/lang/invoke/remote/RemoteExample.java
* ../../../../../../../jdk/java/lang/invoke/common/test/java/lang/invoke/lib/CodeCacheOverflowProcessor.java
* ../test-classes/TestMHApp.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox\$WhiteBoxPermission
* @run junit/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. $i
*/
import org.junit.Test;
import java.io.File;
import jtreg.SkippedException;
import sun.hotspot.gc.GC;
public class $i extends DynamicArchiveTestBase {
@Test
public void test() throws Exception {
runTest($i::testImpl);
}
private static final String classDir = System.getProperty("test.classes");
private static final String mainClass = "TestMHApp";
private static final String javaClassPath = System.getProperty("java.class.path");
private static final String ps = System.getProperty("path.separator");
private static final String testPackageName = "test.java.lang.invoke";
private static final String testClassName = "$i";
private static final String skippedException = "jtreg.SkippedException: Unable to map shared archive: test did not complete";
static void testImpl() throws Exception {
String topArchiveName = getNewArchiveName();
JarBuilder.build("MH", new File(classDir), null);
String appJar = classDir + File.separator + "MH.jar";
String[] classPaths = javaClassPath.split(File.pathSeparator);
String junitJar = null;
for (String path : classPaths) {
if (path.endsWith("junit.jar")) {
junitJar = path;
break;
}
}
dumpAndRun(topArchiveName, "-Xlog:cds,cds+dynamic=debug,class+load=trace",
"-cp", appJar + ps + junitJar,
mainClass, testPackageName + "." + testClassName);
}
}
EOF
done
echo "// --- end auto-generated"

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2020, 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.
*
*/
// this file is auto-generated by ./CDSMHTest_generate.sh. Do not edit manually.
/*
* @test
* @summary Run the MethodHandlesAsCollectorTest.java test in dynamic CDS archive mode.
* @requires vm.cds & vm.compMode != "Xcomp"
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @compile ../../../../../../../jdk/java/lang/invoke/MethodHandlesTest.java
* ../../../../../../../lib/jdk/test/lib/Utils.java
* ../../../../../../../jdk/java/lang/invoke/MethodHandlesAsCollectorTest.java
* ../../../../../../../jdk/java/lang/invoke/remote/RemoteExample.java
* ../../../../../../../jdk/java/lang/invoke/common/test/java/lang/invoke/lib/CodeCacheOverflowProcessor.java
* ../test-classes/TestMHApp.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run junit/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MethodHandlesAsCollectorTest
*/
import org.junit.Test;
import java.io.File;
import jtreg.SkippedException;
import sun.hotspot.gc.GC;
public class MethodHandlesAsCollectorTest extends DynamicArchiveTestBase {
@Test
public void test() throws Exception {
runTest(MethodHandlesAsCollectorTest::testImpl);
}
private static final String classDir = System.getProperty("test.classes");
private static final String mainClass = "TestMHApp";
private static final String javaClassPath = System.getProperty("java.class.path");
private static final String ps = System.getProperty("path.separator");
private static final String testPackageName = "test.java.lang.invoke";
private static final String testClassName = "MethodHandlesAsCollectorTest";
private static final String skippedException = "jtreg.SkippedException: Unable to map shared archive: test did not complete";
static void testImpl() throws Exception {
String topArchiveName = getNewArchiveName();
JarBuilder.build("MH", new File(classDir), null);
String appJar = classDir + File.separator + "MH.jar";
String[] classPaths = javaClassPath.split(File.pathSeparator);
String junitJar = null;
for (String path : classPaths) {
if (path.endsWith("junit.jar")) {
junitJar = path;
break;
}
}
dumpAndRun(topArchiveName, "-Xlog:cds,cds+dynamic=debug,class+load=trace",
"-cp", appJar + ps + junitJar,
mainClass, testPackageName + "." + testClassName);
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2020, 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.
*
*/
// this file is auto-generated by ./CDSMHTest_generate.sh. Do not edit manually.
/*
* @test
* @summary Run the MethodHandlesCastFailureTest.java test in dynamic CDS archive mode.
* @requires vm.cds & vm.compMode != "Xcomp"
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @compile ../../../../../../../jdk/java/lang/invoke/MethodHandlesTest.java
* ../../../../../../../lib/jdk/test/lib/Utils.java
* ../../../../../../../jdk/java/lang/invoke/MethodHandlesCastFailureTest.java
* ../../../../../../../jdk/java/lang/invoke/remote/RemoteExample.java
* ../../../../../../../jdk/java/lang/invoke/common/test/java/lang/invoke/lib/CodeCacheOverflowProcessor.java
* ../test-classes/TestMHApp.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run junit/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MethodHandlesCastFailureTest
*/
import org.junit.Test;
import java.io.File;
import jtreg.SkippedException;
import sun.hotspot.gc.GC;
public class MethodHandlesCastFailureTest extends DynamicArchiveTestBase {
@Test
public void test() throws Exception {
runTest(MethodHandlesCastFailureTest::testImpl);
}
private static final String classDir = System.getProperty("test.classes");
private static final String mainClass = "TestMHApp";
private static final String javaClassPath = System.getProperty("java.class.path");
private static final String ps = System.getProperty("path.separator");
private static final String testPackageName = "test.java.lang.invoke";
private static final String testClassName = "MethodHandlesCastFailureTest";
private static final String skippedException = "jtreg.SkippedException: Unable to map shared archive: test did not complete";
static void testImpl() throws Exception {
String topArchiveName = getNewArchiveName();
JarBuilder.build("MH", new File(classDir), null);
String appJar = classDir + File.separator + "MH.jar";
String[] classPaths = javaClassPath.split(File.pathSeparator);
String junitJar = null;
for (String path : classPaths) {
if (path.endsWith("junit.jar")) {
junitJar = path;
break;
}
}
dumpAndRun(topArchiveName, "-Xlog:cds,cds+dynamic=debug,class+load=trace",
"-cp", appJar + ps + junitJar,
mainClass, testPackageName + "." + testClassName);
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2020, 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.
*
*/
// this file is auto-generated by ./CDSMHTest_generate.sh. Do not edit manually.
/*
* @test
* @summary Run the MethodHandlesGeneralTest.java test in dynamic CDS archive mode.
* @requires vm.cds & vm.compMode != "Xcomp"
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @compile ../../../../../../../jdk/java/lang/invoke/MethodHandlesTest.java
* ../../../../../../../lib/jdk/test/lib/Utils.java
* ../../../../../../../jdk/java/lang/invoke/MethodHandlesGeneralTest.java
* ../../../../../../../jdk/java/lang/invoke/remote/RemoteExample.java
* ../../../../../../../jdk/java/lang/invoke/common/test/java/lang/invoke/lib/CodeCacheOverflowProcessor.java
* ../test-classes/TestMHApp.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run junit/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MethodHandlesGeneralTest
*/
import org.junit.Test;
import java.io.File;
import jtreg.SkippedException;
import sun.hotspot.gc.GC;
public class MethodHandlesGeneralTest extends DynamicArchiveTestBase {
@Test
public void test() throws Exception {
runTest(MethodHandlesGeneralTest::testImpl);
}
private static final String classDir = System.getProperty("test.classes");
private static final String mainClass = "TestMHApp";
private static final String javaClassPath = System.getProperty("java.class.path");
private static final String ps = System.getProperty("path.separator");
private static final String testPackageName = "test.java.lang.invoke";
private static final String testClassName = "MethodHandlesGeneralTest";
private static final String skippedException = "jtreg.SkippedException: Unable to map shared archive: test did not complete";
static void testImpl() throws Exception {
String topArchiveName = getNewArchiveName();
JarBuilder.build("MH", new File(classDir), null);
String appJar = classDir + File.separator + "MH.jar";
String[] classPaths = javaClassPath.split(File.pathSeparator);
String junitJar = null;
for (String path : classPaths) {
if (path.endsWith("junit.jar")) {
junitJar = path;
break;
}
}
dumpAndRun(topArchiveName, "-Xlog:cds,cds+dynamic=debug,class+load=trace",
"-cp", appJar + ps + junitJar,
mainClass, testPackageName + "." + testClassName);
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2020, 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.
*
*/
// this file is auto-generated by ./CDSMHTest_generate.sh. Do not edit manually.
/*
* @test
* @summary Run the MethodHandlesInvokersTest.java test in dynamic CDS archive mode.
* @requires vm.cds & vm.compMode != "Xcomp"
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @compile ../../../../../../../jdk/java/lang/invoke/MethodHandlesTest.java
* ../../../../../../../lib/jdk/test/lib/Utils.java
* ../../../../../../../jdk/java/lang/invoke/MethodHandlesInvokersTest.java
* ../../../../../../../jdk/java/lang/invoke/remote/RemoteExample.java
* ../../../../../../../jdk/java/lang/invoke/common/test/java/lang/invoke/lib/CodeCacheOverflowProcessor.java
* ../test-classes/TestMHApp.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run junit/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MethodHandlesInvokersTest
*/
import org.junit.Test;
import java.io.File;
import jtreg.SkippedException;
import sun.hotspot.gc.GC;
public class MethodHandlesInvokersTest extends DynamicArchiveTestBase {
@Test
public void test() throws Exception {
runTest(MethodHandlesInvokersTest::testImpl);
}
private static final String classDir = System.getProperty("test.classes");
private static final String mainClass = "TestMHApp";
private static final String javaClassPath = System.getProperty("java.class.path");
private static final String ps = System.getProperty("path.separator");
private static final String testPackageName = "test.java.lang.invoke";
private static final String testClassName = "MethodHandlesInvokersTest";
private static final String skippedException = "jtreg.SkippedException: Unable to map shared archive: test did not complete";
static void testImpl() throws Exception {
String topArchiveName = getNewArchiveName();
JarBuilder.build("MH", new File(classDir), null);
String appJar = classDir + File.separator + "MH.jar";
String[] classPaths = javaClassPath.split(File.pathSeparator);
String junitJar = null;
for (String path : classPaths) {
if (path.endsWith("junit.jar")) {
junitJar = path;
break;
}
}
dumpAndRun(topArchiveName, "-Xlog:cds,cds+dynamic=debug,class+load=trace",
"-cp", appJar + ps + junitJar,
mainClass, testPackageName + "." + testClassName);
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2020, 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.
*
*/
// this file is auto-generated by ./CDSMHTest_generate.sh. Do not edit manually.
/*
* @test
* @summary Run the MethodHandlesPermuteArgumentsTest.java test in dynamic CDS archive mode.
* @requires vm.cds & vm.compMode != "Xcomp"
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @compile ../../../../../../../jdk/java/lang/invoke/MethodHandlesTest.java
* ../../../../../../../lib/jdk/test/lib/Utils.java
* ../../../../../../../jdk/java/lang/invoke/MethodHandlesPermuteArgumentsTest.java
* ../../../../../../../jdk/java/lang/invoke/remote/RemoteExample.java
* ../../../../../../../jdk/java/lang/invoke/common/test/java/lang/invoke/lib/CodeCacheOverflowProcessor.java
* ../test-classes/TestMHApp.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run junit/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MethodHandlesPermuteArgumentsTest
*/
import org.junit.Test;
import java.io.File;
import jtreg.SkippedException;
import sun.hotspot.gc.GC;
public class MethodHandlesPermuteArgumentsTest extends DynamicArchiveTestBase {
@Test
public void test() throws Exception {
runTest(MethodHandlesPermuteArgumentsTest::testImpl);
}
private static final String classDir = System.getProperty("test.classes");
private static final String mainClass = "TestMHApp";
private static final String javaClassPath = System.getProperty("java.class.path");
private static final String ps = System.getProperty("path.separator");
private static final String testPackageName = "test.java.lang.invoke";
private static final String testClassName = "MethodHandlesPermuteArgumentsTest";
private static final String skippedException = "jtreg.SkippedException: Unable to map shared archive: test did not complete";
static void testImpl() throws Exception {
String topArchiveName = getNewArchiveName();
JarBuilder.build("MH", new File(classDir), null);
String appJar = classDir + File.separator + "MH.jar";
String[] classPaths = javaClassPath.split(File.pathSeparator);
String junitJar = null;
for (String path : classPaths) {
if (path.endsWith("junit.jar")) {
junitJar = path;
break;
}
}
dumpAndRun(topArchiveName, "-Xlog:cds,cds+dynamic=debug,class+load=trace",
"-cp", appJar + ps + junitJar,
mainClass, testPackageName + "." + testClassName);
}
}

View File

@ -0,0 +1,87 @@
/*
* Copyright (c) 2020, 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.
*
*/
// this file is auto-generated by ./CDSMHTest_generate.sh. Do not edit manually.
/*
* @test
* @summary Run the MethodHandlesSpreadArgumentsTest.java test in dynamic CDS archive mode.
* @requires vm.cds & vm.compMode != "Xcomp"
* @comment Some of the tests run excessively slowly with -Xcomp. The original
* tests aren't executed with -Xcomp in the CI pipeline, so let's exclude
* the generated tests from -Xcomp execution as well.
* @library /test/lib /test/hotspot/jtreg/runtime/cds/appcds
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive
* /test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes
* @compile ../../../../../../../jdk/java/lang/invoke/MethodHandlesTest.java
* ../../../../../../../lib/jdk/test/lib/Utils.java
* ../../../../../../../jdk/java/lang/invoke/MethodHandlesSpreadArgumentsTest.java
* ../../../../../../../jdk/java/lang/invoke/remote/RemoteExample.java
* ../../../../../../../jdk/java/lang/invoke/common/test/java/lang/invoke/lib/CodeCacheOverflowProcessor.java
* ../test-classes/TestMHApp.java
* @build sun.hotspot.WhiteBox
* @run driver ClassFileInstaller sun.hotspot.WhiteBox sun.hotspot.WhiteBox$WhiteBoxPermission
* @run junit/othervm/timeout=240 -XX:+UnlockDiagnosticVMOptions -XX:+WhiteBoxAPI -Xbootclasspath/a:. MethodHandlesSpreadArgumentsTest
*/
import org.junit.Test;
import java.io.File;
import jtreg.SkippedException;
import sun.hotspot.gc.GC;
public class MethodHandlesSpreadArgumentsTest extends DynamicArchiveTestBase {
@Test
public void test() throws Exception {
runTest(MethodHandlesSpreadArgumentsTest::testImpl);
}
private static final String classDir = System.getProperty("test.classes");
private static final String mainClass = "TestMHApp";
private static final String javaClassPath = System.getProperty("java.class.path");
private static final String ps = System.getProperty("path.separator");
private static final String testPackageName = "test.java.lang.invoke";
private static final String testClassName = "MethodHandlesSpreadArgumentsTest";
private static final String skippedException = "jtreg.SkippedException: Unable to map shared archive: test did not complete";
static void testImpl() throws Exception {
String topArchiveName = getNewArchiveName();
JarBuilder.build("MH", new File(classDir), null);
String appJar = classDir + File.separator + "MH.jar";
String[] classPaths = javaClassPath.split(File.pathSeparator);
String junitJar = null;
for (String path : classPaths) {
if (path.endsWith("junit.jar")) {
junitJar = path;
break;
}
}
dumpAndRun(topArchiveName, "-Xlog:cds,cds+dynamic=debug,class+load=trace",
"-cp", appJar + ps + junitJar,
mainClass, testPackageName + "." + testClassName);
}
}

View File

@ -0,0 +1,58 @@
/*
* Copyright (c) 2020, 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.
*
*/
public class BasicLambdaApp {
static boolean isRuntime;
public static void main(String[] args) {
isRuntime = (args.length == 1 && args[0].equals("run")) ? true : false;
testNonCapturingLambda();
testCapturingLambda();
}
static void testNonCapturingLambda() {
doit(() -> {
System.out.println("Hello from Lambda");
LambdaVerification.verifyCallerIsArchivedLambda(isRuntime);
});
}
static int lastX;
static void testCapturingLambda() {
lastX = -1;
for (int i=0; i<10; i++) {
final int x = i;
doit(() -> {
if (x != lastX + 1) {
throw new RuntimeException(x + " != " + (lastX + 1));
}
lastX = x;
LambdaVerification.verifyCallerIsArchivedLambda(isRuntime);
});
}
}
static void doit(Runnable t) {
t.run();
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.io.File;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;
public class CustomLoaderApp {
private static String className = "LambHello";
public static void main(String args[]) throws Exception {
String path = args[0];
URL url = new File(path).toURI().toURL();
URL[] urls = new URL[] {url};
System.out.println(path);
System.out.println(url);
URLClassLoader urlClassLoader =
new URLClassLoader("HelloClassLoader", urls, null);
Class c = Class.forName(className, true, urlClassLoader);
System.out.println(c);
System.out.println(c.getClassLoader());
Object o = c.newInstance();
if (c.getClassLoader() != urlClassLoader) {
throw new RuntimeException("c.getClassLoader() == " + c.getClassLoader() +
", expected == " + urlClassLoader);
}
Method method = c.getDeclaredMethod("doTest");
method.invoke(o);
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright (c) 2020, 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.
*
*/
public class LambHello {
public static void main(String[] args) {
}
public void doTest() {
doit(() -> {
System.out.println("Hello from doTest");
});
}
static void doit(Runnable t) {
t.run();
}
}

View File

@ -0,0 +1,53 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodHandles.Lookup;
import static java.lang.invoke.MethodHandles.Lookup.ClassOption.*;
import jdk.test.lib.compiler.InMemoryJavaCompiler;
import jdk.internal.misc.Unsafe;
public class LambdaProxyCallerIsHiddenApp {
static byte klassbuf[] = InMemoryJavaCompiler.compile("LambdaHello",
"public class LambdaHello { " +
" static Runnable run; " +
" static { " +
" run = LambdaHello::myrun; " +
" } " +
" static void myrun() { " +
" System.out.println(\"Hello\"); " +
" } " +
"} ");
public static void main(String args[]) throws Exception {
Lookup lookup = MethodHandles.lookup();
System.out.println("lookup: " + lookup);
Class<?> hiddenClass = lookup.defineHiddenClass(klassbuf, true, NESTMATE, STRONG).lookupClass();
System.out.println("hiddenClass: " + hiddenClass);
Object o = hiddenClass.newInstance();
System.out.println("o: " + o);
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.lang.StackWalker.StackFrame;
import java.util.List;
import java.util.stream.Collectors;
import java.util.Set;
import sun.hotspot.WhiteBox;
public class LambdaVerification {
static void verifyCallerIsArchivedLambda(boolean isRuntime) {
// getCallerClass(0) = verifyCallerIsArchivedLambda
// getCallerClass(1) = testNonCapturingLambda or testCapturingLambda
// getCallerClass(2) = the lambda proxy class that should be archived by CDS.
Class<?> c = getCallerClass(2);
System.out.println("Lambda proxy class = " + c);
String cn = c.getName();
System.out.println(" cn = " + cn);
String hiddenClassName = cn.replace('/', '+');
String lambdaClassName = cn.substring(0, cn.lastIndexOf('/'));
System.out.println(" lambda name = " + lambdaClassName);
WhiteBox wb = WhiteBox.getWhiteBox();
if (isRuntime) {
// check that c is a shared class
if (wb.isSharedClass(c)) {
System.out.println("As expected, " + c + " is in shared space.");
} else {
throw new java.lang.RuntimeException(c + " must be in shared space.");
}
// check that lambda class cannot be found manually
try {
Class.forName(hiddenClassName);
} catch (ClassNotFoundException cnfe) {
cnfe.printStackTrace(System.out);
System.out.println("As expected, loading of " + hiddenClassName + " should result in ClassNotFoundException.");
} catch (Exception ex) {
throw ex;
}
// check that lambda class is alive
if (wb.isClassAlive(hiddenClassName)) {
System.out.println("As expected, " + cn + " is alive.");
} else {
throw new java.lang.RuntimeException(cn + " should be alive.");
}
} else {
if (wb.isSharedClass(c)) {
throw new java.lang.RuntimeException(c + " must not be in shared space.");
} else {
System.out.println("As expected, " + c + " is not in shared space.");
}
}
//System.out.println("=== Here's the call stack");
//(new Throwable()).printStackTrace(System.out);
//System.out.println("===");
System.out.println("Succeeded");
}
// depth is 0-based -- i.e., depth==0 returns the class of the immediate caller of getCallerClass
static Class<?> getCallerClass(int depth) {
// Need to add the frame of the getCallerClass -- so the immediate caller (depth==0) of this method
// is at stack.get(1) == stack.get(depth+1);
StackWalker walker = StackWalker.getInstance(
Set.of(StackWalker.Option.RETAIN_CLASS_REFERENCE,
StackWalker.Option.SHOW_HIDDEN_FRAMES));
List<StackFrame> stack = walker.walk(s -> s.limit(depth+2).collect(Collectors.toList()));
return stack.get(depth+1).getDeclaringClass();
}
}

View File

@ -0,0 +1,52 @@
/*
* Copyright (c) 2020, 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.
*
*/
public class NestApp {
public static void main(String[] args) throws Exception {
Class<NestApp.InnerA.InnerInnerA> clazzInnerInnerA = NestApp.InnerA.InnerInnerA.class;
NestApp.InnerA.InnerInnerA iia = (NestApp.InnerA.InnerInnerA)clazzInnerInnerA.newInstance();
}
public NestApp(String type, int weight) {
}
static class InnerA {
static class InnerInnerA {
static {
doit(() -> {
System.out.println("Hello from InnerInnerA");
});
}
}
}
public class InnerB {
}
static void doit(Runnable t) {
t.run();
}
}

View File

@ -0,0 +1,218 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.util.concurrent.atomic.AtomicInteger;
import java.util.List;
import java.util.HashMap;
import java.util.ArrayList;
public class ParallelLambdaLoad {
public static int NUM_THREADS = 10;
public static int MAX_CLASSES = 10;
public static AtomicInteger num_ready[];
public static boolean isRuntime;
public static void main(String args[]) throws Throwable {
isRuntime = (args.length == 1 && args[0].equals("run")) ? true : false;
num_ready = new AtomicInteger[MAX_CLASSES];
for (int i = 0; i < MAX_CLASSES; i++) {
num_ready[i] = new AtomicInteger();
}
ArrayList<Thread> list = new ArrayList<>();
list.add(new Thread(() -> {
DoSomething ds = new DoSomething(0);
{ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
}));
list.add(new Thread(() -> {
DoSomething ds = new DoSomething(1);
{ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
}));
list.add(new Thread(() -> {
DoSomething ds = new DoSomething(2);
{ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
}));
list.add(new Thread(() -> {
DoSomething ds = new DoSomething(3);
{ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
}));
list.add(new Thread(() -> {
DoSomething ds = new DoSomething(4);
{ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
}));
list.add(new Thread(() -> {
DoSomething ds = new DoSomething(5);
{ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
}));
list.add(new Thread(() -> {
DoSomething ds = new DoSomething(6);
{ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
}));
list.add(new Thread(() -> {
DoSomething ds = new DoSomething(7);
{ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
}));
list.add(new Thread(() -> {
DoSomething ds = new DoSomething(8);
{ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
}));
list.add(new Thread(() -> {
DoSomething ds = new DoSomething(9);
{ThreadUtil.WaitForLock(0); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(1); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(2); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(3); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(4); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(5); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(6); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(7); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(8); Runnable runner = ds::run; runner.run();}
{ThreadUtil.WaitForLock(9); Runnable runner = ds::run; runner.run();}
}));
for (Thread t : list) {
t.start();
}
for (Thread t : list) {
t.join();
}
synchronized(map) {
System.out.println("map size " + map.size());
int expectedSize = NUM_THREADS * MAX_CLASSES;
if (map.size() != expectedSize) {
throw new RuntimeException("Expected number of lamdba classes is " +
expectedSize + " but got only " + map.size());
}
}
}
static HashMap<Class<?>, Class<?>> map = new HashMap<>();
}
class DoSomething {
DoSomething(int dummy) {}
public void run() {
Class<?> c = LambdaVerification.getCallerClass(1);
synchronized(ParallelLambdaLoad.map) {
ParallelLambdaLoad.map.put(c, c);
}
LambdaVerification.verifyCallerIsArchivedLambda(ParallelLambdaLoad.isRuntime);
}
}
class ThreadUtil {
static void WaitForLock(int i) {
// Spin until every thread is ready to proceed
ParallelLambdaLoad.num_ready[i].incrementAndGet();
while (ParallelLambdaLoad.num_ready[i].intValue() < ParallelLambdaLoad.NUM_THREADS) {
;
}
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
public class PredicateApp {
public static void main(String[] args){
boolean isRuntime = (args.length == 1 && args[0].equals("run")) ? true : false;
List languages = Arrays.asList("Java", "Scala", "C++", "Haskell", "Lisp");
doit(() -> {
System.out.println("Languages which starts with J :");
filter(languages, (str)->((String)str).startsWith("J"));
LambdaVerification.verifyCallerIsArchivedLambda(isRuntime);
});
doit(() -> {
System.out.println("Languages which ends with a ");
filter(languages, (str)->((String)str).endsWith("a"));
LambdaVerification.verifyCallerIsArchivedLambda(isRuntime);
});
doit(() -> {
System.out.println("Print all languages :");
filter(languages, (str)->true);
LambdaVerification.verifyCallerIsArchivedLambda(isRuntime);
});
doit(() -> {
System.out.println("Print no language : ");
filter(languages, (str)->false);
LambdaVerification.verifyCallerIsArchivedLambda(isRuntime);
});
doit(() -> {
System.out.println("Print language whose length greater than 4:");
filter(languages, (str)->((String)str).length() > 4);
LambdaVerification.verifyCallerIsArchivedLambda(isRuntime);
});
}
public static void filter(List names, Predicate condition) {
names.stream().filter((name) -> (condition.test(name))).forEach((name) -> {
System.out.println(name + " ");
});
}
static void doit(Runnable t) {
t.run();
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright (c) 2020, 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.
*
*/
@FunctionalInterface
interface MyInterface {
public String sayHello();
}
class MyClass implements MyInterface {
public String sayHello() {
return "Hello";
}
}
public class SimpleApp {
public static boolean useLambda;
public static void main(String args[]) {
useLambda = (args.length == 1 && args[0].equals("lambda")) ? true : false;
if (!useLambda) {
MyClass mc = new MyClass();
System.out.println(mc.sayHello());
} else {
MyInterface msg = () -> {
return "Hello";
};
System.out.println(msg.sayHello());
}
}
}

View File

@ -0,0 +1,46 @@
/*
* Copyright (c) 2020, 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.
*
*/
class HelloStaticInner {
static class InnerHello {
public static void m1() {
doit(() -> {
System.out.println("Hello from Lambda");
});
}
static void doit(Runnable t) {
t.run();
}
}
}
public class StaticInnerApp {
public static void main(String[] args) {
if (args.length > 0 && args[0].equals("dump")) {
Object o = new HelloStaticInner();
}
HelloStaticInner.InnerHello.m1();
}
}

View File

@ -0,0 +1,77 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
public class TestMHApp {
public static void main(String args[]) throws Exception {
try {
Class<?> testClass = Class.forName(args[0]);
System.out.println(testClass);
Object obj = testClass.newInstance();
final List<Method> allMethods = new ArrayList<Method>(Arrays.asList(testClass.getDeclaredMethods()));
for (final Method method : allMethods) {
//System.out.println(method.toString());
method.setAccessible(true);
Annotation[] annotations = null;
try {
annotations = method.getDeclaredAnnotations();
} catch (Throwable th) {
System.out.println("skipping method");
continue;
}
boolean isTest = false;
for (Annotation annotation : annotations) {
String annotationString = annotation.toString();
System.out.println(" annotation: " + annotationString);
if (annotationString.startsWith("@org.junit.Test")) {
isTest = true;
}
}
if (isTest) {
System.out.println(" invoking method: " + method.getName());
try {
method.invoke(obj);
} catch (IllegalAccessException iae) {
System.out.println("Got IllegalAccessException!!!");
System.out.println(iae.getCause());
} catch (InvocationTargetException ite) {
System.out.println("Got InvocationTargetException!!!");
//System.out.println(ite.getCause());
throw ite;
}
}
}
} catch (ClassNotFoundException cnfe) {
System.out.println("Class not found: " + args[0]);
} catch (java.lang.IllegalAccessError iae) {
System.out.println("Skipping test: " + args[0]);
}
}
}

View File

@ -0,0 +1,94 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.List;
public class TestStreamApp {
public static final String testAnnotation = "@org.testng.annotations.Test";
public static void main(String args[]) throws Exception {
try {
Class<?> testClass = Class.forName(args[0]);
System.out.println(testClass);
Annotation[] classAnnotations = null;
boolean classHasTestAnnotation = false;
try {
classAnnotations= testClass.getDeclaredAnnotations();
for (Annotation classAnnotation : classAnnotations) {
String annoString = classAnnotation.toString();
System.out.println(" class annotation: " + annoString);
if (annoString.startsWith(testAnnotation)) {
classHasTestAnnotation = true;
}
}
} catch (Throwable th) {
System.out.println("Skip class annotation");
}
Object obj = testClass.newInstance();
final List<Method> allMethods = new ArrayList<Method>(Arrays.asList(testClass.getDeclaredMethods()));
for (final Method method : allMethods) {
//System.out.println(method.toString());
Annotation[] annotations = method.getDeclaredAnnotations();
boolean isTest = false;
/*
if (classHasTestAnnotation) {
if (method.toString().indexOf(args[0] + ".test") != -1) {
isTest = true;
}
} else {
for (Annotation annotation : annotations) {
String annotationString = annotation.toString();
System.out.println(" annotation: " + annotationString);
if (annotationString.startsWith(testAnnotation)) {
isTest = true;
}
}
}
*/
if (method.getName().startsWith("test")) {
isTest = true;
}
if (isTest) {
System.out.println(" invoking method: " + method.getName());
try {
method.invoke(obj);
} catch (IllegalAccessException iae) {
System.out.println("Got IllegalAccessException!!!");
System.out.println(iae.getCause());
} catch (InvocationTargetException ite) {
System.out.println("Got InvocationTargetException!!!");
//System.out.println(ite.getCause());
throw ite;
}
}
}
} catch (ClassNotFoundException cnfe) {
System.out.println("Class not found!");
}
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import jdk.test.lib.compiler.InMemoryJavaCompiler;
import jdk.internal.misc.Unsafe;
public class UnsafeAndLambdaApp {
static byte klassbuf[] = InMemoryJavaCompiler.compile("LambdaHello",
"public class LambdaHello { " +
" public LambdaHello() { " +
" doit(() -> { " +
" System.out.println(\"Hello from Lambda\"); " +
" }); " +
" } " +
" static void doit (Runnable r) { " +
" r.run(); " +
" } " +
"} ");
public static void main(String args[]) throws Exception {
Unsafe unsafe = Unsafe.getUnsafe();
Class klass = unsafe.defineAnonymousClass(UnsafeAndLambdaApp.class, klassbuf, new Object[0]);
try {
Object obj = klass.newInstance();
// If we come to here, LambdaMetafactory has probably been modified
// to support vm-anon classes. In that case, we will need more tests for CDS.
throw new RuntimeException("Unexpected support for lambda classes in VM anonymous classes");
} catch (java.lang.InternalError expected) {
System.out.println("Caught expected java.lang.InternalError");
}
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import jdk.test.lib.compiler.InMemoryJavaCompiler;
import jdk.internal.misc.Unsafe;
public class UnsafeAnonymousApp {
static byte klassbuf[] = InMemoryJavaCompiler.compile("TestClass",
"public class TestClass { " +
"} ");
public static void main(String args[]) throws Exception {
Unsafe unsafe = Unsafe.getUnsafe();
Class klass = unsafe.defineAnonymousClass(UnsafeAnonymousApp.class, klassbuf, new Object[0]);
Object obj = klass.newInstance();
}
}

View File

@ -0,0 +1,76 @@
/*
* Copyright (c) 2020, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*
*/
import java.util.HashMap;
import sun.hotspot.WhiteBox;
public class UsedAllArchivedLambdasApp {
public static boolean isRuntime;
public static int NUM_CLASSES = 3;
public static WhiteBox wb = WhiteBox.getWhiteBox();
public static HashMap<Class<?>, Class<?>> inArchiveMap = new HashMap<>();
public static HashMap<Class<?>, Class<?>> notInArchiveMap = new HashMap<>();
public static void main(String args[]) {
isRuntime = (args.length == 1 && args[0].equals("run")) ? true : false;
{Runnable run1 = UsedAllArchivedLambdasApp::myrun; run1.run();}
{Runnable run1 = UsedAllArchivedLambdasApp::myrun; run1.run();}
{Runnable run1 = UsedAllArchivedLambdasApp::myrun; run1.run();}
if (isRuntime) {
{Runnable run1 = UsedAllArchivedLambdasApp::myrun; run1.run();}
{Runnable run1 = UsedAllArchivedLambdasApp::myrun; run1.run();}
{Runnable run1 = UsedAllArchivedLambdasApp::myrun; run1.run();}
}
int mapSize = 0;
if (isRuntime) {
mapSize = inArchiveMap.size();
System.out.println("Number of lambda classes in archive: " + mapSize);
if (mapSize != NUM_CLASSES) {
throw new RuntimeException("Expected number of lambda classes in archive is " +
NUM_CLASSES + " but got " + mapSize);
}
mapSize = notInArchiveMap.size();
System.out.println("Number of lambda classes in archive: " + mapSize);
if (mapSize != NUM_CLASSES) {
throw new RuntimeException("Expected number of lambda classes NOT in archive is " +
NUM_CLASSES + " but got " + mapSize);
}
}
}
static void myrun() {
Class<?> c = LambdaVerification.getCallerClass(1);
if (isRuntime) {
if (wb.isSharedClass(c)) {
System.out.println(c.getName() + " is a shared class");
inArchiveMap.put(c,c);
} else {
System.out.println(c.getName() + " is NOT a shared class");
notInArchiveMap.put(c,c);
}
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2018, 2019, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2018, 2020, 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
@ -45,6 +45,9 @@ public class AnonVmClassesDuringDump {
public static String cdsDiagnosticOption = "-XX:+AllowArchivingWithJavaAgent";
public static final boolean dynamicMode =
Boolean.getBoolean(System.getProperty("test.dynamic.cds.archive", "false"));
public static void main(String[] args) throws Throwable {
String agentJar =
ClassFileInstaller.writeJar("AnonVmClassesDuringDumpTransformer.jar",
@ -71,13 +74,17 @@ public class AnonVmClassesDuringDump {
// during run time, anonymous classes shouldn't be loaded from the archive
TestCommon.run("-cp", appJar,
"-XX:+UnlockDiagnosticVMOptions", cdsDiagnosticOption, Hello.class.getName())
.assertNormalExit(output -> output.shouldNotMatch(pattern));
.assertNormalExit(dynamicMode ?
output -> output.shouldMatch(pattern) :
output -> output.shouldNotMatch(pattern));
// inspect the archive and make sure no anonymous class is in there
TestCommon.run("-cp", appJar,
"-XX:+UnlockDiagnosticVMOptions", cdsDiagnosticOption,
"-XX:+PrintSharedArchiveAndExit", "-XX:+PrintSharedDictionary", Hello.class.getName())
.assertNormalExit(output -> output.shouldNotMatch(class_pattern));
.assertNormalExit(dynamicMode ?
output -> output.shouldMatch(pattern) :
output -> output.shouldNotMatch(pattern));
}
}

View File

@ -26,6 +26,7 @@ package jdk.test.lib;
import java.io.File;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.net.Inet6Address;
import java.net.InetAddress;
import java.net.InetSocketAddress;
@ -834,7 +835,7 @@ public final class Utils {
public static String getTestName() {
String result = null;
// If we are using testng, then we should be able to load the "Test" annotation.
Class<? extends Annotation> testClassAnnotation;
Class<? extends Annotation> testClassAnnotation, junitTestClassAnnotation;
try {
testClassAnnotation = (Class<? extends Annotation>)Class.forName("org.testng.annotations.Test");
@ -842,13 +843,21 @@ public final class Utils {
testClassAnnotation = null;
}
// If we are using junit, then we should be able to load the "Test" annotation.
try {
junitTestClassAnnotation = (Class<? extends Annotation>)Class.forName("org.junit.Test");
} catch (ClassNotFoundException e) {
junitTestClassAnnotation = null;
}
StackTraceElement[] elms = (new Throwable()).getStackTrace();
for (StackTraceElement n: elms) {
String className = n.getClassName();
// If this is a "main" method, then use its class name, but only
// if we are not using testng.
if (testClassAnnotation == null && "main".equals(n.getMethodName())) {
// if we are not using testng or junit.
if (testClassAnnotation == null && junitTestClassAnnotation == null &&
"main".equals(n.getMethodName())) {
result = className;
break;
}
@ -867,6 +876,26 @@ public final class Utils {
throw new RuntimeException("Unexpected exception: " + e, e);
}
}
// If this is a junit test, the test will have no "main" method. We can
// detect a junit test class by going through all the methods and
// check if the method has the org.junit.Test annotation. If present,
// then use the name of this class.
if (junitTestClassAnnotation != null) {
try {
Class<?> c = Class.forName(className);
Method[] methods = c.getMethods();
for (Method method : methods) {
if (method.getName().equals(n.getMethodName()) &&
method.isAnnotationPresent(junitTestClassAnnotation)) {
result = className;
break;
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeException("Unexpected exception: " + e, e);
}
}
}
if (result == null) {