changeset 59716:f32cc62c5821

8198698: Support Lambda proxy classes in dynamic CDS archive Summary: Added archving of hidden classes of type lambda proxy classes. Reviewed-by: mchung, iklam, dholmes Contributed-by: calvin.cheung@oracle.com, ioi.lam@oracle.com
author ccheung
date Wed, 10 Jun 2020 15:50:26 +0000
parents 6109276549d7
children e8d34f3f6833
files make/hotspot/symbols/symbols-unix src/hotspot/share/classfile/systemDictionary.cpp src/hotspot/share/classfile/systemDictionary.hpp src/hotspot/share/classfile/systemDictionaryShared.cpp src/hotspot/share/classfile/systemDictionaryShared.hpp src/hotspot/share/include/jvm.h src/hotspot/share/memory/dynamicArchive.cpp src/hotspot/share/oops/constantPool.cpp src/hotspot/share/oops/instanceKlass.cpp src/hotspot/share/oops/instanceKlass.hpp src/hotspot/share/oops/klass.hpp src/hotspot/share/prims/jvm.cpp src/hotspot/share/runtime/mutexLocker.cpp src/hotspot/share/runtime/mutexLocker.hpp src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java src/java.base/share/classes/java/lang/invoke/LambdaProxyClassArchive.java src/java.base/share/classes/jdk/internal/misc/VM.java src/java.base/share/native/libjava/LambdaProxyClassArchive.c src/java.base/share/native/libjava/VM.c test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/BasicLambdaTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSStreamTestDriver.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DoubleSumAverageTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaForClassInBaseArchive.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaProxyCallerIsHidden.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/NestTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ParallelLambdaLoadTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/PredicateTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RegularHiddenClass.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/StaticInnerTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnsafeAndLambda.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnsafeAnonymous.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UsedAllArchivedLambdas.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/CDSMHTest_generate.sh test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesAsCollectorTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesCastFailureTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesGeneralTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesInvokersTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesPermuteArgumentsTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesSpreadArgumentsTest.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/BasicLambdaApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/CustomLoaderApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/LambHello.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/LambdaProxyCallerIsHiddenApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/LambdaVerification.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/NestApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/ParallelLambdaLoad.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/PredicateApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/SimpleApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/StaticInnerApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/TestMHApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/TestStreamApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/UnsafeAndLambdaApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/UnsafeAnonymousApp.java test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/UsedAllArchivedLambdasApp.java test/hotspot/jtreg/runtime/cds/appcds/javaldr/AnonVmClassesDuringDump.java test/lib/jdk/test/lib/Utils.java
diffstat 57 files changed, 3724 insertions(+), 39 deletions(-) [+]
line wrap: on
line diff
--- a/make/hotspot/symbols/symbols-unix	Wed Jun 10 11:12:33 2020 -0400
+++ b/make/hotspot/symbols/symbols-unix	Wed Jun 10 15:50:26 2020 +0000
@@ -143,6 +143,8 @@
 JVM_Interrupt
 JVM_InvokeMethod
 JVM_IsArrayClass
+JVM_IsCDSDumpingEnabled
+JVM_IsCDSSharingEnabled
 JVM_IsConstructorIx
 JVM_IsHiddenClass
 JVM_IsInterface
@@ -155,6 +157,7 @@
 JVM_LatestUserDefinedLoader
 JVM_LoadLibrary
 JVM_LookupDefineClass
+JVM_LookupLambdaProxyClassFromArchive
 JVM_MaxMemory
 JVM_MaxObjectInspectionAge
 JVM_MonitorNotify
@@ -171,6 +174,7 @@
 JVM_RawMonitorDestroy
 JVM_RawMonitorEnter
 JVM_RawMonitorExit
+JVM_RegisterLambdaProxyClassForArchiving
 JVM_RegisterSignal
 JVM_ReleaseUTF
 JVM_ResumeThread
--- a/src/hotspot/share/classfile/systemDictionary.cpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/classfile/systemDictionary.cpp	Wed Jun 10 15:50:26 2020 +0000
@@ -703,7 +703,7 @@
   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 @@
   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 @@
     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.
