diff --git a/src/hotspot/share/cds/dynamicArchive.cpp b/src/hotspot/share/cds/dynamicArchive.cpp index 5effa4e458c..04c60b89580 100644 --- a/src/hotspot/share/cds/dynamicArchive.cpp +++ b/src/hotspot/share/cds/dynamicArchive.cpp @@ -31,6 +31,7 @@ #include "cds/classPrelinker.hpp" #include "cds/dynamicArchive.hpp" #include "cds/regeneratedClasses.hpp" +#include "classfile/classLoader.hpp" #include "classfile/classLoaderData.inline.hpp" #include "classfile/symbolTable.hpp" #include "classfile/systemDictionaryShared.hpp" @@ -118,6 +119,9 @@ public: return; } + log_info(cds,dynamic)("CDS dynamic dump: clinit = " JLONG_FORMAT "ms)", + ClassLoader::class_init_time_ms()); + init_header(); gather_source_objs(); gather_array_klasses(); diff --git a/src/hotspot/share/classfile/classLoader.cpp b/src/hotspot/share/classfile/classLoader.cpp index b317aaa071c..910cbe48c5c 100644 --- a/src/hotspot/share/classfile/classLoader.cpp +++ b/src/hotspot/share/classfile/classLoader.cpp @@ -78,6 +78,7 @@ #include "utilities/classpathStream.hpp" #include "utilities/events.hpp" #include "utilities/macros.hpp" +#include "utilities/ostream.hpp" #include "utilities/utf8.hpp" // Entry point in java.dll for path canonicalization @@ -118,9 +119,40 @@ PerfCounter* ClassLoader::_perf_define_appclass_time = nullptr; PerfCounter* ClassLoader::_perf_define_appclass_selftime = nullptr; PerfCounter* ClassLoader::_perf_app_classfile_bytes_read = nullptr; PerfCounter* ClassLoader::_perf_sys_classfile_bytes_read = nullptr; +PerfCounter* ClassLoader::_perf_ik_link_methods_time = nullptr; +PerfCounter* ClassLoader::_perf_method_adapters_time = nullptr; +PerfCounter* ClassLoader::_perf_ik_link_methods_count = nullptr; +PerfCounter* ClassLoader::_perf_method_adapters_count = nullptr; PerfCounter* ClassLoader::_unsafe_defineClassCallCounter = nullptr; PerfCounter* ClassLoader::_perf_secondary_hash_time = nullptr; +PerfCounter* ClassLoader::_perf_resolve_indy_time = nullptr; +PerfCounter* ClassLoader::_perf_resolve_invokehandle_time = nullptr; +PerfCounter* ClassLoader::_perf_resolve_mh_time = nullptr; +PerfCounter* ClassLoader::_perf_resolve_mt_time = nullptr; + +PerfCounter* ClassLoader::_perf_resolve_indy_count = nullptr; +PerfCounter* ClassLoader::_perf_resolve_invokehandle_count = nullptr; +PerfCounter* ClassLoader::_perf_resolve_mh_count = nullptr; +PerfCounter* ClassLoader::_perf_resolve_mt_count = nullptr; + +void ClassLoader::print_counters(outputStream *st) { + // The counters are only active if the logging is enabled, but + // we print to the passed in outputStream as requested. + if (log_is_enabled(Info, perf, class, link)) { + st->print_cr("ClassLoader:"); + st->print_cr(" clinit: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", ClassLoader::class_init_time_ms(), ClassLoader::class_init_count()); + st->print_cr(" link methods: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_ik_link_methods_time->get_value()) , _perf_ik_link_methods_count->get_value()); + st->print_cr(" method adapters: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_method_adapters_time->get_value()) , _perf_method_adapters_count->get_value()); + st->print_cr(" resolve..."); + st->print_cr(" invokedynamic: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_indy_time->get_value()) , _perf_resolve_indy_count->get_value()); + st->print_cr(" invokehandle: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_invokehandle_time->get_value()) , _perf_resolve_invokehandle_count->get_value()); + st->print_cr(" CP_MethodHandle: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_mh_time->get_value()) , _perf_resolve_mh_count->get_value()); + st->print_cr(" CP_MethodType: " JLONG_FORMAT "ms / " JLONG_FORMAT " events", Management::ticks_to_ms(_perf_resolve_mt_time->get_value()) , _perf_resolve_mt_count->get_value()); + st->cr(); + } +} + GrowableArray* ClassLoader::_patch_mod_entries = nullptr; GrowableArray* ClassLoader::_exploded_entries = nullptr; ClassPathEntry* ClassLoader::_jrt_entry = nullptr; @@ -1336,9 +1368,25 @@ void ClassLoader::initialize(TRAPS) { NEWPERFTICKCOUNTER(_perf_define_appclass_selftime, SUN_CLS, "defineAppClassTime.self"); NEWPERFBYTECOUNTER(_perf_app_classfile_bytes_read, SUN_CLS, "appClassBytes"); NEWPERFBYTECOUNTER(_perf_sys_classfile_bytes_read, SUN_CLS, "sysClassBytes"); - NEWPERFEVENTCOUNTER(_unsafe_defineClassCallCounter, SUN_CLS, "unsafeDefineClassCalls"); NEWPERFTICKCOUNTER(_perf_secondary_hash_time, SUN_CLS, "secondarySuperHashTime"); + + if (log_is_enabled(Info, perf, class, link)) { + NEWPERFTICKCOUNTER(_perf_ik_link_methods_time, SUN_CLS, "linkMethodsTime"); + NEWPERFTICKCOUNTER(_perf_method_adapters_time, SUN_CLS, "makeAdaptersTime"); + NEWPERFEVENTCOUNTER(_perf_ik_link_methods_count, SUN_CLS, "linkMethodsCount"); + NEWPERFEVENTCOUNTER(_perf_method_adapters_count, SUN_CLS, "makeAdaptersCount"); + + NEWPERFTICKCOUNTER(_perf_resolve_indy_time, SUN_CLS, "resolve_invokedynamic_time"); + NEWPERFTICKCOUNTER(_perf_resolve_invokehandle_time, SUN_CLS, "resolve_invokehandle_time"); + NEWPERFTICKCOUNTER(_perf_resolve_mh_time, SUN_CLS, "resolve_MethodHandle_time"); + NEWPERFTICKCOUNTER(_perf_resolve_mt_time, SUN_CLS, "resolve_MethodType_time"); + + NEWPERFEVENTCOUNTER(_perf_resolve_indy_count, SUN_CLS, "resolve_invokedynamic_count"); + NEWPERFEVENTCOUNTER(_perf_resolve_invokehandle_count, SUN_CLS, "resolve_invokehandle_count"); + NEWPERFEVENTCOUNTER(_perf_resolve_mh_count, SUN_CLS, "resolve_MethodHandle_count"); + NEWPERFEVENTCOUNTER(_perf_resolve_mt_count, SUN_CLS, "resolve_MethodType_count"); + } } // lookup java library entry points diff --git a/src/hotspot/share/classfile/classLoader.hpp b/src/hotspot/share/classfile/classLoader.hpp index d3ca476ac95..af625082dda 100644 --- a/src/hotspot/share/classfile/classLoader.hpp +++ b/src/hotspot/share/classfile/classLoader.hpp @@ -30,6 +30,7 @@ #include "runtime/perfDataTypes.hpp" #include "utilities/exceptions.hpp" #include "utilities/macros.hpp" +#include "utilities/ostream.hpp" #include "utilities/zipLibrary.hpp" // The VM class loader. @@ -166,6 +167,20 @@ class ClassLoader: AllStatic { static PerfCounter* _perf_define_appclass_selftime; static PerfCounter* _perf_app_classfile_bytes_read; static PerfCounter* _perf_sys_classfile_bytes_read; + static PerfCounter* _perf_ik_link_methods_time; + static PerfCounter* _perf_method_adapters_time; + static PerfCounter* _perf_ik_link_methods_count; + static PerfCounter* _perf_method_adapters_count; + + static PerfCounter* _perf_resolve_indy_time; + static PerfCounter* _perf_resolve_invokehandle_time; + static PerfCounter* _perf_resolve_mh_time; + static PerfCounter* _perf_resolve_mt_time; + + static PerfCounter* _perf_resolve_indy_count; + static PerfCounter* _perf_resolve_invokehandle_count; + static PerfCounter* _perf_resolve_mh_count; + static PerfCounter* _perf_resolve_mt_count; static PerfCounter* _unsafe_defineClassCallCounter; @@ -285,6 +300,23 @@ class ClassLoader: AllStatic { static PerfCounter* perf_app_classfile_bytes_read() { return _perf_app_classfile_bytes_read; } static PerfCounter* perf_sys_classfile_bytes_read() { return _perf_sys_classfile_bytes_read; } + static PerfCounter* perf_ik_link_methods_time() { return _perf_ik_link_methods_time; } + static PerfCounter* perf_method_adapters_time() { return _perf_method_adapters_time; } + static PerfCounter* perf_ik_link_methods_count() { return _perf_ik_link_methods_count; } + static PerfCounter* perf_method_adapters_count() { return _perf_method_adapters_count; } + + static PerfCounter* perf_resolve_invokedynamic_time() { return _perf_resolve_indy_time; } + static PerfCounter* perf_resolve_invokehandle_time() { return _perf_resolve_invokehandle_time; } + static PerfCounter* perf_resolve_method_handle_time() { return _perf_resolve_mh_time; } + static PerfCounter* perf_resolve_method_type_time() { return _perf_resolve_mt_time; } + + static PerfCounter* perf_resolve_invokedynamic_count() { return _perf_resolve_indy_count; } + static PerfCounter* perf_resolve_invokehandle_count() { return _perf_resolve_invokehandle_count; } + static PerfCounter* perf_resolve_method_handle_count() { return _perf_resolve_mh_count; } + static PerfCounter* perf_resolve_method_type_count() { return _perf_resolve_mt_count; } + + static void print_counters(outputStream *st); + // Record how many calls to Unsafe_DefineClass static PerfCounter* unsafe_defineClassCallCounter() { return _unsafe_defineClassCallCounter; diff --git a/src/hotspot/share/interpreter/linkResolver.cpp b/src/hotspot/share/interpreter/linkResolver.cpp index 9b80550130f..9247b8a1740 100644 --- a/src/hotspot/share/interpreter/linkResolver.cpp +++ b/src/hotspot/share/interpreter/linkResolver.cpp @@ -24,6 +24,7 @@ #include "precompiled.hpp" #include "cds/archiveUtils.hpp" +#include "classfile/classLoader.hpp" #include "classfile/defaultMethods.hpp" #include "classfile/javaClasses.hpp" #include "classfile/systemDictionary.hpp" @@ -55,7 +56,8 @@ #include "runtime/fieldDescriptor.inline.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" -#include "runtime/javaThread.hpp" +#include "runtime/javaThread.inline.hpp" +#include "runtime/perfData.hpp" #include "runtime/reflection.hpp" #include "runtime/safepointVerifiers.hpp" #include "runtime/sharedRuntime.hpp" @@ -1728,6 +1730,10 @@ bool LinkResolver::resolve_previously_linked_invokehandle(CallInfo& result, cons } void LinkResolver::resolve_invokehandle(CallInfo& result, const constantPoolHandle& pool, int index, TRAPS) { + + PerfTraceTimedEvent timer(ClassLoader::perf_resolve_invokehandle_time(), + ClassLoader::perf_resolve_invokehandle_count()); + LinkInfo link_info(pool, index, Bytecodes::_invokehandle, CHECK); if (log_is_enabled(Info, methodhandles)) { ResourceMark rm(THREAD); @@ -1779,6 +1785,9 @@ void LinkResolver::resolve_handle_call(CallInfo& result, } void LinkResolver::resolve_invokedynamic(CallInfo& result, const constantPoolHandle& pool, int indy_index, TRAPS) { + PerfTraceTimedEvent timer(ClassLoader::perf_resolve_invokedynamic_time(), + ClassLoader::perf_resolve_invokedynamic_count()); + int pool_index = pool->resolved_indy_entry_at(indy_index)->constant_pool_index(); // Resolve the bootstrap specifier (BSM + optional arguments). diff --git a/src/hotspot/share/logging/logTag.hpp b/src/hotspot/share/logging/logTag.hpp index bf60af68770..b64097311a4 100644 --- a/src/hotspot/share/logging/logTag.hpp +++ b/src/hotspot/share/logging/logTag.hpp @@ -110,6 +110,7 @@ class outputStream; LOG_TAG(jvmti) \ LOG_TAG(lambda) \ LOG_TAG(library) \ + LOG_TAG(link) \ LOG_TAG(liveness) \ LOG_TAG(load) /* Trace all classes loaded */ \ LOG_TAG(loader) \ diff --git a/src/hotspot/share/oops/constantPool.cpp b/src/hotspot/share/oops/constantPool.cpp index 85cc5a77f1e..329b8157cb7 100644 --- a/src/hotspot/share/oops/constantPool.cpp +++ b/src/hotspot/share/oops/constantPool.cpp @@ -29,6 +29,7 @@ #include "cds/cdsConfig.hpp" #include "cds/classPrelinker.hpp" #include "cds/heapShared.hpp" +#include "classfile/classLoader.hpp" #include "classfile/classLoaderData.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/metadataOnStackMark.hpp" @@ -62,7 +63,8 @@ #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/javaCalls.hpp" -#include "runtime/javaThread.hpp" +#include "runtime/javaThread.inline.hpp" +#include "runtime/perfData.hpp" #include "runtime/signature.hpp" #include "runtime/vframe.inline.hpp" #include "utilities/checkedCast.hpp" @@ -1014,7 +1016,9 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, } case JVM_CONSTANT_Dynamic: - { + { PerfTraceTimedEvent timer(ClassLoader::perf_resolve_invokedynamic_time(), + ClassLoader::perf_resolve_invokedynamic_count()); + // Resolve the Dynamically-Computed constant to invoke the BSM in order to obtain the resulting oop. BootstrapInfo bootstrap_specifier(this_cp, cp_index); @@ -1072,7 +1076,9 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, break; case JVM_CONSTANT_MethodHandle: - { + { PerfTraceTimedEvent timer(ClassLoader::perf_resolve_method_handle_time(), + ClassLoader::perf_resolve_method_handle_count()); + int ref_kind = this_cp->method_handle_ref_kind_at(cp_index); int callee_index = this_cp->method_handle_klass_index_at(cp_index); Symbol* name = this_cp->method_handle_name_ref_at(cp_index); @@ -1120,7 +1126,9 @@ oop ConstantPool::resolve_constant_at_impl(const constantPoolHandle& this_cp, } case JVM_CONSTANT_MethodType: - { + { PerfTraceTimedEvent timer(ClassLoader::perf_resolve_method_type_time(), + ClassLoader::perf_resolve_method_type_count()); + Symbol* signature = this_cp->method_type_signature_at(cp_index); { ResourceMark rm(THREAD); log_debug(class, resolve)("resolve JVM_CONSTANT_MethodType [%d/%d] %s", diff --git a/src/hotspot/share/oops/instanceKlass.cpp b/src/hotspot/share/oops/instanceKlass.cpp index d66ce5ce247..83dde12af3d 100644 --- a/src/hotspot/share/oops/instanceKlass.cpp +++ b/src/hotspot/share/oops/instanceKlass.cpp @@ -978,6 +978,8 @@ void InstanceKlass::rewrite_class(TRAPS) { // This is outside is_rewritten flag. In case of an exception, it can be // executed more than once. void InstanceKlass::link_methods(TRAPS) { + PerfTraceTime timer(ClassLoader::perf_ik_link_methods_time()); + int len = methods()->length(); for (int i = len-1; i >= 0; i--) { methodHandle m(THREAD, methods()->at(i)); diff --git a/src/hotspot/share/oops/method.cpp b/src/hotspot/share/oops/method.cpp index a5b2267cf33..525ec284c08 100644 --- a/src/hotspot/share/oops/method.cpp +++ b/src/hotspot/share/oops/method.cpp @@ -26,6 +26,7 @@ #include "cds/cdsConfig.hpp" #include "cds/cppVtables.hpp" #include "cds/metaspaceShared.hpp" +#include "classfile/classLoader.hpp" #include "classfile/classLoaderDataGraph.hpp" #include "classfile/metadataOnStackMark.hpp" #include "classfile/symbolTable.hpp" @@ -62,12 +63,14 @@ #include "prims/jvmtiExport.hpp" #include "prims/methodHandles.hpp" #include "runtime/atomic.hpp" +#include "runtime/arguments.hpp" #include "runtime/continuationEntry.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" #include "runtime/init.hpp" #include "runtime/java.hpp" #include "runtime/orderAccess.hpp" +#include "runtime/perfData.hpp" #include "runtime/relocator.hpp" #include "runtime/safepointVerifiers.hpp" #include "runtime/sharedRuntime.hpp" @@ -1168,6 +1171,10 @@ void Method::remove_unshareable_flags() { // Called when the method_holder is getting linked. Setup entrypoints so the method // is ready to be called from interpreter, compiler, and vtables. void Method::link_method(const methodHandle& h_method, TRAPS) { + if (log_is_enabled(Info, perf, class, link)) { + ClassLoader::perf_ik_link_methods_count()->inc(); + } + // If the code cache is full, we may reenter this function for the // leftover methods that weren't linked. if (adapter() != nullptr) { @@ -1219,6 +1226,8 @@ void Method::link_method(const methodHandle& h_method, TRAPS) { } address Method::make_adapters(const methodHandle& mh, TRAPS) { + PerfTraceTime timer(ClassLoader::perf_method_adapters_time()); + // Adapters for compiled code are made eagerly here. They are fairly // small (generally < 100 bytes) and quick to make (and cached and shared) // so making them eagerly shouldn't be too expensive. diff --git a/src/hotspot/share/runtime/arguments.cpp b/src/hotspot/share/runtime/arguments.cpp index 6680851405f..10a4c06d53c 100644 --- a/src/hotspot/share/runtime/arguments.cpp +++ b/src/hotspot/share/runtime/arguments.cpp @@ -3729,6 +3729,13 @@ jint Arguments::apply_ergo() { } #endif // COMPILER2_OR_JVMCI + if (log_is_enabled(Info, perf, class, link)) { + if (!UsePerfData) { + warning("Disabling -Xlog:perf+class+link since UsePerfData is turned off."); + LogConfiguration::configure_stdout(LogLevel::Off, false, LOG_TAGS(perf, class, link)); + } + } + if (FLAG_IS_CMDLINE(DiagnoseSyncOnValueBasedClasses)) { if (DiagnoseSyncOnValueBasedClasses == ObjectSynchronizer::LOG_WARNING && !log_is_enabled(Info, valuebasedclasses)) { LogConfiguration::configure_stdout(LogLevel::Info, true, LOG_TAGS(valuebasedclasses)); diff --git a/src/hotspot/share/runtime/java.cpp b/src/hotspot/share/runtime/java.cpp index 5271bdcda0b..f4d9152c8a5 100644 --- a/src/hotspot/share/runtime/java.cpp +++ b/src/hotspot/share/runtime/java.cpp @@ -25,6 +25,7 @@ #include "precompiled.hpp" #include "cds/cds_globals.hpp" #include "cds/dynamicArchive.hpp" +#include "classfile/classLoader.hpp" #include "classfile/classLoaderDataGraph.hpp" #include "classfile/javaClasses.hpp" #include "classfile/stringTable.hpp" @@ -156,7 +157,6 @@ static void print_method_profiling_data() { } } - #ifndef PRODUCT // Statistics printing (method invocation histogram) @@ -356,6 +356,8 @@ void print_statistics() { } ThreadsSMRSupport::log_statistics(); + + ClassLoader::print_counters(tty); } // Note: before_exit() can be executed only once, if more than one threads diff --git a/src/hotspot/share/runtime/perfData.cpp b/src/hotspot/share/runtime/perfData.cpp index b195274dc01..5e78baad3ab 100644 --- a/src/hotspot/share/runtime/perfData.cpp +++ b/src/hotspot/share/runtime/perfData.cpp @@ -296,7 +296,7 @@ void PerfDataManager::add_item(PerfData* p, bool sampled) { _has_PerfData = true; } - assert(!_all->contains(p->name()), "duplicate name added"); + assert(!_all->contains(p->name()), "duplicate name added: %s", p->name()); // add to the list of all perf data items _all->append(p); @@ -527,8 +527,3 @@ PerfDataList* PerfDataList::clone() { return copy; } -PerfTraceTime::~PerfTraceTime() { - if (!UsePerfData) return; - _t.stop(); - _timerp->inc(_t.ticks()); -} diff --git a/src/hotspot/share/runtime/perfData.hpp b/src/hotspot/share/runtime/perfData.hpp index 103e2698d9b..1f75560715a 100644 --- a/src/hotspot/share/runtime/perfData.hpp +++ b/src/hotspot/share/runtime/perfData.hpp @@ -831,11 +831,20 @@ class PerfTraceTime : public StackObj { public: inline PerfTraceTime(PerfLongCounter* timerp) : _timerp(timerp) { - if (!UsePerfData) return; + if (!UsePerfData || timerp == nullptr) { return; } _t.start(); } - ~PerfTraceTime(); + const char* name() const { + assert(_timerp != nullptr, "sanity"); + return _timerp->name(); + } + + ~PerfTraceTime() { + if (!UsePerfData || !_t.is_active()) { return; } + _t.stop(); + _timerp->inc(_t.ticks()); + } }; /* The PerfTraceTimedEvent class is responsible for counting the @@ -864,7 +873,7 @@ class PerfTraceTimedEvent : public PerfTraceTime { public: inline PerfTraceTimedEvent(PerfLongCounter* timerp, PerfLongCounter* eventp): PerfTraceTime(timerp), _eventp(eventp) { - if (!UsePerfData) return; + if (!UsePerfData || timerp == nullptr) { return; } _eventp->inc(); } diff --git a/src/hotspot/share/runtime/sharedRuntime.cpp b/src/hotspot/share/runtime/sharedRuntime.cpp index 0a7f5c54676..f794a15ac07 100644 --- a/src/hotspot/share/runtime/sharedRuntime.cpp +++ b/src/hotspot/share/runtime/sharedRuntime.cpp @@ -23,6 +23,7 @@ */ #include "precompiled.hpp" +#include "classfile/classLoader.hpp" #include "classfile/javaClasses.inline.hpp" #include "classfile/stringTable.hpp" #include "classfile/vmClasses.hpp" @@ -55,6 +56,7 @@ #include "prims/jvmtiThreadState.hpp" #include "prims/methodHandles.hpp" #include "prims/nativeLookup.hpp" +#include "runtime/arguments.hpp" #include "runtime/atomic.hpp" #include "runtime/frame.inline.hpp" #include "runtime/handles.inline.hpp" @@ -63,6 +65,7 @@ #include "runtime/java.hpp" #include "runtime/javaCalls.hpp" #include "runtime/jniHandles.inline.hpp" +#include "runtime/perfData.hpp" #include "runtime/sharedRuntime.hpp" #include "runtime/stackWatermarkSet.hpp" #include "runtime/stubRoutines.hpp" @@ -2570,6 +2573,9 @@ AdapterHandlerEntry* AdapterHandlerLibrary::create_adapter(AdapterBlob*& new_ada int total_args_passed, BasicType* sig_bt, bool allocate_code_blob) { + if (log_is_enabled(Info, perf, class, link)) { + ClassLoader::perf_method_adapters_count()->inc(); + } // StubRoutines::_final_stubs_code is initialized after this function can be called. As a result, // VerifyAdapterCalls and VerifyAdapterSharing can fail if we re-use code that generated prior diff --git a/src/hotspot/share/runtime/threads.cpp b/src/hotspot/share/runtime/threads.cpp index e7c425b2b8c..e65470ac526 100644 --- a/src/hotspot/share/runtime/threads.cpp +++ b/src/hotspot/share/runtime/threads.cpp @@ -821,6 +821,12 @@ jint Threads::create_vm(JavaVMInitArgs* args, bool* canTryAgain) { MetaspaceShared::preload_and_dump(); } + if (log_is_enabled(Info, perf, class, link)) { + LogStreamHandle(Info, perf, class, link) log; + log.print_cr("At VM initialization completion:"); + ClassLoader::print_counters(&log); + } + return JNI_OK; }