diff a/src/hotspot/share/prims/methodHandles.cpp b/src/hotspot/share/prims/methodHandles.cpp
--- a/src/hotspot/share/prims/methodHandles.cpp
+++ b/src/hotspot/share/prims/methodHandles.cpp
@@ -21,14 +21,16 @@
  * questions.
  *
  */
 
 #include "precompiled.hpp"
+#include "cds/cds_globals.hpp"
 #include "classfile/javaClasses.inline.hpp"
 #include "classfile/stringTable.hpp"
 #include "classfile/symbolTable.hpp"
 #include "classfile/systemDictionary.hpp"
+#include "classfile/systemDictionaryShared.hpp"
 #include "classfile/vmClasses.hpp"
 #include "code/codeCache.hpp"
 #include "code/dependencyContext.hpp"
 #include "compiler/compileBroker.hpp"
 #include "interpreter/interpreter.hpp"
@@ -49,18 +51,21 @@
 #include "prims/methodHandles.hpp"
 #include "runtime/deoptimization.hpp"
 #include "runtime/fieldDescriptor.inline.hpp"
 #include "runtime/handles.inline.hpp"
 #include "runtime/interfaceSupport.inline.hpp"
+#include "runtime/java.hpp"
 #include "runtime/javaCalls.hpp"
 #include "runtime/jniHandles.inline.hpp"
+#include "runtime/perfData.inline.hpp"
 #include "runtime/timerTrace.hpp"
 #include "runtime/reflection.hpp"
 #include "runtime/safepointVerifiers.hpp"
 #include "runtime/signature.hpp"
 #include "runtime/stubRoutines.hpp"
 #include "sanitizers/leak.hpp"
