| 1 | /* |
| 2 | * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. |
| 3 | * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| 4 | * |
| 5 | * This code is free software; you can redistribute it and/or modify it |
| 6 | * under the terms of the GNU General Public License version 2 only, as |
| 7 | * published by the Free Software Foundation. |
| 8 | * |
| 9 | * This code is distributed in the hope that it will be useful, but WITHOUT |
| 10 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 11 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| 12 | * version 2 for more details (a copy is included in the LICENSE file that |
| 13 | * accompanied this code). |
| 14 | * |
| 15 | * You should have received a copy of the GNU General Public License version |
| 16 | * 2 along with this work; if not, write to the Free Software Foundation, |
| 17 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| 18 | * |
| 19 | * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| 20 | * or visit www.oracle.com if you need additional information or have any |
| 21 | * questions. |
| 22 | * |
| 23 | */ |
| 24 | |
| 25 | #ifndef SHARE_CLASSFILE_CLASSLOADER_HPP |
| 26 | #define SHARE_CLASSFILE_CLASSLOADER_HPP |
| 27 | |
| 28 | #include "jimage.hpp" |
| 29 | #include "runtime/handles.hpp" |
| 30 | #include "runtime/perfData.hpp" |
| 31 | #include "utilities/exceptions.hpp" |
| 32 | #include "utilities/macros.hpp" |
| 33 | |
| 34 | // The VM class loader. |
| 35 | #include <sys/stat.h> |
| 36 | |
| 37 | // Name of boot "modules" image |
| 38 | #define MODULES_IMAGE_NAME "modules" |
| 39 | |
| 40 | // Class path entry (directory or zip file) |
| 41 | |
| 42 | class JImageFile; |
| 43 | class ClassFileStream; |
| 44 | class PackageEntry; |
| 45 | template <typename T> class GrowableArray; |
| 46 | |
| 47 | class ClassPathEntry : public CHeapObj<mtClass> { |
| 48 | private: |
| 49 | ClassPathEntry* volatile _next; |
| 50 | public: |
| 51 | ClassPathEntry* next() const; |
| 52 | virtual ~ClassPathEntry() {} |
| 53 | void set_next(ClassPathEntry* next); |
| 54 | virtual bool is_modules_image() const = 0; |
| 55 | virtual bool is_jar_file() const = 0; |
| 56 | virtual const char* name() const = 0; |
| 57 | virtual JImageFile* jimage() const = 0; |
| 58 | virtual void close_jimage() = 0; |
| 59 | // Constructor |
| 60 | ClassPathEntry() : _next(NULL) {} |
| 61 | // Attempt to locate file_name through this class path entry. |
| 62 | // Returns a class file parsing stream if successfull. |
| 63 | virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0; |
| 64 | // Open the stream for a specific class loader |
| 65 | virtual ClassFileStream* open_stream_for_loader(const char* name, ClassLoaderData* loader_data, TRAPS) { |
| 66 | return open_stream(name, THREAD); |
| 67 | } |
| 68 | }; |
| 69 | |
| 70 | class ClassPathDirEntry: public ClassPathEntry { |
| 71 | private: |
| 72 | const char* _dir; // Name of directory |
| 73 | public: |
| 74 | bool is_modules_image() const { return false; } |
| 75 | bool is_jar_file() const { return false; } |
| 76 | const char* name() const { return _dir; } |
| 77 | JImageFile* jimage() const { return NULL; } |
| 78 | void close_jimage() {} |
| 79 | ClassPathDirEntry(const char* dir); |
| 80 | virtual ~ClassPathDirEntry() {} |
| 81 | ClassFileStream* open_stream(const char* name, TRAPS); |
| 82 | }; |
| 83 | |
| 84 | |
| 85 | // Type definitions for zip file and zip file entry |
| 86 | typedef void* jzfile; |
| 87 | typedef struct { |
| 88 | char *name; /* entry name */ |
| 89 | jlong time; /* modification time */ |
| 90 | jlong size; /* size of uncompressed data */ |
| 91 | jlong csize; /* size of compressed data (zero if uncompressed) */ |
| 92 | jint crc; /* crc of uncompressed data */ |
| 93 | char *; /* optional zip file comment */ |
| 94 | jbyte *; /* optional extra data */ |
| 95 | jlong pos; /* position of LOC header (if negative) or data */ |
| 96 | } jzentry; |
| 97 | |
| 98 | class ClassPathZipEntry: public ClassPathEntry { |
| 99 | private: |
| 100 | jzfile* _zip; // The zip archive |
| 101 | const char* _zip_name; // Name of zip archive |
| 102 | public: |
| 103 | bool is_modules_image() const { return false; } |
| 104 | bool is_jar_file() const { return true; } |
| 105 | const char* name() const { return _zip_name; } |
| 106 | JImageFile* jimage() const { return NULL; } |
| 107 | void close_jimage() {} |
| 108 | ClassPathZipEntry(jzfile* zip, const char* zip_name, bool is_boot_append); |
| 109 | virtual ~ClassPathZipEntry(); |
| 110 | u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS); |
| 111 | ClassFileStream* open_stream(const char* name, TRAPS); |
| 112 | void contents_do(void f(const char* name, void* context), void* context); |
| 113 | }; |
| 114 | |
| 115 | |
| 116 | // For java image files |
| 117 | class ClassPathImageEntry: public ClassPathEntry { |
| 118 | private: |
| 119 | JImageFile* _jimage; |
| 120 | const char* _name; |
| 121 | DEBUG_ONLY(static ClassPathImageEntry* _singleton;) |
| 122 | public: |
| 123 | bool is_modules_image() const; |
| 124 | bool is_jar_file() const { return false; } |
| 125 | bool is_open() const { return _jimage != NULL; } |
| 126 | const char* name() const { return _name == NULL ? "" : _name; } |
| 127 | JImageFile* jimage() const { return _jimage; } |
| 128 | void close_jimage(); |
| 129 | ClassPathImageEntry(JImageFile* jimage, const char* name); |
| 130 | virtual ~ClassPathImageEntry(); |
| 131 | ClassFileStream* open_stream(const char* name, TRAPS); |
| 132 | ClassFileStream* open_stream_for_loader(const char* name, ClassLoaderData* loader_data, TRAPS); |
| 133 | }; |
| 134 | |
| 135 | // ModuleClassPathList contains a linked list of ClassPathEntry's |
| 136 | // that have been specified for a specific module. Currently, |
| 137 | // the only way to specify a module/path pair is via the --patch-module |
| 138 | // command line option. |
| 139 | class ModuleClassPathList : public CHeapObj<mtClass> { |
| 140 | private: |
| 141 | Symbol* _module_name; |
| 142 | // First and last entries of class path entries for a specific module |
| 143 | ClassPathEntry* _module_first_entry; |
| 144 | ClassPathEntry* _module_last_entry; |
| 145 | public: |
| 146 | Symbol* module_name() const { return _module_name; } |
| 147 | ClassPathEntry* module_first_entry() const { return _module_first_entry; } |
| 148 | ModuleClassPathList(Symbol* module_name); |
| 149 | ~ModuleClassPathList(); |
| 150 | void add_to_list(ClassPathEntry* new_entry); |
| 151 | }; |
| 152 | |
| 153 | class SharedPathsMiscInfo; |
| 154 | |
| 155 | class ClassLoader: AllStatic { |
| 156 | public: |
| 157 | enum ClassLoaderType { |
| 158 | BOOT_LOADER = 1, /* boot loader */ |
| 159 | PLATFORM_LOADER = 2, /* PlatformClassLoader */ |
| 160 | APP_LOADER = 3 /* AppClassLoader */ |
| 161 | }; |
| 162 | protected: |
| 163 | |
| 164 | // Performance counters |
| 165 | static PerfCounter* _perf_accumulated_time; |
| 166 | static PerfCounter* _perf_classes_inited; |
| 167 | static PerfCounter* _perf_class_init_time; |
| 168 | static PerfCounter* _perf_class_init_selftime; |
| 169 | static PerfCounter* _perf_classes_verified; |
| 170 | static PerfCounter* _perf_class_verify_time; |
| 171 | static PerfCounter* _perf_class_verify_selftime; |
| 172 | static PerfCounter* _perf_classes_linked; |
| 173 | static PerfCounter* _perf_class_link_time; |
| 174 | static PerfCounter* _perf_class_link_selftime; |
| 175 | static PerfCounter* _perf_class_parse_time; |
| 176 | static PerfCounter* _perf_class_parse_selftime; |
| 177 | static PerfCounter* _perf_sys_class_lookup_time; |
| 178 | static PerfCounter* _perf_shared_classload_time; |
| 179 | static PerfCounter* _perf_sys_classload_time; |
| 180 | static PerfCounter* _perf_app_classload_time; |
| 181 | static PerfCounter* _perf_app_classload_selftime; |
| 182 | static PerfCounter* _perf_app_classload_count; |
| 183 | static PerfCounter* _perf_define_appclasses; |
| 184 | static PerfCounter* _perf_define_appclass_time; |
| 185 | static PerfCounter* _perf_define_appclass_selftime; |
| 186 | static PerfCounter* _perf_app_classfile_bytes_read; |
| 187 | static PerfCounter* _perf_sys_classfile_bytes_read; |
| 188 | |
| 189 | static PerfCounter* _sync_systemLoaderLockContentionRate; |
| 190 | static PerfCounter* _sync_nonSystemLoaderLockContentionRate; |
| 191 | static PerfCounter* _sync_JVMFindLoadedClassLockFreeCounter; |
| 192 | static PerfCounter* _sync_JVMDefineClassLockFreeCounter; |
| 193 | static PerfCounter* _sync_JNIDefineClassLockFreeCounter; |
| 194 | |
| 195 | static PerfCounter* _unsafe_defineClassCallCounter; |
| 196 | |
| 197 | // The boot class path consists of 3 ordered pieces: |
| 198 | // 1. the module/path pairs specified to --patch-module |
| 199 | // --patch-module=<module>=<file>(<pathsep><file>)* |
| 200 | // 2. the base piece |
| 201 | // [jimage | build with exploded modules] |
| 202 | // 3. boot loader append path |
| 203 | // [-Xbootclasspath/a]; [jvmti appended entries] |
| 204 | // |
| 205 | // The boot loader must obey this order when attempting |
| 206 | // to load a class. |
| 207 | |
| 208 | // 1. Contains the module/path pairs specified to --patch-module |
| 209 | static GrowableArray<ModuleClassPathList*>* _patch_mod_entries; |
| 210 | |
| 211 | // 2. the base piece |
| 212 | // Contains the ClassPathEntry of the modular java runtime image. |
| 213 | // If no java runtime image is present, this indicates a |
| 214 | // build with exploded modules is being used instead. |
| 215 | static ClassPathEntry* _jrt_entry; |
| 216 | static GrowableArray<ModuleClassPathList*>* _exploded_entries; |
| 217 | enum { EXPLODED_ENTRY_SIZE = 80 }; // Initial number of exploded modules |
| 218 | |
| 219 | // 3. the boot loader's append path |
| 220 | // [-Xbootclasspath/a]; [jvmti appended entries] |
| 221 | // Note: boot loader append path does not support named modules. |
| 222 | static ClassPathEntry* _first_append_entry; |
| 223 | // Last entry in linked list of appended ClassPathEntry instances |
| 224 | static ClassPathEntry* _last_append_entry; |
| 225 | |
| 226 | // Info used by CDS |
| 227 | CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;) |
| 228 | |
| 229 | CDS_ONLY(static ClassPathEntry* _app_classpath_entries;) |
| 230 | CDS_ONLY(static ClassPathEntry* _last_app_classpath_entry;) |
| 231 | CDS_ONLY(static ClassPathEntry* _module_path_entries;) |
| 232 | CDS_ONLY(static ClassPathEntry* _last_module_path_entry;) |
| 233 | CDS_ONLY(static void setup_app_search_path(const char* class_path);) |
| 234 | CDS_ONLY(static void setup_module_search_path(const char* path, TRAPS);) |
| 235 | static void add_to_app_classpath_entries(const char* path, |
| 236 | ClassPathEntry* entry, |
| 237 | bool check_for_duplicates); |
| 238 | CDS_ONLY(static void add_to_module_path_entries(const char* path, |
| 239 | ClassPathEntry* entry);) |
| 240 | public: |
| 241 | CDS_ONLY(static ClassPathEntry* app_classpath_entries() {return _app_classpath_entries;}) |
| 242 | CDS_ONLY(static ClassPathEntry* module_path_entries() {return _module_path_entries;}) |
| 243 | |
| 244 | protected: |
| 245 | // Initialization: |
| 246 | // - setup the boot loader's system class path |
| 247 | // - setup the boot loader's patch mod entries, if present |
| 248 | // - create the ModuleEntry for java.base |
| 249 | static void setup_bootstrap_search_path(); |
| 250 | static void setup_boot_search_path(const char *class_path); |
| 251 | static void setup_patch_mod_entries(); |
| 252 | static void create_javabase(); |
| 253 | |
| 254 | static void load_zip_library(); |
| 255 | static void load_jimage_library(); |
| 256 | |
| 257 | public: |
| 258 | static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st, |
| 259 | bool throw_exception, |
| 260 | bool is_boot_append, TRAPS); |
| 261 | |
| 262 | // If the package for the fully qualified class name is in the boot |
| 263 | // loader's package entry table then add_package() sets the classpath_index |
| 264 | // field so that get_system_package() will know to return a non-null value |
| 265 | // for the package's location. And, so that the package will be added to |
| 266 | // the list of packages returned by get_system_packages(). |
| 267 | // For packages whose classes are loaded from the boot loader class path, the |
| 268 | // classpath_index indicates which entry on the boot loader class path. |
| 269 | static bool add_package(const char *fullq_class_name, s2 classpath_index, TRAPS); |
| 270 | |
| 271 | // Canonicalizes path names, so strcmp will work properly. This is mainly |
| 272 | // to avoid confusing the zip library |
| 273 | static bool get_canonical_path(const char* orig, char* out, int len); |
| 274 | static const char* file_name_for_class_name(const char* class_name, |
| 275 | int class_name_len); |
| 276 | static PackageEntry* get_package_entry(const char* class_name, ClassLoaderData* loader_data, TRAPS); |
| 277 | |
| 278 | public: |
| 279 | static jboolean decompress(void *in, u8 inSize, void *out, u8 outSize, char **pmsg); |
| 280 | static int crc32(int crc, const char* buf, int len); |
| 281 | static bool update_class_path_entry_list(const char *path, |
| 282 | bool check_for_duplicates, |
| 283 | bool is_boot_append, |
| 284 | bool throw_exception=true); |
| 285 | CDS_ONLY(static void update_module_path_entry_list(const char *path, TRAPS);) |
| 286 | static void print_bootclasspath(); |
| 287 | |
| 288 | // Timing |
| 289 | static PerfCounter* perf_accumulated_time() { return _perf_accumulated_time; } |
| 290 | static PerfCounter* perf_classes_inited() { return _perf_classes_inited; } |
| 291 | static PerfCounter* perf_class_init_time() { return _perf_class_init_time; } |
| 292 | static PerfCounter* perf_class_init_selftime() { return _perf_class_init_selftime; } |
| 293 | static PerfCounter* perf_classes_verified() { return _perf_classes_verified; } |
| 294 | static PerfCounter* perf_class_verify_time() { return _perf_class_verify_time; } |
| 295 | static PerfCounter* perf_class_verify_selftime() { return _perf_class_verify_selftime; } |
| 296 | static PerfCounter* perf_classes_linked() { return _perf_classes_linked; } |
| 297 | static PerfCounter* perf_class_link_time() { return _perf_class_link_time; } |
| 298 | static PerfCounter* perf_class_link_selftime() { return _perf_class_link_selftime; } |
| 299 | static PerfCounter* perf_class_parse_time() { return _perf_class_parse_time; } |
| 300 | static PerfCounter* perf_class_parse_selftime() { return _perf_class_parse_selftime; } |
| 301 | static PerfCounter* perf_sys_class_lookup_time() { return _perf_sys_class_lookup_time; } |
| 302 | static PerfCounter* perf_shared_classload_time() { return _perf_shared_classload_time; } |
| 303 | static PerfCounter* perf_sys_classload_time() { return _perf_sys_classload_time; } |
| 304 | static PerfCounter* perf_app_classload_time() { return _perf_app_classload_time; } |
| 305 | static PerfCounter* perf_app_classload_selftime() { return _perf_app_classload_selftime; } |
| 306 | static PerfCounter* perf_app_classload_count() { return _perf_app_classload_count; } |
| 307 | static PerfCounter* perf_define_appclasses() { return _perf_define_appclasses; } |
| 308 | static PerfCounter* perf_define_appclass_time() { return _perf_define_appclass_time; } |
| 309 | static PerfCounter* perf_define_appclass_selftime() { return _perf_define_appclass_selftime; } |
| 310 | static PerfCounter* perf_app_classfile_bytes_read() { return _perf_app_classfile_bytes_read; } |
| 311 | static PerfCounter* perf_sys_classfile_bytes_read() { return _perf_sys_classfile_bytes_read; } |
| 312 | |
| 313 | // Record how often system loader lock object is contended |
| 314 | static PerfCounter* sync_systemLoaderLockContentionRate() { |
| 315 | return _sync_systemLoaderLockContentionRate; |
| 316 | } |
| 317 | |
| 318 | // Record how often non system loader lock object is contended |
| 319 | static PerfCounter* sync_nonSystemLoaderLockContentionRate() { |
| 320 | return _sync_nonSystemLoaderLockContentionRate; |
| 321 | } |
| 322 | |
| 323 | // Record how many calls to JVM_FindLoadedClass w/o holding a lock |
| 324 | static PerfCounter* sync_JVMFindLoadedClassLockFreeCounter() { |
| 325 | return _sync_JVMFindLoadedClassLockFreeCounter; |
| 326 | } |
| 327 | |
| 328 | // Record how many calls to JVM_DefineClass w/o holding a lock |
| 329 | static PerfCounter* sync_JVMDefineClassLockFreeCounter() { |
| 330 | return _sync_JVMDefineClassLockFreeCounter; |
| 331 | } |
| 332 | |
| 333 | // Record how many calls to jni_DefineClass w/o holding a lock |
| 334 | static PerfCounter* sync_JNIDefineClassLockFreeCounter() { |
| 335 | return _sync_JNIDefineClassLockFreeCounter; |
| 336 | } |
| 337 | |
| 338 | // Record how many calls to Unsafe_DefineClass |
| 339 | static PerfCounter* unsafe_defineClassCallCounter() { |
| 340 | return _unsafe_defineClassCallCounter; |
| 341 | } |
| 342 | |
| 343 | // Modular java runtime image is present vs. a build with exploded modules |
| 344 | static bool has_jrt_entry() { return (_jrt_entry != NULL); } |
| 345 | static ClassPathEntry* get_jrt_entry() { return _jrt_entry; } |
| 346 | static void close_jrt_image(); |
| 347 | |
| 348 | // Add a module's exploded directory to the boot loader's exploded module build list |
| 349 | static void add_to_exploded_build_list(Symbol* module_name, TRAPS); |
| 350 | |
| 351 | // Attempt load of individual class from either the patched or exploded modules build lists |
| 352 | static ClassFileStream* search_module_entries(const GrowableArray<ModuleClassPathList*>* const module_list, |
| 353 | const char* const class_name, |
| 354 | const char* const file_name, TRAPS); |
| 355 | |
| 356 | // Load individual .class file |
| 357 | static InstanceKlass* load_class(Symbol* class_name, bool search_append_only, TRAPS); |
| 358 | |
| 359 | // If the specified package has been loaded by the system, then returns |
| 360 | // the name of the directory or ZIP file that the package was loaded from. |
| 361 | // Returns null if the package was not loaded. |
| 362 | // Note: The specified name can either be the name of a class or package. |
| 363 | // If a package name is specified, then it must be "/"-separator and also |
| 364 | // end with a trailing "/". |
| 365 | static oop get_system_package(const char* name, TRAPS); |
| 366 | |
| 367 | // Returns an array of Java strings representing all of the currently |
| 368 | // loaded system packages. |
| 369 | // Note: The package names returned are "/"-separated and end with a |
| 370 | // trailing "/". |
| 371 | static objArrayOop get_system_packages(TRAPS); |
| 372 | |
| 373 | // Initialization |
| 374 | static void initialize(); |
| 375 | static void classLoader_init2(TRAPS); |
| 376 | CDS_ONLY(static void initialize_shared_path();) |
| 377 | CDS_ONLY(static void initialize_module_path(TRAPS);) |
| 378 | |
| 379 | static int compute_Object_vtable(); |
| 380 | |
| 381 | static ClassPathEntry* classpath_entry(int n); |
| 382 | |
| 383 | static bool is_in_patch_mod_entries(Symbol* module_name); |
| 384 | |
| 385 | #if INCLUDE_CDS |
| 386 | // Sharing dump and restore |
| 387 | |
| 388 | // Helper function used by CDS code to get the number of boot classpath |
| 389 | // entries during shared classpath setup time. |
| 390 | static int num_boot_classpath_entries(); |
| 391 | |
| 392 | static ClassPathEntry* get_next_boot_classpath_entry(ClassPathEntry* e); |
| 393 | |
| 394 | // Helper function used by CDS code to get the number of app classpath |
| 395 | // entries during shared classpath setup time. |
| 396 | static int num_app_classpath_entries(); |
| 397 | |
| 398 | // Helper function used by CDS code to get the number of module path |
| 399 | // entries during shared classpath setup time. |
| 400 | static int num_module_path_entries() { |
| 401 | assert(DumpSharedSpaces || DynamicDumpSharedSpaces, |
| 402 | "Should only be called at CDS dump time" ); |
| 403 | int num_entries = 0; |
| 404 | ClassPathEntry* e= ClassLoader::_module_path_entries; |
| 405 | while (e != NULL) { |
| 406 | num_entries ++; |
| 407 | e = e->next(); |
| 408 | } |
| 409 | return num_entries; |
| 410 | } |
| 411 | static void finalize_shared_paths_misc_info(); |
| 412 | static int get_shared_paths_misc_info_size(); |
| 413 | static void* get_shared_paths_misc_info(); |
| 414 | static bool check_shared_paths_misc_info(void* info, int size, bool is_static); |
| 415 | static void exit_with_path_failure(const char* error, const char* message); |
| 416 | static char* skip_uri_protocol(char* source); |
| 417 | static void record_result(InstanceKlass* ik, const ClassFileStream* stream, TRAPS); |
| 418 | #endif |
| 419 | static JImageLocationRef jimage_find_resource(JImageFile* jf, const char* module_name, |
| 420 | const char* file_name, jlong &size); |
| 421 | |
| 422 | static void trace_class_path(const char* msg, const char* name = NULL); |
| 423 | |
| 424 | // VM monitoring and management support |
| 425 | static jlong classloader_time_ms(); |
| 426 | static jlong class_method_total_size(); |
| 427 | static jlong class_init_count(); |
| 428 | static jlong class_init_time_ms(); |
| 429 | static jlong class_verify_time_ms(); |
| 430 | static jlong class_link_count(); |
| 431 | static jlong class_link_time_ms(); |
| 432 | |
| 433 | // indicates if class path already contains a entry (exact match by name) |
| 434 | static bool contains_append_entry(const char* name); |
| 435 | |
| 436 | // adds a class path to the boot append entries |
| 437 | static void add_to_boot_append_entries(ClassPathEntry* new_entry); |
| 438 | |
| 439 | // creates a class path zip entry (returns NULL if JAR file cannot be opened) |
| 440 | static ClassPathZipEntry* create_class_path_zip_entry(const char *apath, bool is_boot_append); |
| 441 | |
| 442 | static bool string_ends_with(const char* str, const char* str_to_find); |
| 443 | |
| 444 | // obtain package name from a fully qualified class name |
| 445 | // *bad_class_name is set to true if there's a problem with parsing class_name, to |
| 446 | // distinguish from a class_name with no package name, as both cases have a NULL return value |
| 447 | static const char* package_from_name(const char* const class_name, bool* bad_class_name = NULL); |
| 448 | |
| 449 | // Debugging |
| 450 | static void verify() PRODUCT_RETURN; |
| 451 | }; |
| 452 | |
| 453 | // PerfClassTraceTime is used to measure time for class loading related events. |
| 454 | // This class tracks cumulative time and exclusive time for specific event types. |
| 455 | // During the execution of one event, other event types (e.g. class loading and |
| 456 | // resolution) as well as recursive calls of the same event type could happen. |
| 457 | // Only one elapsed timer (cumulative) and one thread-local self timer (exclusive) |
| 458 | // (i.e. only one event type) are active at a time even multiple PerfClassTraceTime |
| 459 | // instances have been created as multiple events are happening. |
| 460 | class PerfClassTraceTime { |
| 461 | public: |
| 462 | enum { |
| 463 | CLASS_LOAD = 0, |
| 464 | PARSE_CLASS = 1, |
| 465 | CLASS_LINK = 2, |
| 466 | CLASS_VERIFY = 3, |
| 467 | CLASS_CLINIT = 4, |
| 468 | DEFINE_CLASS = 5, |
| 469 | EVENT_TYPE_COUNT = 6 |
| 470 | }; |
| 471 | protected: |
| 472 | // _t tracks time from initialization to destruction of this timer instance |
| 473 | // including time for all other event types, and recursive calls of this type. |
| 474 | // When a timer is called recursively, the elapsedTimer _t would not be used. |
| 475 | elapsedTimer _t; |
| 476 | PerfLongCounter* _timep; |
| 477 | PerfLongCounter* _selftimep; |
| 478 | PerfLongCounter* _eventp; |
| 479 | // pointer to thread-local recursion counter and timer array |
| 480 | // The thread_local timers track cumulative time for specific event types |
| 481 | // exclusive of time for other event types, but including recursive calls |
| 482 | // of the same type. |
| 483 | int* _recursion_counters; |
| 484 | elapsedTimer* _timers; |
| 485 | int _event_type; |
| 486 | int _prev_active_event; |
| 487 | |
| 488 | public: |
| 489 | |
| 490 | inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ |
| 491 | PerfLongCounter* selftimep, /* counter incremented with exclusive time */ |
| 492 | PerfLongCounter* eventp, /* event counter */ |
| 493 | int* recursion_counters, /* thread-local recursion counter array */ |
| 494 | elapsedTimer* timers, /* thread-local timer array */ |
| 495 | int type /* event type */ ) : |
| 496 | _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) { |
| 497 | initialize(); |
| 498 | } |
| 499 | |
| 500 | inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ |
| 501 | elapsedTimer* timers, /* thread-local timer array */ |
| 502 | int type /* event type */ ) : |
| 503 | _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) { |
| 504 | initialize(); |
| 505 | } |
| 506 | |
| 507 | inline void suspend() { _t.stop(); _timers[_event_type].stop(); } |
| 508 | inline void resume() { _t.start(); _timers[_event_type].start(); } |
| 509 | |
| 510 | ~PerfClassTraceTime(); |
| 511 | void initialize(); |
| 512 | }; |
| 513 | |
| 514 | #endif // SHARE_CLASSFILE_CLASSLOADER_HPP |
| 515 | |