Mon, 15 Jun 2020 14:08:11 +0300
8245167: Top package in method profiling shows null in JMC
Reviewed-by: neugens
Contributed-by: asemenov@azul.com
1.1 --- a/src/share/vm/classfile/classLoader.cpp Fri Jun 12 02:59:56 2020 +0100 1.2 +++ b/src/share/vm/classfile/classLoader.cpp Mon Jun 15 14:08:11 2020 +0300 1.3 @@ -162,6 +162,64 @@ 1.4 return (strncmp(str + (str_len - str_to_find_len), str_to_find, str_to_find_len) == 0); 1.5 } 1.6 1.7 +// Used to obtain the package name from a fully qualified class name. 1.8 +// It is the responsibility of the caller to establish a ResourceMark. 1.9 +const char* ClassLoader::package_from_name(const char* const class_name, bool* bad_class_name) { 1.10 + if (class_name == NULL) { 1.11 + if (bad_class_name != NULL) { 1.12 + *bad_class_name = true; 1.13 + } 1.14 + return NULL; 1.15 + } 1.16 + 1.17 + if (bad_class_name != NULL) { 1.18 + *bad_class_name = false; 1.19 + } 1.20 + 1.21 + const char* const last_slash = strrchr(class_name, '/'); 1.22 + if (last_slash == NULL) { 1.23 + // No package name 1.24 + return NULL; 1.25 + } 1.26 + 1.27 + char* class_name_ptr = (char*) class_name; 1.28 + // Skip over '['s 1.29 + if (*class_name_ptr == '[') { 1.30 + do { 1.31 + class_name_ptr++; 1.32 + } while (*class_name_ptr == '['); 1.33 + 1.34 + // Fully qualified class names should not contain a 'L'. 1.35 + // Set bad_class_name to true to indicate that the package name 1.36 + // could not be obtained due to an error condition. 1.37 + // In this situation, is_same_class_package returns false. 1.38 + if (*class_name_ptr == 'L') { 1.39 + if (bad_class_name != NULL) { 1.40 + *bad_class_name = true; 1.41 + } 1.42 + return NULL; 1.43 + } 1.44 + } 1.45 + 1.46 + int length = last_slash - class_name_ptr; 1.47 + 1.48 + // A class name could have just the slash character in the name. 1.49 + if (length <= 0) { 1.50 + // No package name 1.51 + if (bad_class_name != NULL) { 1.52 + *bad_class_name = true; 1.53 + } 1.54 + return NULL; 1.55 + } 1.56 + 1.57 + // drop name after last slash (including slash) 1.58 + // Ex., "java/lang/String.class" => "java/lang" 1.59 + char* pkg_name = NEW_RESOURCE_ARRAY(char, length + 1); 1.60 + strncpy(pkg_name, class_name_ptr, length); 1.61 + *(pkg_name+length) = '\0'; 1.62 + 1.63 + return (const char *)pkg_name; 1.64 +} 1.65 1.66 MetaIndex::MetaIndex(char** meta_package_names, int num_meta_package_names) { 1.67 if (num_meta_package_names == 0) {
2.1 --- a/src/share/vm/classfile/classLoader.hpp Fri Jun 12 02:59:56 2020 +0100 2.2 +++ b/src/share/vm/classfile/classLoader.hpp Mon Jun 15 14:08:11 2020 +0300 2.3 @@ -366,6 +366,11 @@ 2.4 // creates a class path zip entry (returns NULL if JAR file cannot be opened) 2.5 static ClassPathZipEntry* create_class_path_zip_entry(const char *apath); 2.6 2.7 + // obtain package name from a fully qualified class name 2.8 + // *bad_class_name is set to true if there's a problem with parsing class_name, to 2.9 + // distinguish from a class_name with no package name, as both cases have a NULL return value 2.10 + static const char* package_from_name(const char* const class_name, bool* bad_class_name = NULL); 2.11 + 2.12 // Debugging 2.13 static void verify() PRODUCT_RETURN; 2.14
3.1 --- a/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.cpp Fri Jun 12 02:59:56 2020 +0100 3.2 +++ b/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.cpp Mon Jun 15 14:08:11 2020 +0300 3.3 @@ -52,6 +52,7 @@ 3.4 // creates a unique id by combining a checkpoint relative symbol id (2^24) 3.5 // with the current checkpoint id (2^40) 3.6 #define CREATE_SYMBOL_ID(sym_id) (((u8)((checkpoint_id << 24) | sym_id))) 3.7 +#define CREATE_PACKAGE_ID(pkg_id) (((u8)((checkpoint_id << 24) | pkg_id))) 3.8 3.9 typedef const Klass* KlassPtr; 3.10 // XXX typedef const PackageEntry* PkgPtr; 3.11 @@ -61,12 +62,23 @@ 3.12 typedef const JfrSymbolId::SymbolEntry* SymbolEntryPtr; 3.13 typedef const JfrSymbolId::CStringEntry* CStringEntryPtr; 3.14 3.15 -// XXX 3.16 -// static traceid package_id(KlassPtr klass) { 3.17 -// assert(klass != NULL, "invariant"); 3.18 -// PkgPtr pkg_entry = klass->package(); 3.19 -// return pkg_entry == NULL ? 0 : TRACE_ID(pkg_entry); 3.20 -// } 3.21 +inline uintptr_t package_name_hash(const char *s) { 3.22 + uintptr_t val = 0; 3.23 + while (*s != 0) { 3.24 + val = *s++ + 31 * val; 3.25 + } 3.26 + return val; 3.27 +} 3.28 + 3.29 +static traceid package_id(KlassPtr klass, JfrArtifactSet* artifacts) { 3.30 + assert(klass != NULL, "invariant"); 3.31 + char* klass_name = klass->name()->as_C_string(); // uses ResourceMark declared in JfrTypeSet::serialize() 3.32 + const char* pkg_name = ClassLoader::package_from_name(klass_name, NULL); 3.33 + if (pkg_name == NULL) { 3.34 + return 0; 3.35 + } 3.36 + return CREATE_PACKAGE_ID(artifacts->markPackage(pkg_name, package_name_hash(pkg_name))); 3.37 +} 3.38 3.39 static traceid cld_id(CldPtr cld) { 3.40 assert(cld != NULL, "invariant"); 3.41 @@ -125,7 +137,7 @@ 3.42 theklass = obj_arr_klass->bottom_klass(); 3.43 } 3.44 if (theklass->oop_is_instance()) { 3.45 - pkg_id = 0; // XXX package_id(theklass); 3.46 + pkg_id = package_id(theklass, artifacts); 3.47 } else { 3.48 assert(theklass->oop_is_typeArray(), "invariant"); 3.49 } 3.50 @@ -169,28 +181,19 @@ 3.51 typedef JfrArtifactWriterImplHost<MethodPtr, write__artifact__method> MethodWriterImplTarget; 3.52 typedef JfrArtifactWriterHost<MethodWriterImplTarget, TYPE_METHOD> MethodWriterImpl; 3.53 3.54 -// XXX 3.55 -// int write__artifact__package(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* p) { 3.56 -// assert(writer != NULL, "invariant"); 3.57 -// assert(artifacts != NULL, "invariant"); 3.58 -// assert(p != NULL, "invariant"); 3.59 -// PkgPtr pkg = (PkgPtr)p; 3.60 -// Symbol* const pkg_name = pkg->name(); 3.61 -// const traceid package_name_symbol_id = pkg_name != NULL ? artifacts->mark(pkg_name) : 0; 3.62 -// assert(package_name_symbol_id > 0, "invariant"); 3.63 -// writer->write((traceid)TRACE_ID(pkg)); 3.64 -// writer->write((traceid)CREATE_SYMBOL_ID(package_name_symbol_id)); 3.65 -// writer->write((bool)pkg->is_exported()); 3.66 -// return 1; 3.67 -// } 3.68 +int write__artifact__package(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* p) { 3.69 + assert(writer != NULL, "invariant"); 3.70 + assert(artifacts != NULL, "invariant"); 3.71 + assert(p != NULL, "invariant"); 3.72 3.73 -// typedef LeakPredicate<PkgPtr> LeakPackagePredicate; 3.74 -// int _compare_pkg_ptr_(PkgPtr const& lhs, PkgPtr const& rhs) { return lhs > rhs ? 1 : (lhs < rhs) ? -1 : 0; } 3.75 -// typedef UniquePredicate<PkgPtr, _compare_pkg_ptr_> PackagePredicate; 3.76 -// typedef JfrPredicatedArtifactWriterImplHost<PkgPtr, LeakPackagePredicate, write__artifact__package> LeakPackageWriterImpl; 3.77 -// typedef JfrPredicatedArtifactWriterImplHost<PkgPtr, PackagePredicate, write__artifact__package> PackageWriterImpl; 3.78 -// typedef JfrArtifactWriterHost<LeakPackageWriterImpl, TYPE_PACKAGE> LeakPackageWriter; 3.79 -// typedef JfrArtifactWriterHost<PackageWriterImpl, TYPE_PACKAGE> PackageWriter; 3.80 + CStringEntryPtr entry = (CStringEntryPtr)p; 3.81 + const traceid package_name_symbol_id = artifacts->mark(entry->value(), package_name_hash(entry->value())); 3.82 + assert(package_name_symbol_id > 0, "invariant"); 3.83 + writer->write((traceid)CREATE_PACKAGE_ID(entry->id())); 3.84 + writer->write((traceid)CREATE_SYMBOL_ID(package_name_symbol_id)); 3.85 + writer->write((bool)true); // exported 3.86 + return 1; 3.87 +} 3.88 3.89 int write__artifact__classloader(JfrCheckpointWriter* writer, JfrArtifactSet* artifacts, const void* c) { 3.90 assert(c != NULL, "invariant"); 3.91 @@ -525,99 +528,17 @@ 3.92 do_klasses(); 3.93 } 3.94 3.95 -// XXX 3.96 -// typedef CompositeFunctor<PkgPtr, 3.97 -// PackageWriter, 3.98 -// ClearArtifact<PkgPtr> > PackageWriterWithClear; 3.99 +typedef JfrArtifactWriterImplHost<CStringEntryPtr, write__artifact__package> PackageEntryWriterImpl; 3.100 +typedef JfrArtifactWriterHost<PackageEntryWriterImpl, TYPE_PACKAGE> PackageEntryWriter; 3.101 3.102 -// typedef CompositeFunctor<PkgPtr, 3.103 -// LeakPackageWriter, 3.104 -// PackageWriter> CompositePackageWriter; 3.105 - 3.106 -// typedef CompositeFunctor<PkgPtr, 3.107 -// CompositePackageWriter, 3.108 -// ClearArtifact<PkgPtr> > CompositePackageWriterWithClear; 3.109 - 3.110 -// class PackageFieldSelector { 3.111 -// public: 3.112 -// typedef PkgPtr TypePtr; 3.113 -// static TypePtr select(KlassPtr klass) { 3.114 -// assert(klass != NULL, "invariant"); 3.115 -// return ((InstanceKlass*)klass)->package(); 3.116 -// } 3.117 -// }; 3.118 - 3.119 -// typedef KlassToFieldEnvelope<PackageFieldSelector, 3.120 -// PackageWriterWithClear> KlassPackageWriterWithClear; 3.121 - 3.122 -// typedef KlassToFieldEnvelope<PackageFieldSelector, 3.123 -// CompositePackageWriterWithClear> KlassCompositePackageWriterWithClear; 3.124 - 3.125 -// typedef JfrArtifactCallbackHost<PkgPtr, PackageWriterWithClear> PackageCallback; 3.126 -// typedef JfrArtifactCallbackHost<PkgPtr, CompositePackageWriterWithClear> CompositePackageCallback; 3.127 - 3.128 -// /* 3.129 -// * Composite operation 3.130 -// * 3.131 -// * LeakpPackageWriter -> 3.132 -// * PackageWriter -> 3.133 -// * ClearArtifact<PackageEntry> 3.134 -// * 3.135 -// */ 3.136 -// void JfrTypeSet::write_package_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) { 3.137 -// assert(_artifacts->has_klass_entries(), "invariant"); 3.138 -// ClearArtifact<PkgPtr> clear(_class_unload); 3.139 -// PackageWriter pw(writer, _artifacts, _class_unload); 3.140 -// if (leakp_writer == NULL) { 3.141 -// PackageWriterWithClear pwwc(&pw, &clear); 3.142 -// KlassPackageWriterWithClear kpwwc(&pwwc); 3.143 -// _artifacts->iterate_klasses(kpwwc); 3.144 -// PackageCallback callback(&pwwc); 3.145 -// _subsystem_callback = &callback; 3.146 -// do_packages(); 3.147 -// return; 3.148 -// } 3.149 -// LeakPackageWriter lpw(leakp_writer, _artifacts, _class_unload); 3.150 -// CompositePackageWriter cpw(&lpw, &pw); 3.151 -// CompositePackageWriterWithClear cpwwc(&cpw, &clear); 3.152 -// KlassCompositePackageWriterWithClear ckpw(&cpwwc); 3.153 -// _artifacts->iterate_klasses(ckpw); 3.154 -// CompositePackageCallback callback(&cpwwc); 3.155 -// _subsystem_callback = &callback; 3.156 -// do_packages(); 3.157 -// } 3.158 - 3.159 -// typedef CompositeFunctor<ModPtr, 3.160 -// ModuleWriter, 3.161 -// ClearArtifact<ModPtr> > ModuleWriterWithClear; 3.162 - 3.163 -// typedef CompositeFunctor<ModPtr, 3.164 -// LeakModuleWriter, 3.165 -// ModuleWriter> CompositeModuleWriter; 3.166 - 3.167 -// typedef CompositeFunctor<ModPtr, 3.168 -// CompositeModuleWriter, 3.169 -// ClearArtifact<ModPtr> > CompositeModuleWriterWithClear; 3.170 - 3.171 -// typedef JfrArtifactCallbackHost<ModPtr, ModuleWriterWithClear> ModuleCallback; 3.172 -// typedef JfrArtifactCallbackHost<ModPtr, CompositeModuleWriterWithClear> CompositeModuleCallback; 3.173 - 3.174 -// XXX 3.175 -// class ModuleFieldSelector { 3.176 -// public: 3.177 -// typedef ModPtr TypePtr; 3.178 -// static TypePtr select(KlassPtr klass) { 3.179 -// assert(klass != NULL, "invariant"); 3.180 -// PkgPtr pkg = klass->package(); 3.181 -// return pkg != NULL ? pkg->module() : NULL; 3.182 -// } 3.183 -// }; 3.184 - 3.185 -// typedef KlassToFieldEnvelope<ModuleFieldSelector, 3.186 -// ModuleWriterWithClear> KlassModuleWriterWithClear; 3.187 - 3.188 -// typedef KlassToFieldEnvelope<ModuleFieldSelector, 3.189 -// CompositeModuleWriterWithClear> KlassCompositeModuleWriterWithClear; 3.190 +void JfrTypeSet::write_package_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer) { 3.191 + assert(_artifacts->has_klass_entries(), "invariant"); 3.192 + assert(writer != NULL, "invariant"); 3.193 + // below jdk9 there is no oop for packages, so nothing to do with leakp_writer 3.194 + // just write packages 3.195 + PackageEntryWriter pw(writer, _artifacts, _class_unload); 3.196 + _artifacts->iterate_packages(pw); 3.197 +} 3.198 3.199 typedef CompositeFunctor<CldPtr, CldWriter, ClearArtifact<CldPtr> > CldWriterWithClear; 3.200 typedef CompositeFunctor<CldPtr, LeakCldWriter, CldWriter> CompositeCldWriter; 3.201 @@ -892,7 +813,7 @@ 3.202 // might tag an artifact to be written in a subsequent step 3.203 write_klass_constants(writer, leakp_writer); 3.204 if (_artifacts->has_klass_entries()) { 3.205 -// XXX write_package_constants(writer, leakp_writer); 3.206 + write_package_constants(writer, leakp_writer); 3.207 write_class_loader_constants(writer, leakp_writer); 3.208 write_method_constants(writer, leakp_writer); 3.209 write_symbol_constants(writer, leakp_writer);
4.1 --- a/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.hpp Fri Jun 12 02:59:56 2020 +0100 4.2 +++ b/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSet.hpp Mon Jun 15 14:08:11 2020 +0300 4.3 @@ -58,7 +58,7 @@ 4.4 static void do_class_loaders(); 4.5 4.6 static void write_klass_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer); 4.7 -// XXX static void write_package_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer); 4.8 + static void write_package_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer); 4.9 static void write_class_loader_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer); 4.10 static void write_method_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer); 4.11 static void write_symbol_constants(JfrCheckpointWriter* writer, JfrCheckpointWriter* leakp_writer);
5.1 --- a/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp Fri Jun 12 02:59:56 2020 +0100 5.2 +++ b/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.cpp Mon Jun 15 14:08:11 2020 +0300 5.3 @@ -28,9 +28,11 @@ 5.4 #include "oops/oop.inline.hpp" 5.5 #include "oops/symbol.hpp" 5.6 5.7 -JfrSymbolId::JfrSymbolId() : _symbol_id_counter(0), _sym_table(new SymbolTable(this)), _cstring_table(new CStringTable(this)) { 5.8 +JfrSymbolId::JfrSymbolId() : _symbol_id_counter(0), _sym_table(new SymbolTable(this)), 5.9 + _cstring_table(new CStringTable(this)), _pkg_table(new CStringTable(this)) { 5.10 assert(_sym_table != NULL, "invariant"); 5.11 assert(_cstring_table != NULL, "invariant"); 5.12 + assert(_pkg_table != NULL, "invariant"); 5.13 initialize(); 5.14 } 5.15 5.16 @@ -52,6 +54,11 @@ 5.17 } 5.18 assert(!_cstring_table->has_entries(), "invariant"); 5.19 _symbol_id_counter = 0; 5.20 + assert(_pkg_table != NULL, "invariant"); 5.21 + if (_pkg_table->has_entries()) { 5.22 + _pkg_table->clear_entries(); 5.23 + } 5.24 + assert(!_pkg_table->has_entries(), "invariant"); 5.25 } 5.26 5.27 JfrSymbolId::~JfrSymbolId() { 5.28 @@ -148,6 +155,12 @@ 5.29 return _cstring_table->id(str, hash); 5.30 } 5.31 5.32 +traceid JfrSymbolId::markPackage(const char* name, uintptr_t hash) { 5.33 + assert(name != NULL, "invariant"); 5.34 + assert(_pkg_table != NULL, "invariant"); 5.35 + return _pkg_table->id(name, hash); 5.36 +} 5.37 + 5.38 bool JfrSymbolId::is_anonymous_klass(const Klass* k) { 5.39 assert(k != NULL, "invariant"); 5.40 return k->oop_is_instance() && ((const InstanceKlass*)k)->is_anonymous(); 5.41 @@ -243,6 +256,10 @@ 5.42 return _symbol_id->mark(str, hash); 5.43 } 5.44 5.45 +traceid JfrArtifactSet::markPackage(const char* const name, uintptr_t hash) { 5.46 + return _symbol_id->markPackage(name, hash); 5.47 +} 5.48 + 5.49 const JfrSymbolId::SymbolEntry* JfrArtifactSet::map_symbol(const Symbol* symbol) const { 5.50 return _symbol_id->map_symbol(symbol); 5.51 }
6.1 --- a/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp Fri Jun 12 02:59:56 2020 +0100 6.2 +++ b/src/share/vm/jfr/recorder/checkpoint/types/jfrTypeSetUtils.hpp Mon Jun 15 14:08:11 2020 +0300 6.3 @@ -230,9 +230,10 @@ 6.4 typedef SymbolTable::HashEntry SymbolEntry; 6.5 typedef CStringTable::HashEntry CStringEntry; 6.6 private: 6.7 + traceid _symbol_id_counter; 6.8 SymbolTable* _sym_table; 6.9 CStringTable* _cstring_table; 6.10 - traceid _symbol_id_counter; 6.11 + CStringTable* _pkg_table; 6.12 6.13 // hashtable(s) callbacks 6.14 void assign_id(SymbolEntry* entry); 6.15 @@ -257,6 +258,12 @@ 6.16 traceid mark(const Klass* k); 6.17 traceid mark(const Symbol* symbol); 6.18 traceid mark(const char* str, uintptr_t hash); 6.19 + traceid markPackage(const char* name, uintptr_t hash); 6.20 + 6.21 + template <typename T> 6.22 + void iterate_packages(T& functor) { 6.23 + _pkg_table->iterate_entry(functor); 6.24 + } 6.25 6.26 const SymbolEntry* map_symbol(const Symbol* symbol) const; 6.27 const SymbolEntry* map_symbol(uintptr_t hash) const; 6.28 @@ -334,6 +341,8 @@ 6.29 traceid mark(const char* const str, uintptr_t hash); 6.30 traceid mark_anonymous_klass_name(const Klass* klass); 6.31 6.32 + traceid markPackage(const char* const name, uintptr_t hash); 6.33 + 6.34 const JfrSymbolId::SymbolEntry* map_symbol(const Symbol* symbol) const; 6.35 const JfrSymbolId::SymbolEntry* map_symbol(uintptr_t hash) const; 6.36 const JfrSymbolId::CStringEntry* map_cstring(uintptr_t hash) const; 6.37 @@ -360,6 +369,11 @@ 6.38 void iterate_cstrings(T& functor) { 6.39 _symbol_id->iterate_cstrings(functor); 6.40 } 6.41 + 6.42 + template <typename T> 6.43 + void iterate_packages(T& functor) { 6.44 + _symbol_id->iterate_packages(functor); 6.45 + } 6.46 }; 6.47 6.48 class KlassArtifactRegistrator {