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:
parent
268d870187
commit
847a3baca8
@ -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
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
@ -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(©);
|
||||
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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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) {
|
||||
|
@ -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();
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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.
|
||||
*/
|
||||
|
59
src/java.base/share/native/libjava/LambdaProxyClassArchive.c
Normal file
59
src/java.base/share/native/libjava/LambdaProxyClassArchive.c
Normal 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);
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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?)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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)");
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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)");
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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);
|
||||
});
|
||||
}
|
||||
}
|
@ -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"
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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) {
|
||||
;
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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]);
|
||||
}
|
||||
}
|
||||
}
|
@ -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!");
|
||||
}
|
||||
}
|
||||
}
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user