--- a/src/hotspot/share/classfile/systemDictionary.hpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/classfile/systemDictionary.hpp	Wed Jun 10 15:50:26 2020 +0000
@@ -132,6 +132,7 @@
 class ProtectionDomainCacheTable;
 class ProtectionDomainCacheEntry;
 class GCTimer;
+class EventClassLoad;
 
 #define WK_KLASS_ENUM_NAME(kname)    kname##_knum
 
@@ -606,6 +607,7 @@
   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 @@
                                             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,
--- a/src/hotspot/share/classfile/systemDictionaryShared.cpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/classfile/systemDictionaryShared.cpp	Wed Jun 10 15:50:26 2020 +0000
@@ -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 @@
 
   InstanceKlass*               _klass;
   bool                         _failed_verification;
+  bool                         _is_archived_lambda_proxy;
   int                          _id;
   int                          _clsfile_size;
   int                          _clsfile_crc32;
@@ -106,6 +108,7 @@
   DumpTimeSharedClassInfo() {
     _klass = NULL;
     _failed_verification = false;
+    _is_archived_lambda_proxy = false;
     _id = -1;
     _clsfile_size = -1;
     _clsfile_crc32 = -1;
@@ -242,6 +245,159 @@
   }
 };
 
+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 @@
   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 @@
   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 @@
     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 @@
     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 @@
       }
     }
     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 @@
 
 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 @@
   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 @@
     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 @@
     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 @@
   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 @@
 
   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 @@
 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 @@
       } 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 @@
   }
 };
 
+void SystemDictionaryShared::write_lambda_proxy_class_dictionary(LambdaProxyClassDictionary *dictionary) {
+  CompactHashtableStats stats;
+  dictionary->reset();
+  CompactHashtableWriter writer(_dumptime_lambda_proxy_class_dictionary->_count, &stats);
+  CopyLambdaProxyClassInfoToArchive copy(&writer);
+  _dumptime_lambda_proxy_class_dictionary->iterate(&copy);
+  writer.dump(dictionary, "lambda proxy class dictionary");
+}
+
 void SystemDictionaryShared::write_dictionary(RunTimeSharedDictionary* dictionary,
                                               bool is_builtin,
                                               bool is_static_archive) {
@@ -1659,6 +2067,16 @@
     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 @@
   } else {
     _dynamic_builtin_dictionary.serialize_header(soc);
     _dynamic_unregistered_dictionary.serialize_header(soc);
+    _lambda_proxy_class_dictionary.serialize_header(soc);
   }
 }
 
@@ -1703,6 +2122,7 @@
 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 @@
   }
 };
 
+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 @@
     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 @@
     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");
     }
   }
 }
--- a/src/hotspot/share/classfile/systemDictionaryShared.hpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/classfile/systemDictionaryShared.hpp	Wed Jun 10 15:50:26 2020 +0000
@@ -105,6 +105,7 @@
 class ClassFileStream;
 class DumpTimeSharedClassInfo;
 class DumpTimeSharedClassTable;
+class LambdaProxyClassDictionary;
 class RunTimeSharedClassInfo;
 class RunTimeSharedDictionary;
 
@@ -178,7 +179,6 @@
                                              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 @@
   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 @@
                                              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 @@
   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);
--- a/src/hotspot/share/include/jvm.h	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/include/jvm.h	Wed Jun 10 15:50:26 2020 +0000
@@ -176,6 +176,30 @@
 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();
 
--- a/src/hotspot/share/memory/dynamicArchive.cpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/memory/dynamicArchive.cpp	Wed Jun 10 15:50:26 2020 +0000
@@ -660,6 +660,11 @@
     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;
       PointerMarker marker(this);
@@ -838,16 +843,7 @@
 
   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();
--- a/src/hotspot/share/oops/constantPool.cpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/oops/constantPool.cpp	Wed Jun 10 15:50:26 2020 +0000
@@ -414,13 +414,21 @@
       // 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) {
--- a/src/hotspot/share/oops/instanceKlass.cpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/oops/instanceKlass.cpp	Wed Jun 10 15:50:26 2020 +0000
@@ -2602,6 +2602,19 @@
   }
 }
 
+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();
--- a/src/hotspot/share/oops/instanceKlass.hpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/oops/instanceKlass.hpp	Wed Jun 10 15:50:26 2020 +0000
@@ -368,6 +368,8 @@
 
   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;
   }