+#include "services/management.hpp"
 #include "utilities/exceptions.hpp"
 
 
 /*
  * JSR 292 reference implementation: method handles
@@ -1044,11 +1049,11 @@
 #undef VALUE_COMMA
 #undef STRING_NULL
 #undef EACH_NAMED_CON
 #endif // PRODUCT
 
-JVM_ENTRY(jint, MHN_getNamedCon(JNIEnv *env, jobject igcls, jint which, jobjectArray box_jh)) {
+JVM_ENTRY_PROF(jint, MHN_getNamedCon, MHN_getNamedCon(JNIEnv *env, jobject igcls, jint which, jobjectArray box_jh)) {
 #ifndef PRODUCT
   if (advertise_con_value(which)) {
     assert(which >= 0 && which < con_value_count, "");
     int con = con_values[which];
     objArrayHandle box(THREAD, (objArrayOop) JNIHandles::resolve(box_jh));
@@ -1065,29 +1070,29 @@
   return 0;
 }
 JVM_END
 
 // void init(MemberName self, AccessibleObject ref)
-JVM_ENTRY(void, MHN_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) {
+JVM_ENTRY_PROF(void, MHN_init_Mem, MHN_init_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jobject target_jh)) {
   if (mname_jh == nullptr) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
   if (target_jh == nullptr) { THROW_MSG(vmSymbols::java_lang_InternalError(), "target is null"); }
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
   Handle target(THREAD, JNIHandles::resolve_non_null(target_jh));
   MethodHandles::init_MemberName(mname, target, CHECK);
 }
 JVM_END
 
 // void expand(MemberName self)
-JVM_ENTRY(void, MHN_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) {
+JVM_ENTRY_PROF(void, MHN_expand_Mem, MHN_expand_Mem(JNIEnv *env, jobject igcls, jobject mname_jh)) {
   if (mname_jh == nullptr) { THROW_MSG(vmSymbols::java_lang_InternalError(), "mname is null"); }
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
   MethodHandles::expand_MemberName(mname, 0, CHECK);
 }
 JVM_END
 
 // void resolve(MemberName self, Class<?> caller)
-JVM_ENTRY(jobject, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh,
+JVM_ENTRY_PROF(jobject, MHN_resolve_Mem, MHN_resolve_Mem(JNIEnv *env, jobject igcls, jobject mname_jh, jclass caller_jh,
     jint lookup_mode, jboolean speculative_resolve)) {
   if (mname_jh == nullptr) { THROW_MSG_NULL(vmSymbols::java_lang_InternalError(), "mname is null"); }
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
 
   // The trusted Java code that calls this method should already have performed
@@ -1169,29 +1174,29 @@
   const char* msg = (must_be_static ? "static field required" : "non-static field required");
   THROW_MSG_0(vmSymbols::java_lang_InternalError(), msg);
   return 0;
 }
 
-JVM_ENTRY(jlong, MHN_objectFieldOffset(JNIEnv *env, jobject igcls, jobject mname_jh)) {
+JVM_ENTRY_PROF(jlong, MHN_objectFieldOffset, MHN_objectFieldOffset(JNIEnv *env, jobject igcls, jobject mname_jh)) {
   return find_member_field_offset(JNIHandles::resolve(mname_jh), false, THREAD);
 }
 JVM_END
 
-JVM_ENTRY(jlong, MHN_staticFieldOffset(JNIEnv *env, jobject igcls, jobject mname_jh)) {
+JVM_ENTRY_PROF(jlong, MHN_staticFieldOffset, MHN_staticFieldOffset(JNIEnv *env, jobject igcls, jobject mname_jh)) {
   return find_member_field_offset(JNIHandles::resolve(mname_jh), true, THREAD);
 }
 JVM_END
 
-JVM_ENTRY(jobject, MHN_staticFieldBase(JNIEnv *env, jobject igcls, jobject mname_jh)) {
+JVM_ENTRY_PROF(jobject, MHN_staticFieldBase, MHN_staticFieldBase(JNIEnv *env, jobject igcls, jobject mname_jh)) {
   // use the other function to perform sanity checks:
   jlong ignore = find_member_field_offset(JNIHandles::resolve(mname_jh), true, CHECK_NULL);
   oop clazz = java_lang_invoke_MemberName::clazz(JNIHandles::resolve_non_null(mname_jh));
   return JNIHandles::make_local(THREAD, clazz);
 }
 JVM_END
 
-JVM_ENTRY(jobject, MHN_getMemberVMInfo(JNIEnv *env, jobject igcls, jobject mname_jh)) {
+JVM_ENTRY_PROF(jobject, MHN_getMemberVMInfo, MHN_getMemberVMInfo(JNIEnv *env, jobject igcls, jobject mname_jh)) {
   if (mname_jh == nullptr)  return nullptr;
   Handle mname(THREAD, JNIHandles::resolve_non_null(mname_jh));
   intptr_t vmindex  = java_lang_invoke_MemberName::vmindex(mname());
   objArrayHandle result = oopFactory::new_objArray_handle(vmClasses::Object_klass(), 2, CHECK_NULL);
   jvalue vmindex_value; vmindex_value.j = (long)vmindex;
@@ -1209,11 +1214,11 @@
   result->obj_at_put(1, x);
   return JNIHandles::make_local(THREAD, result());
 }
 JVM_END
 
-JVM_ENTRY(void, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) {
+JVM_ENTRY_PROF(void, MHN_setCallSiteTargetNormal, MHN_setCallSiteTargetNormal(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) {
   Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
   Handle target   (THREAD, JNIHandles::resolve_non_null(target_jh));
   DeoptimizationScope deopt_scope;
   {
     // Walk all nmethods depending on this call site.
@@ -1225,11 +1230,43 @@
     deopt_scope.deoptimize_marked();
   }
 }
 JVM_END
 
-JVM_ENTRY(void, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) {
+// Make sure the class is linked. If the class cannot be verified, etc, an exception will be thrown.
+JVM_ENTRY_PROF(void, MHN_checkArchivable, MHN_checkArchivable(JNIEnv *env, jobject igcls, jclass klass_jh)) {
+  if (klass_jh == nullptr) { THROW_MSG(vmSymbols::java_lang_InternalError(), "klass is null"); }
+
+  if (ArchiveInvokeDynamic) {
+    Klass* klass = java_lang_Class::as_Klass(JNIHandles::resolve_non_null(klass_jh));
+    if (klass != nullptr && klass->is_instance_klass()) {
+      // klass could be null during very early VM start-up
+      InstanceKlass* ik = InstanceKlass::cast(klass);
+      ik->link_class(THREAD); // exception will be thrown if unverifiable
+      if (!ik->is_linked()) {
+        assert(HAS_PENDING_EXCEPTION, "must be");
+        ResourceMark rm;
+        log_warning(cds)("Cannot use unverifiable class %s in MethodType",
+                         klass->external_name());
+        return;
+      }
+
+      if (SystemDictionaryShared::is_jfr_event_class(ik)) {
+        ResourceMark rm;
+        log_warning(cds)("Cannot use JFR event class %s in MethodType",
+                         klass->external_name());
+        Exceptions::fthrow(THREAD_AND_LOCATION,
+                           vmSymbols::java_lang_NoClassDefFoundError(),
+                           "Class %s, or one of its supertypes, is a JFR event class",
+                           klass->external_name());
+      }
+    }
+  }
+}
+JVM_END
+
+JVM_ENTRY_PROF(void, MHN_setCallSiteTargetVolatile, MHN_setCallSiteTargetVolatile(JNIEnv* env, jobject igcls, jobject call_site_jh, jobject target_jh)) {
   Handle call_site(THREAD, JNIHandles::resolve_non_null(call_site_jh));
   Handle target   (THREAD, JNIHandles::resolve_non_null(target_jh));
   DeoptimizationScope deopt_scope;
   {
     // Walk all nmethods depending on this call site.
@@ -1241,11 +1278,11 @@
     deopt_scope.deoptimize_marked();
   }
 }
 JVM_END
 
-JVM_ENTRY(void, MHN_copyOutBootstrapArguments(JNIEnv* env, jobject igcls,
+JVM_ENTRY_PROF(void, MHN_copyOutBootstrapArguments, MHN_copyOutBootstrapArguments(JNIEnv* env, jobject igcls,
                                               jobject caller_jh, jintArray index_info_jh,
                                               jint start, jint end,
                                               jobjectArray buf_jh, jint pos,
                                               jboolean resolve, jobject ifna_jh)) {
   Klass* caller_k = java_lang_Class::as_Klass(JNIHandles::resolve(caller_jh));
@@ -1324,11 +1361,11 @@
 }
 JVM_END
 
 // It is called by a Cleaner object which ensures that dropped CallSites properly
 // deallocate their dependency information.
-JVM_ENTRY(void, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) {
+JVM_ENTRY_PROF(void, MHN_clearCallSiteContext, MHN_clearCallSiteContext(JNIEnv* env, jobject igcls, jobject context_jh)) {
   Handle context(THREAD, JNIHandles::resolve_non_null(context_jh));
   DeoptimizationScope deopt_scope;
   {
     NoSafepointVerifier nsv;
     MutexLocker ml(THREAD, CodeCache_lock, Mutex::_no_safepoint_check_flag);
@@ -1344,22 +1381,22 @@
 /**
  * Throws a java/lang/UnsupportedOperationException unconditionally.
  * This is required by the specification of MethodHandle.invoke if
  * invoked directly.
  */