--- a/src/hotspot/share/oops/klass.hpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/oops/klass.hpp	Wed Jun 10 15:50:26 2020 +0000
@@ -176,7 +176,8 @@
   // 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 @@
 
   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 @@
     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;
--- a/src/hotspot/share/prims/jvm.cpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/prims/jvm.cpp	Wed Jun 10 15:50:26 2020 +0000
@@ -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 @@
   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) {
--- a/src/hotspot/share/runtime/mutexLocker.cpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/runtime/mutexLocker.cpp	Wed Jun 10 15:50:26 2020 +0000
@@ -150,6 +150,7 @@
 Mutex*   CDSClassFileStream_lock      = NULL;
 #endif
 Mutex*   DumpTimeTable_lock           = NULL;
+Mutex*   CDSLambda_lock               = NULL;
 #endif // INCLUDE_CDS
 
 #if INCLUDE_JVMCI
@@ -344,6 +345,7 @@
   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
--- a/src/hotspot/share/runtime/mutexLocker.hpp	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/hotspot/share/runtime/mutexLocker.hpp	Wed Jun 10 15:50:26 2020 +0000
@@ -129,6 +129,7 @@
 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
--- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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
@@ -245,6 +245,47 @@
     }
 
     /**
+     * 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 @@
      * @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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/classes/java/lang/invoke/LambdaProxyClassArchive.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+    }
+}
--- a/src/java.base/share/classes/jdk/internal/misc/VM.java	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/java.base/share/classes/jdk/internal/misc/VM.java	Wed Jun 10 15:50:26 2020 +0000
@@ -471,6 +471,16 @@
     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.
      */
     public interface BufferPool {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/java.base/share/native/libjava/LambdaProxyClassArchive.c	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+}
--- a/src/java.base/share/native/libjava/VM.c	Wed Jun 10 11:12:33 2020 -0400
+++ b/src/java.base/share/native/libjava/VM.c	Wed Jun 10 15:50:26 2020 +0000
@@ -66,3 +66,13 @@
 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);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/BasicLambdaTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/CDSStreamTestDriver.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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?)");
+              }
+           }
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/DoubleSumAverageTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaCustomLoader.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaForClassInBaseArchive.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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)");
+                });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/LambdaProxyCallerIsHidden.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/NestTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/ParallelLambdaLoadTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/PredicateTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/RegularHiddenClass.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/StaticInnerTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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)");
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnsafeAndLambda.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UnsafeAnonymous.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/UsedAllArchivedLambdas.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            });
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/CDSMHTest_generate.sh	Wed Jun 10 15:50:26 2020 +0000
@@ -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"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesAsCollectorTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesCastFailureTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesGeneralTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesInvokersTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesPermuteArgumentsTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/methodHandles/MethodHandlesSpreadArgumentsTest.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/BasicLambdaApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/CustomLoaderApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/LambHello.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/LambdaProxyCallerIsHiddenApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/LambdaVerification.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/NestApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/ParallelLambdaLoad.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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) {
+            ;
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/PredicateApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/SimpleApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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());
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/StaticInnerApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/TestMHApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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]);
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/TestStreamApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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!");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/UnsafeAndLambdaApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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");
+        }
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/UnsafeAnonymousApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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();
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/hotspot/jtreg/runtime/cds/appcds/dynamicArchive/test-classes/UsedAllArchivedLambdasApp.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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);
+            }
+        }
+    }
+}
--- a/test/hotspot/jtreg/runtime/cds/appcds/javaldr/AnonVmClassesDuringDump.java	Wed Jun 10 11:12:33 2020 -0400
+++ b/test/hotspot/jtreg/runtime/cds/appcds/javaldr/AnonVmClassesDuringDump.java	Wed Jun 10 15:50:26 2020 +0000
@@ -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 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 @@
         // 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));
     }
 }
 
--- a/test/lib/jdk/test/lib/Utils.java	Wed Jun 10 11:12:33 2020 -0400
+++ b/test/lib/jdk/test/lib/Utils.java	Wed Jun 10 15:50:26 2020 +0000
@@ -26,6 +26,7 @@
 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 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 @@
             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 @@
                     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) {