-JVM_ENTRY(jobject, MH_invoke_UOE(JNIEnv* env, jobject mh, jobjectArray args)) {
+JVM_ENTRY_PROF(jobject, MH_invoke_UOE, MH_invoke_UOE(JNIEnv* env, jobject mh, jobjectArray args)) {
   THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "MethodHandle.invoke cannot be invoked reflectively");
   return nullptr;
 }
 JVM_END
 
 /**
  * Throws a java/lang/UnsupportedOperationException unconditionally.
  * This is required by the specification of MethodHandle.invokeExact if
  * invoked directly.
  */
-JVM_ENTRY(jobject, MH_invokeExact_UOE(JNIEnv* env, jobject mh, jobjectArray args)) {
+JVM_ENTRY_PROF(jobject, MH_invokeExact_UOE, MH_invokeExact_UOE(JNIEnv* env, jobject mh, jobjectArray args)) {
   THROW_MSG_NULL(vmSymbols::java_lang_UnsupportedOperationException(), "MethodHandle.invokeExact cannot be invoked reflectively");
   return nullptr;
 }
 JVM_END
 
@@ -1383,10 +1420,11 @@
 // These are the native methods on java.lang.invoke.MethodHandleNatives.
 static JNINativeMethod MHN_methods[] = {
   {CC "init",                      CC "(" MEM "" OBJ ")V",                   FN_PTR(MHN_init_Mem)},
   {CC "expand",                    CC "(" MEM ")V",                          FN_PTR(MHN_expand_Mem)},
   {CC "resolve",                   CC "(" MEM "" CLS "IZ)" MEM,              FN_PTR(MHN_resolve_Mem)},
+  {CC "checkArchivable",           CC "(" CLS ")V",                          FN_PTR(MHN_checkArchivable)},
   //  static native int getNamedCon(int which, Object[] name)
   {CC "getNamedCon",               CC "(I[" OBJ ")I",                        FN_PTR(MHN_getNamedCon)},
   {CC "objectFieldOffset",         CC "(" MEM ")J",                          FN_PTR(MHN_objectFieldOffset)},
   {CC "setCallSiteTargetNormal",   CC "(" CS "" MH ")V",                     FN_PTR(MHN_setCallSiteTargetNormal)},
   {CC "setCallSiteTargetVolatile", CC "(" CS "" MH ")V",                     FN_PTR(MHN_setCallSiteTargetVolatile)},
@@ -1404,11 +1442,11 @@
 };
 
 /**
  * This one function is exported, used by NativeLookup.
  */
-JVM_ENTRY(void, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
+JVM_ENTRY_PROF(void, JVM_RegisterMethodHandleMethods, JVM_RegisterMethodHandleMethods(JNIEnv *env, jclass MHN_class)) {
   assert(!MethodHandles::enabled(), "must not be enabled");
   assert(vmClasses::MethodHandle_klass() != nullptr, "should be present");
 
   oop mirror = vmClasses::MethodHandle_klass()->java_mirror();
   jclass MH_class = (jclass) JNIHandles::make_local(THREAD, mirror);
@@ -1428,5 +1466,60 @@
   log_debug(methodhandles, indy)("MethodHandle support loaded (using LambdaForms)");
 
   MethodHandles::set_enabled(true);
 }
 JVM_END
+
+#define DO_COUNTERS(macro)             \
+  macro(MHN_init_Mem)                  \
+  macro(MHN_expand_Mem)                \
+  macro(MHN_resolve_Mem)               \
+  macro(MHN_checkArchivable)           \
+  macro(MHN_getNamedCon)               \
+  macro(MHN_objectFieldOffset)         \
+  macro(MHN_setCallSiteTargetNormal)   \
+  macro(MHN_setCallSiteTargetVolatile) \
+  macro(MHN_copyOutBootstrapArguments) \
+  macro(MHN_clearCallSiteContext)      \
+  macro(MHN_staticFieldOffset)         \
+  macro(MHN_staticFieldBase)           \
+  macro(MHN_getMemberVMInfo)           \
+  macro(MH_invoke_UOE)                 \
+  macro(MH_invokeExact_UOE)            \
+  macro(JVM_RegisterMethodHandleMethods)
+
+#define INIT_COUNTER(name) \
+    NEWPERFTICKCOUNTERS(_perf_##name##_timer, SUN_RT, #name); \
+    NEWPERFEVENTCOUNTER(_perf_##name##_count, SUN_RT, #name "_count"); \
+
+void MethodHandles::init_counters() {
+  if (UsePerfData) {
+    EXCEPTION_MARK;
+
+    DO_COUNTERS(INIT_COUNTER)
+
+    if (HAS_PENDING_EXCEPTION) {
+      vm_exit_during_initialization("perf_mhn_init failed unexpectedly");
+    }
+  }
+}
+
+#undef INIT_COUNTER
+
+#define PRINT_COUNTER(name) {\
+  jlong count = _perf_##name##_count->get_value(); \
+  if (count > 0) { \
+    st->print_cr("  %-40s = %4ldms (elapsed) %4ldms (thread) (%5ld events)", #name, \
+                 _perf_##name##_timer->elapsed_counter_value_ms(), \
+                 _perf_##name##_timer->thread_counter_value_ms(), \
+                 count); \
+  }}
+
+void MethodHandles::print_counters_on(outputStream* st) {
+  if (ProfileVMCalls && UsePerfData) {
+    DO_COUNTERS(PRINT_COUNTER)
+  } else {
+    st->print_cr("  MHN:  no info (%s is disabled)", (UsePerfData ? "ProfileVMCalls" : "UsePerfData"));
+  }
+}
+
+#undef PRINT_COUNTER
