ssssssss13


class ClassFileParser VALUE_OBJ_CLASS_SPEC {
 private:
  bool _need_verify;
  bool _relax_verify;
  u2   _major_version;
  u2   _minor_version;
  u2   _this_class_index;
  Symbol* _class_name;
  ClassLoaderData* _loader_data;
  KlassHandle _host_klass;
  GrowableArray<Handle>* _cp_patches; // overrides for CP entries
  bool _has_finalizer;
  bool _has_empty_finalizer;
  bool _has_vanilla_constructor;
  int _max_bootstrap_specifier_index;  // detects BSS values
  bool       _synthetic_flag;
  int        _sde_length;
  char*      _sde_buffer;
  u2         _sourcefile_index;
  u2         _generic_signature_index;
  instanceKlassHandle _super_klass;
  ConstantPool*    _cp;
  Array<u2>*       _fields;
  Array<Method*>*  _methods;
  Array<u2>*       _inner_classes;
  Array<Klass*>*   _local_interfaces;
  Array<Klass*>*   _transitive_interfaces;
  Annotations*     _combined_annotations;
  AnnotationArray* _annotations;
  AnnotationArray* _type_annotations;
  Array<AnnotationArray*>* _fields_annotations;
  Array<AnnotationArray*>* _fields_type_annotations;
  InstanceKlass*   _klass;  // InstanceKlass once created.
  void set_class_synthetic_flag(bool x)        { _synthetic_flag = x; }
  void set_class_sourcefile_index(u2 x)        { _sourcefile_index = x; }
  void set_class_generic_signature_index(u2 x) { _generic_signature_index = x; }
  void set_class_sde_buffer(char* x, int len)  { _sde_buffer = x; _sde_length = len; }
  void create_combined_annotations(TRAPS);
  void init_parsed_class_attributes(ClassLoaderData* loader_data) {
    _loader_data = loader_data;
    _synthetic_flag = false;
    _sourcefile_index = 0;
    _generic_signature_index = 0;
    _sde_buffer = NULL;
    _sde_length = 0;
    _has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false;
    _max_bootstrap_specifier_index = -1;
    clear_class_metadata();
    _klass = NULL;
  }
  void apply_parsed_class_attributes(instanceKlassHandle k);  // update k
  void apply_parsed_class_metadata(instanceKlassHandle k, int fields_count, TRAPS);
  void clear_class_metadata() {
    _cp = NULL;
    _fields = NULL;
    _methods = NULL;
    _inner_classes = NULL;
    _local_interfaces = NULL;
    _transitive_interfaces = NULL;
    _combined_annotations = NULL;
    _annotations = _type_annotations = NULL;
    _fields_annotations = _fields_type_annotations = NULL;
  }
  class AnnotationCollector {
  public:
    enum Location { _in_field, _in_method, _in_class };
    enum ID {
      _unknown = 0,
      _method_CallerSensitive,
      _method_ForceInline,
      _method_DontInline,
      _method_InjectedProfile,
      _method_LambdaForm_Compiled,
      _method_LambdaForm_Hidden,
      _sun_misc_Contended,
      _field_Stable,
      _annotation_LIMIT
    };
    const Location _location;
    int _annotations_present;
    u2 _contended_group;
    AnnotationCollector(Location location)
    : _location(location), _annotations_present(0), _contended_group(0)
    {
      assert((int)_annotation_LIMIT <= (int)sizeof(_annotations_present) * BitsPerByte, "");
    }
    ID annotation_index(ClassLoaderData* loader_data, Symbol* name);
    void set_annotation(ID id) {
      assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
      _annotations_present |= nth_bit((int)id);
    }
    void remove_annotation(ID id) {
      assert((int)id >= 0 && (int)id < (int)_annotation_LIMIT, "oob");
      _annotations_present &= ~nth_bit((int)id);
    }
    bool has_any_annotations() const { return _annotations_present != 0; }
    bool has_annotation(ID id) const { return (nth_bit((int)id) & _annotations_present) != 0; }
    void set_contended_group(u2 group) { _contended_group = group; }
    u2 contended_group() const { return _contended_group; }
    bool is_contended() const { return has_annotation(_sun_misc_Contended); }
    void set_stable(bool stable) { set_annotation(_field_Stable); }
    bool is_stable() const { return has_annotation(_field_Stable); }
  };
  class FieldAnnotationCollector: public AnnotationCollector {
    ClassLoaderData* _loader_data;
    AnnotationArray* _field_annotations;
    AnnotationArray* _field_type_annotations;
  public:
    FieldAnnotationCollector(ClassLoaderData* loader_data) :
                                 AnnotationCollector(_in_field),
                                 _loader_data(loader_data),
                                 _field_annotations(NULL),
                                 _field_type_annotations(NULL) {}
    void apply_to(FieldInfo* f);
    ~FieldAnnotationCollector();
    AnnotationArray* field_annotations()      { return _field_annotations; }
    AnnotationArray* field_type_annotations() { return _field_type_annotations; }
    void set_field_annotations(AnnotationArray* a)      { _field_annotations = a; }
    void set_field_type_annotations(AnnotationArray* a) { _field_type_annotations = a; }
  };
  class MethodAnnotationCollector: public AnnotationCollector {
  public:
    MethodAnnotationCollector() : AnnotationCollector(_in_method) { }
    void apply_to(methodHandle m);
  };
  class ClassAnnotationCollector: public AnnotationCollector {
  public:
    ClassAnnotationCollector() : AnnotationCollector(_in_class) { }
    void apply_to(instanceKlassHandle k);
  };
  enum { fixed_buffer_size = 128 };
  u_char linenumbertable_buffer[fixed_buffer_size];
  ClassFileStream* _stream;              // Actual input stream
  enum { LegalClass, LegalField, LegalMethod }; // used to verify unqualified names
  ClassFileStream* stream()                        { return _stream; }
  void set_stream(ClassFileStream* st)             { _stream = st; }
  void parse_constant_pool_entries(int length, TRAPS);
  constantPoolHandle parse_constant_pool(TRAPS);
  Array<Klass*>* parse_interfaces(int length,
                                  Handle protection_domain,
                                  Symbol* class_name,
                                  bool* has_default_methods,
                                  TRAPS);
  void record_defined_class_dependencies(instanceKlassHandle defined_klass, TRAPS);
  instanceKlassHandle parse_super_class(int super_class_index, TRAPS);
  void parse_field_attributes(u2 attributes_count,
                              bool is_static, u2 signature_index,
                              u2* constantvalue_index_addr,
                              bool* is_synthetic_addr,
                              u2* generic_signature_index_addr,
                              FieldAnnotationCollector* parsed_annotations,
                              TRAPS);
  Array<u2>* parse_fields(Symbol* class_name,
                          bool is_interface,
                          FieldAllocationCount *fac,
                          u2* java_fields_count_ptr, TRAPS);
  void print_field_layout(Symbol* name,
                          Array<u2>* fields,
                          constantPoolHandle cp,
                          int instance_size,
                          int instance_fields_start,
                          int instance_fields_end,
                          int static_fields_end);
  methodHandle parse_method(bool is_interface,
                            AccessFlags* promoted_flags,
                            TRAPS);
  Array<Method*>* parse_methods(bool is_interface,
                                AccessFlags* promoted_flags,
                                bool* has_final_method,
                                bool* declares_default_methods,
                                TRAPS);
  intArray* sort_methods(Array<Method*>* methods);
  u2* parse_exception_table(u4 code_length, u4 exception_table_length,
                            TRAPS);
  void parse_linenumber_table(
      u4 code_attribute_length, u4 code_length,
      CompressedLineNumberWriteStream** write_stream, TRAPS);
  u2* parse_localvariable_table(u4 code_length, u2 max_locals, u4 code_attribute_length,
                                u2* localvariable_table_length,
                                bool isLVTT, TRAPS);
  u2* parse_checked_exceptions(u2* checked_exceptions_length, u4 method_attribute_length,
                               TRAPS);
  void parse_type_array(u2 array_length, u4 code_length, u4* u1_index, u4* u2_index,
                        u1* u1_array, u2* u2_array, TRAPS);
  u1* parse_stackmap_table(u4 code_attribute_length, TRAPS);
  u2 parse_generic_signature_attribute(TRAPS);
  void parse_classfile_sourcefile_attribute(TRAPS);
  void parse_classfile_source_debug_extension_attribute(int length, TRAPS);
  bool check_inner_classes_circularity(const ConstantPool* cp, int length, TRAPS);
  u2   parse_classfile_inner_classes_attribute(const ConstantPool* cp,
                                               u1* inner_classes_attribute_start,
                                               bool parsed_enclosingmethod_attribute,
                                               u2 enclosing_method_class_index,
                                               u2 enclosing_method_method_index,
                                               TRAPS);
  void parse_classfile_attributes(ClassAnnotationCollector* parsed_annotations,
                                  TRAPS);
  void parse_classfile_synthetic_attribute(TRAPS);
  void parse_classfile_signature_attribute(TRAPS);
  void parse_classfile_bootstrap_methods_attribute(u4 attribute_length, TRAPS);
  AnnotationArray* assemble_annotations(u1* runtime_visible_annotations,
                                        int runtime_visible_annotations_length,
                                        u1* runtime_invisible_annotations,
                                        int runtime_invisible_annotations_length, TRAPS);
  int skip_annotation(u1* buffer, int limit, int index);
  int skip_annotation_value(u1* buffer, int limit, int index);
  void parse_annotations(u1* buffer, int limit,
                         AnnotationCollector* result,
                         TRAPS);
  unsigned int compute_oop_map_count(instanceKlassHandle super,
                                     unsigned int nonstatic_oop_count,
                                     int first_nonstatic_oop_offset);
  void fill_oop_maps(instanceKlassHandle k,
                     unsigned int nonstatic_oop_map_count,
                     int* nonstatic_oop_offsets,
                     unsigned int* nonstatic_oop_counts);
  void set_precomputed_flags(instanceKlassHandle k);
  Array<Klass*>* compute_transitive_interfaces(instanceKlassHandle super,
                                               Array<Klass*>* local_ifs, TRAPS);
  void classfile_parse_error(const char* msg, TRAPS);
  void classfile_parse_error(const char* msg, int index, TRAPS);
  void classfile_parse_error(const char* msg, const char *name, TRAPS);
  void classfile_parse_error(const char* msg, int index, const char *name, TRAPS);
  void classfile_parse_error(const char* msg, const char* name, const char* signature, TRAPS);
  inline void guarantee_property(bool b, const char* msg, TRAPS) {
    if (!b) { classfile_parse_error(msg, CHECK); }
  }
PRAGMA_DIAG_PUSH
PRAGMA_FORMAT_NONLITERAL_IGNORED
inline void assert_property(bool b, const char* msg, TRAPS) {
#ifdef ASSERT
    if (!b) {
      ResourceMark rm(THREAD);
      fatal(err_msg(msg, _class_name->as_C_string()));
    }
#endif
  }
  inline void assert_property(bool b, const char* msg, int index, TRAPS) {
#ifdef ASSERT
    if (!b) {
      ResourceMark rm(THREAD);
      fatal(err_msg(msg, index, _class_name->as_C_string()));
    }
#endif
  }
PRAGMA_DIAG_POP
  inline void check_property(bool property, const char* msg, int index, TRAPS) {
    if (_need_verify) {
      guarantee_property(property, msg, index, CHECK);
    } else {
      assert_property(property, msg, index, CHECK);
    }
  }
  inline void check_property(bool property, const char* msg, TRAPS) {
    if (_need_verify) {
      guarantee_property(property, msg, CHECK);
    } else {
      assert_property(property, msg, CHECK);
    }
  }
  inline void guarantee_property(bool b, const char* msg, int index, TRAPS) {
    if (!b) { classfile_parse_error(msg, index, CHECK); }
  }
  inline void guarantee_property(bool b, const char* msg, const char *name, TRAPS) {
    if (!b) { classfile_parse_error(msg, name, CHECK); }
  }
  inline void guarantee_property(bool b, const char* msg, int index, const char *name, TRAPS) {
    if (!b) { classfile_parse_error(msg, index, name, CHECK); }
  }
  void throwIllegalSignature(
      const char* type, Symbol* name, Symbol* sig, TRAPS);
  bool is_supported_version(u2 major, u2 minor);
  bool has_illegal_visibility(jint flags);
  void verify_constantvalue(int constantvalue_index, int signature_index, TRAPS);
  void verify_legal_utf8(const unsigned char* buffer, int length, TRAPS);
  void verify_legal_class_name(Symbol* name, TRAPS);
  void verify_legal_field_name(Symbol* name, TRAPS);
  void verify_legal_method_name(Symbol* name, TRAPS);
  void verify_legal_field_signature(Symbol* fieldname, Symbol* signature, TRAPS);
  int  verify_legal_method_signature(Symbol* methodname, Symbol* signature, TRAPS);
  void verify_legal_class_modifiers(jint flags, TRAPS);
  void verify_legal_field_modifiers(jint flags, bool is_interface, TRAPS);
  void verify_legal_method_modifiers(jint flags, bool is_interface, Symbol* name, TRAPS);
  bool verify_unqualified_name(char* name, unsigned int length, int type);
  char* skip_over_field_name(char* name, bool slash_ok, unsigned int length);
  char* skip_over_field_signature(char* signature, bool void_ok, unsigned int length, TRAPS);
  bool is_anonymous() {
    assert(EnableInvokeDynamic || _host_klass.is_null(), "");
    return _host_klass.not_null();
  }
  bool has_cp_patch_at(int index) {
    assert(EnableInvokeDynamic, "");
    assert(index >= 0, "oob");
    return (_cp_patches != NULL
            && index < _cp_patches->length()
            && _cp_patches->adr_at(index)->not_null());
  }
  Handle cp_patch_at(int index) {
    assert(has_cp_patch_at(index), "oob");
    return _cp_patches->at(index);
  }
  Handle clear_cp_patch_at(int index) {
    Handle patch = cp_patch_at(index);
    _cp_patches->at_put(index, Handle());
    assert(!has_cp_patch_at(index), "");
    return patch;
  }
  void patch_constant_pool(constantPoolHandle cp, int index, Handle patch, TRAPS);
  bool valid_klass_reference_at(int index) {
    return _cp->is_within_bounds(index) &&
         (EnableInvokeDynamic
            ? _cp->tag_at(index).is_klass_or_reference()
            : _cp->tag_at(index).is_klass_reference());
  }
  bool valid_symbol_at(int cpool_index) {
    return (_cp->is_within_bounds(cpool_index) &&
            _cp->tag_at(cpool_index).is_utf8());
  }
  void copy_localvariable_table(ConstMethod* cm, int lvt_cnt,
                                u2* localvariable_table_length,
                                u2** localvariable_table_start,
                                int lvtt_cnt,
                                u2* localvariable_type_table_length,
                                u2** localvariable_type_table_start,
                                TRAPS);
  void copy_method_annotations(ConstMethod* cm,
                               u1* runtime_visible_annotations,
                               int runtime_visible_annotations_length,
                               u1* runtime_invisible_annotations,
                               int runtime_invisible_annotations_length,
                               u1* runtime_visible_parameter_annotations,
                               int runtime_visible_parameter_annotations_length,
                               u1* runtime_invisible_parameter_annotations,
                               int runtime_invisible_parameter_annotations_length,
                               u1* runtime_visible_type_annotations,
                               int runtime_visible_type_annotations_length,
                               u1* runtime_invisible_type_annotations,
                               int runtime_invisible_type_annotations_length,
                               u1* annotation_default,
                               int annotation_default_length,
                               TRAPS);
  void layout_fields(Handle class_loader, FieldAllocationCount* fac,
                     ClassAnnotationCollector* parsed_annotations,
                     FieldLayoutInfo* info, TRAPS);
 public:
  ClassFileParser(ClassFileStream* st) { set_stream(st); }
  ~ClassFileParser();
  instanceKlassHandle parseClassFile(Symbol* name,
                                     ClassLoaderData* loader_data,
                                     Handle protection_domain,
                                     TempNewSymbol& parsed_name,
                                     bool verify,
                                     TRAPS) {
    KlassHandle no_host_klass;
    return parseClassFile(name, loader_data, protection_domain, no_host_klass, NULL, parsed_name, verify, THREAD);
  }
  instanceKlassHandle parseClassFile(Symbol* name,
                                     ClassLoaderData* loader_data,
                                     Handle protection_domain,
                                     KlassHandle host_klass,
                                     GrowableArray<Handle>* cp_patches,
                                     TempNewSymbol& parsed_name,
                                     bool verify,
                                     TRAPS);
  static void check_super_class_access(instanceKlassHandle this_klass, TRAPS);
  static void check_super_interface_access(instanceKlassHandle this_klass, TRAPS);
  static void check_final_method_override(instanceKlassHandle this_klass, TRAPS);
  static void check_illegal_static_method(instanceKlassHandle this_klass, TRAPS);
  u2 this_class_index() const { return _this_class_index; }
#if INCLUDE_JFR
  ClassFileStream* clone_stream() const;
  void set_klass_to_deallocate(InstanceKlass* klass);
#endif // INCLUDE_JFR
};
#endif // SHARE_VM_CLASSFILE_CLASSFILEPARSER_HPP
C:\hotspot-69087d08d473\src\share\vm/classfile/classFileStream.cpp
#include "precompiled.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/vmSymbols.hpp"
void ClassFileStream::truncated_file_error(TRAPS) {
  THROW_MSG(vmSymbols::java_lang_ClassFormatError(), "Truncated class file");
}
ClassFileStream::ClassFileStream(u1* buffer, int length, const char* source, bool need_verify) {
  _buffer_start = buffer;
  _buffer_end   = buffer + length;
  _current      = buffer;
  _source       = source;
  _need_verify  = need_verify;
}
u1 ClassFileStream::get_u1(TRAPS) {
  if (_need_verify) {
    guarantee_more(1, CHECK_0);
  } else {
    assert(1 <= _buffer_end - _current, "buffer overflow");
  }
  return *_current++;
}
u2 ClassFileStream::get_u2(TRAPS) {
  if (_need_verify) {
    guarantee_more(2, CHECK_0);
  } else {
    assert(2 <= _buffer_end - _current, "buffer overflow");
  }
  u1* tmp = _current;
  _current += 2;
  return Bytes::get_Java_u2(tmp);
}
u4 ClassFileStream::get_u4(TRAPS) {
  if (_need_verify) {
    guarantee_more(4, CHECK_0);
  } else {
    assert(4 <= _buffer_end - _current, "buffer overflow");
  }
  u1* tmp = _current;
  _current += 4;
  return Bytes::get_Java_u4(tmp);
}
u8 ClassFileStream::get_u8(TRAPS) {
  if (_need_verify) {
    guarantee_more(8, CHECK_0);
  } else {
    assert(8 <= _buffer_end - _current, "buffer overflow");
  }
  u1* tmp = _current;
  _current += 8;
  return Bytes::get_Java_u8(tmp);
}
void ClassFileStream::skip_u1(int length, TRAPS) {
  if (_need_verify) {
    guarantee_more(length, CHECK);
  }
  _current += length;
}
void ClassFileStream::skip_u2(int length, TRAPS) {
  if (_need_verify) {
    guarantee_more(length * 2, CHECK);
  }
  _current += length * 2;
}
void ClassFileStream::skip_u4(int length, TRAPS) {
  if (_need_verify) {
    guarantee_more(length * 4, CHECK);
  }
  _current += length * 4;
}
#if INCLUDE_JFR
u1* ClassFileStream::clone_buffer() const {
  u1* const new_buffer_start = NEW_RESOURCE_ARRAY(u1, length());
  memcpy(new_buffer_start, _buffer_start, length());
  return new_buffer_start;
}
const char* const ClassFileStream::clone_source() const {
  const char* const src = source();
  char* source_copy = NULL;
  if (src != NULL) {
    size_t source_len = strlen(src);
    source_copy = NEW_RESOURCE_ARRAY(char, source_len + 1);
    strncpy(source_copy, src, source_len + 1);
  }
  return source_copy;
}
ClassFileStream* ClassFileStream::clone() const {
  u1* const new_buffer_start = clone_buffer();
  return new ClassFileStream(new_buffer_start,
                             length(),
                             clone_source(),
                             need_verify());
}
#endif // INCLUDE_JFR
C:\hotspot-69087d08d473\src\share\vm/classfile/classFileStream.hpp
#ifndef SHARE_VM_CLASSFILE_CLASSFILESTREAM_HPP
#define SHARE_VM_CLASSFILE_CLASSFILESTREAM_HPP
#include "utilities/top.hpp"
#ifdef TARGET_ARCH_x86
# include "bytes_x86.hpp"
#endif
#ifdef TARGET_ARCH_aarch64
# include "bytes_aarch64.hpp"
#endif
#ifdef TARGET_ARCH_sparc
# include "bytes_sparc.hpp"
#endif
#ifdef TARGET_ARCH_zero
# include "bytes_zero.hpp"
#endif
#ifdef TARGET_ARCH_arm
# include "bytes_arm.hpp"
#endif
#ifdef TARGET_ARCH_ppc
# include "bytes_ppc.hpp"
#endif
class ClassFileStream: public ResourceObj {
 private:
  u1*   _buffer_start; // Buffer bottom
  u1*   _buffer_end;   // Buffer top (one past last element)
  u1*   _current;      // Current buffer position
  const char* _source; // Source of stream (directory name, ZIP/JAR archive name)
  bool  _need_verify;  // True if verification is on for the class file
  void truncated_file_error(TRAPS);
#if INCLUDE_JFR
  u1* clone_buffer() const;
  const char* const clone_source() const;
#endif
 public:
  ClassFileStream(u1* buffer, int length, const char* source, bool need_verify = false);
  u1* buffer() const           { return _buffer_start; }
  int length() const           { return _buffer_end - _buffer_start; }
  u1* current() const          { return _current; }
  void set_current(u1* pos)    { _current = pos; }
  juint current_offset() const {
    return (juint)(_current - _buffer_start);
  }
  const char* source() const   { return _source; }
  void set_verify(bool flag)   { _need_verify = flag; }
  void check_truncated_file(bool b, TRAPS) {
    if (b) {
      truncated_file_error(THREAD);
    }
  }
  void guarantee_more(int size, TRAPS) {
    size_t remaining = (size_t)(_buffer_end - _current);
    unsigned int usize = (unsigned int)size;
    check_truncated_file(usize > remaining, CHECK);
  }
  u1 get_u1(TRAPS);
  u1 get_u1_fast() {
    return *_current++;
  }
  u2 get_u2(TRAPS);
  u2 get_u2_fast() {
    u2 res = Bytes::get_Java_u2(_current);
    _current += 2;
    return res;
  }
  u4 get_u4(TRAPS);
  u4 get_u4_fast() {
    u4 res = Bytes::get_Java_u4(_current);
    _current += 4;
    return res;
  }
  u8 get_u8(TRAPS);
  u8 get_u8_fast() {
    u8 res = Bytes::get_Java_u8(_current);
    _current += 8;
    return res;
  }
  u1* get_u1_buffer() {
    return _current;
  }
  u2* get_u2_buffer() {
    return (u2*) _current;
  }
  void skip_u1(int length, TRAPS);
  void skip_u1_fast(int length) {
    _current += length;
  }
  void skip_u2(int length, TRAPS);
  void skip_u2_fast(int length) {
    _current += 2 * length;
  }
  void skip_u4(int length, TRAPS);
  void skip_u4_fast(int length) {
    _current += 4 * length;
  }
  bool at_eos() const          { return _current == _buffer_end; }
#if INCLUDE_JFR
  ClassFileStream* clone() const;
  bool need_verify() const { return _need_verify; }
#endif
};
#endif // SHARE_VM_CLASSFILE_CLASSFILESTREAM_HPP
C:\hotspot-69087d08d473\src\share\vm/classfile/classLoader.cpp
#include "precompiled.hpp"
#include "classfile/classFileParser.hpp"
#include "classfile/classFileStream.hpp"
#include "classfile/classLoader.hpp"
#include "classfile/classLoaderExt.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp"
#if INCLUDE_CDS
#include "classfile/sharedPathsMiscInfo.hpp"
#include "classfile/sharedClassUtil.hpp"
#endif
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "compiler/compileBroker.hpp"
#include "gc_interface/collectedHeap.inline.hpp"
#include "interpreter/bytecodeStream.hpp"
#include "interpreter/oopMapCache.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/filemap.hpp"
#include "memory/generation.hpp"
#include "memory/oopFactory.hpp"
#include "memory/universe.inline.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceRefKlass.hpp"
#include "oops/oop.inline.hpp"
#include "oops/symbol.hpp"
#include "prims/jvm_misc.hpp"
#include "runtime/arguments.hpp"
#include "runtime/compilationPolicy.hpp"
#include "runtime/fprofiler.hpp"
#include "runtime/handles.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/init.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/threadCritical.hpp"
#include "runtime/timer.hpp"
#include "services/management.hpp"
#include "services/threadService.hpp"
#include "utilities/events.hpp"
#include "utilities/hashtable.hpp"
#include "utilities/hashtable.inline.hpp"
#ifdef TARGET_OS_FAMILY_linux
# include "os_linux.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_solaris
# include "os_solaris.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_windows
# include "os_windows.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_aix
# include "os_aix.inline.hpp"
#endif
#ifdef TARGET_OS_FAMILY_bsd
# include "os_bsd.inline.hpp"
#endif
typedef void * * (JNICALL *ZipOpen_t)(const char *name, char **pmsg);
typedef void (JNICALL *ZipClose_t)(jzfile *zip);
typedef jzentry* (JNICALL *FindEntry_t)(jzfile *zip, const char *name, jint *sizeP, jint *nameLen);
typedef jboolean (JNICALL *ReadEntry_t)(jzfile *zip, jzentry *entry, unsigned char *buf, char *namebuf);
typedef jboolean (JNICALL *ReadMappedEntry_t)(jzfile *zip, jzentry *entry, unsigned char **buf, char *namebuf);
typedef jzentry* (JNICALL *GetNextEntry_t)(jzfile *zip, jint n);
typedef jint     (JNICALL *Crc32_t)(jint crc, const jbyte *buf, jint len);
static ZipOpen_t         ZipOpen            = NULL;
static ZipClose_t        ZipClose           = NULL;
static FindEntry_t       FindEntry          = NULL;
static ReadEntry_t       ReadEntry          = NULL;
static ReadMappedEntry_t ReadMappedEntry    = NULL;
static GetNextEntry_t    GetNextEntry       = NULL;
static canonicalize_fn_t CanonicalizeEntry  = NULL;
static Crc32_t           Crc32              = NULL;
PerfCounter*    ClassLoader::_perf_accumulated_time = NULL;
PerfCounter*    ClassLoader::_perf_classes_inited = NULL;
PerfCounter*    ClassLoader::_perf_class_init_time = NULL;
PerfCounter*    ClassLoader::_perf_class_init_selftime = NULL;
PerfCounter*    ClassLoader::_perf_classes_verified = NULL;
PerfCounter*    ClassLoader::_perf_class_verify_time = NULL;
PerfCounter*    ClassLoader::_perf_class_verify_selftime = NULL;
PerfCounter*    ClassLoader::_perf_classes_linked = NULL;
PerfCounter*    ClassLoader::_perf_class_link_time = NULL;
PerfCounter*    ClassLoader::_perf_class_link_selftime = NULL;
PerfCounter*    ClassLoader::_perf_class_parse_time = NULL;
PerfCounter*    ClassLoader::_perf_class_parse_selftime = NULL;
PerfCounter*    ClassLoader::_perf_sys_class_lookup_time = NULL;
PerfCounter*    ClassLoader::_perf_shared_classload_time = NULL;
PerfCounter*    ClassLoader::_perf_sys_classload_time = NULL;
PerfCounter*    ClassLoader::_perf_app_classload_time = NULL;
PerfCounter*    ClassLoader::_perf_app_classload_selftime = NULL;
PerfCounter*    ClassLoader::_perf_app_classload_count = NULL;
PerfCounter*    ClassLoader::_perf_define_appclasses = NULL;
PerfCounter*    ClassLoader::_perf_define_appclass_time = NULL;
PerfCounter*    ClassLoader::_perf_define_appclass_selftime = NULL;
PerfCounter*    ClassLoader::_perf_app_classfile_bytes_read = NULL;
PerfCounter*    ClassLoader::_perf_sys_classfile_bytes_read = NULL;
PerfCounter*    ClassLoader::_sync_systemLoaderLockContentionRate = NULL;
PerfCounter*    ClassLoader::_sync_nonSystemLoaderLockContentionRate = NULL;
PerfCounter*    ClassLoader::_sync_JVMFindLoadedClassLockFreeCounter = NULL;
PerfCounter*    ClassLoader::_sync_JVMDefineClassLockFreeCounter = NULL;
PerfCounter*    ClassLoader::_sync_JNIDefineClassLockFreeCounter = NULL;
PerfCounter*    ClassLoader::_unsafe_defineClassCallCounter = NULL;
PerfCounter*    ClassLoader::_isUnsyncloadClass = NULL;
PerfCounter*    ClassLoader::_load_instance_class_failCounter = NULL;
ClassPathEntry* ClassLoader::_first_entry         = NULL;
ClassPathEntry* ClassLoader::_last_entry          = NULL;
int             ClassLoader::_num_entries         = 0;
PackageHashtable* ClassLoader::_package_hash_table = NULL;
#if INCLUDE_CDS
SharedPathsMiscInfo* ClassLoader::_shared_paths_misc_info = NULL;
#endif
bool string_starts_with(const char* str, const char* str_to_find) {
  size_t str_len = strlen(str);
  size_t str_to_find_len = strlen(str_to_find);
  if (str_to_find_len > str_len) {
    return false;
  }
  return (strncmp(str, str_to_find, str_to_find_len) == 0);
}
bool string_ends_with(const char* str, const char* str_to_find) {
  size_t str_len = strlen(str);
  size_t str_to_find_len = strlen(str_to_find);
  if (str_to_find_len > str_len) {
    return false;
  }
  return (strncmp(str + (str_len - str_to_find_len), str_to_find, str_to_find_len) == 0);
}
const char* ClassLoader::package_from_name(const char* const class_name, bool* bad_class_name) {
  if (class_name == NULL) {
    if (bad_class_name != NULL) {
    }
    return NULL;
  }
  if (bad_class_name != NULL) {
  }
  const char* const last_slash = strrchr(class_name, '/');
  if (last_slash == NULL) {
    return NULL;
  }
  char* class_name_ptr = (char*) class_name;
  if (*class_name_ptr == '[') {
    do {
      class_name_ptr++;
    } while (*class_name_ptr == '[');
    if (*class_name_ptr == 'L') {
      if (bad_class_name != NULL) {
      }
      return NULL;
    }
  }
  int length = last_slash - class_name_ptr;
  if (length <= 0) {
    if (bad_class_name != NULL) {
    }
    return NULL;
  }
  char* pkg_name = NEW_RESOURCE_ARRAY(char, length + 1);
  strncpy(pkg_name, class_name_ptr, length);
  return (const char *)pkg_name;
}
MetaIndex::MetaIndex(char** meta_package_names, int num_meta_package_names) {
  if (num_meta_package_names == 0) {
    _meta_package_names = NULL;
    _num_meta_package_names = 0;
  } else {
    _meta_package_names = NEW_C_HEAP_ARRAY(char*, num_meta_package_names, mtClass);
    _num_meta_package_names = num_meta_package_names;
    memcpy(_meta_package_names, meta_package_names, num_meta_package_names * sizeof(char*));
  }
}
MetaIndex::~MetaIndex() {
  FREE_C_HEAP_ARRAY(char*, _meta_package_names, mtClass);
}
bool MetaIndex::may_contain(const char* class_name) {
  if ( _num_meta_package_names == 0) {
    return false;
  }
  size_t class_name_len = strlen(class_name);
  for (int i = 0; i < _num_meta_package_names; i++) {
    char* pkg = _meta_package_names[i];
    size_t pkg_len = strlen(pkg);
    size_t min_len = MIN2(class_name_len, pkg_len);
    if (!strncmp(class_name, pkg, min_len)) {
      return true;
    }
  }
  return false;
}
ClassPathEntry::ClassPathEntry() {
  set_next(NULL);
}
bool ClassPathEntry::is_lazy() {
  return false;
}
ClassPathDirEntry::ClassPathDirEntry(const char* dir) : ClassPathEntry() {
  char* copy = NEW_C_HEAP_ARRAY(char, strlen(dir)+1, mtClass);
  strcpy(copy, dir);
  _dir = copy;
}
ClassFileStream* ClassPathDirEntry::open_stream(const char* name, TRAPS) {
  char path[JVM_MAXPATHLEN];
  if (jio_snprintf(path, sizeof(path), "%s%s%s", _dir, os::file_separator(), name) == -1) {
    return NULL;
  }
  struct stat st;
  if (os::stat(path, &st) == 0) {
#if INCLUDE_CDS
    if (DumpSharedSpaces) {
      ShouldNotReachHere();
    }
#endif
    int file_handle = os::open(path, 0, 0);
    if (file_handle != -1) {
      u1* buffer = NEW_RESOURCE_ARRAY(u1, st.st_size);
      size_t num_read = os::read(file_handle, (char*) buffer, st.st_size);
      os::close(file_handle);
      if (num_read == (size_t)st.st_size) {
        if (UsePerfData) {
          ClassLoader::perf_sys_classfile_bytes_read()->inc(num_read);
        }
        return new ClassFileStream(buffer, st.st_size, _dir);    // Resource allocated
      }
    }
  }
  return NULL;
}
ClassPathZipEntry::ClassPathZipEntry(jzfile* zip, const char* zip_name) : ClassPathEntry() {
  _zip = zip;
  char *copy = NEW_C_HEAP_ARRAY(char, strlen(zip_name)+1, mtClass);
  strcpy(copy, zip_name);
  _zip_name = copy;
}
ClassPathZipEntry::~ClassPathZipEntry() {
  if (ZipClose != NULL) {
    (*ZipClose)(_zip);
  }
  FREE_C_HEAP_ARRAY(char, _zip_name, mtClass);
}
u1* ClassPathZipEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) {
  JavaThread* thread = JavaThread::current();
  ThreadToNativeFromVM ttn(thread);
  jint name_len;
  jzentry* entry = (*FindEntry)(_zip, name, filesize, &name_len);
  if (entry == NULL) return NULL;
  u1* buffer;
  char name_buf[128];
  char* filename;
  if (name_len < 128) {
    filename = name_buf;
  } else {
    filename = NEW_RESOURCE_ARRAY(char, name_len + 1);
  }
  if (ReadMappedEntry == NULL ||
      !(*ReadMappedEntry)(_zip, entry, &buffer, filename)) {
      int size = (*filesize) + ((nul_terminate) ? 1 : 0);
      buffer = NEW_RESOURCE_ARRAY(u1, size);
      if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL;
  }
  if (nul_terminate) {
    buffer[*filesize] = 0;
  }
  return buffer;
}
ClassFileStream* ClassPathZipEntry::open_stream(const char* name, TRAPS) {
  jint filesize;
  u1* buffer = open_entry(name, &filesize, false, CHECK_NULL);
  if (buffer == NULL) {
    return NULL;
  }
  if (UsePerfData) {
    ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize);
  }
  return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated
}
void ClassPathZipEntry::contents_do(void f(const char* name, void* context), void* context) {
  JavaThread* thread = JavaThread::current();
  HandleMark  handle_mark(thread);
  ThreadToNativeFromVM ttn(thread);
  for (int n = 0; ; n++) {
    jzentry * ze = ((*GetNextEntry)(_zip, n));
    if (ze == NULL) break;
    (*f)(ze->name, context);
  }
}
LazyClassPathEntry::LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception) : ClassPathEntry() {
  _path = strdup(path);
  _st = *st;
  _meta_index = NULL;
  _resolved_entry = NULL;
  _has_error = false;
  _throw_exception = throw_exception;
}
bool LazyClassPathEntry::is_jar_file() {
  return ((_st.st_mode & S_IFREG) == S_IFREG);
}
ClassPathEntry* LazyClassPathEntry::resolve_entry(TRAPS) {
  if (_resolved_entry != NULL) {
    return (ClassPathEntry*) _resolved_entry;
  }
  ClassPathEntry* new_entry = NULL;
  new_entry = ClassLoader::create_class_path_entry(_path, &_st, false, _throw_exception, CHECK_NULL);
  if (!_throw_exception && new_entry == NULL) {
    assert(!HAS_PENDING_EXCEPTION, "must be");
    return NULL;
  }
  {
    ThreadCritical tc;
    if (_resolved_entry == NULL) {
      _resolved_entry = new_entry;
      return new_entry;
    }
  }
  assert(_resolved_entry != NULL, "bug in MT-safe resolution logic");
  delete new_entry;
  return (ClassPathEntry*) _resolved_entry;
}
ClassFileStream* LazyClassPathEntry::open_stream(const char* name, TRAPS) {
  if (_meta_index != NULL &&
      !_meta_index->may_contain(name)) {
    return NULL;
  }
  if (_has_error) {
    return NULL;
  }
  ClassPathEntry* cpe = resolve_entry(THREAD);
  if (cpe == NULL) {
    _has_error = true;
    return NULL;
  } else {
    return cpe->open_stream(name, THREAD);
  }
}
bool LazyClassPathEntry::is_lazy() {
  return true;
}
u1* LazyClassPathEntry::open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS) {
  if (_has_error) {
    return NULL;
  }
  ClassPathEntry* cpe = resolve_entry(THREAD);
  if (cpe == NULL) {
    _has_error = true;
    return NULL;
  } else if (cpe->is_jar_file()) {
    return ((ClassPathZipEntry*)cpe)->open_entry(name, filesize, nul_terminate,THREAD);
  } else {
    ShouldNotReachHere();
    return NULL;
  }
}
static void print_meta_index(LazyClassPathEntry* entry,
                             GrowableArray<char*>& meta_packages) {
  tty->print("[Meta index for %s=", entry->name());
  for (int i = 0; i < meta_packages.length(); i++) {
    if (i > 0) tty->print(" ");
    tty->print("%s", meta_packages.at(i));
  }
  tty->print_cr("]");
}
#if INCLUDE_CDS
void ClassLoader::exit_with_path_failure(const char* error, const char* message) {
  assert(DumpSharedSpaces, "only called at dump time");
  tty->print_cr("Hint: enable -XX:+TraceClassPaths to diagnose the failure");
  vm_exit_during_initialization(error, message);
}
#endif
void ClassLoader::trace_class_path(outputStream* out, const char* msg, const char* name) {
  if (!TraceClassPaths) {
    return;
  }
  if (msg) {
    out->print("%s", msg);
  }
  if (name) {
    if (strlen(name) < 256) {
      out->print("%s", name);
    } else {
      while (name[0] != '\0') {
        out->print("%c", name[0]);
        name++;
      }
    }
  }
  if (msg && msg[0] == '[') {
    out->print_cr("]");
  } else {
    out->cr();
  }
}
void ClassLoader::setup_bootstrap_meta_index() {
  const char* meta_index_path = Arguments::get_meta_index_path();
  const char* meta_index_dir  = Arguments::get_meta_index_dir();
  setup_meta_index(meta_index_path, meta_index_dir, 0);
}
void ClassLoader::setup_meta_index(const char* meta_index_path, const char* meta_index_dir, int start_index) {
  const char* known_version = "% VERSION 2";
  FILE* file = fopen(meta_index_path, "r");
  int line_no = 0;
#if INCLUDE_CDS
  if (DumpSharedSpaces) {
    if (file != NULL) {
      _shared_paths_misc_info->add_required_file(meta_index_path);
    } else {
      _shared_paths_misc_info->add_nonexist_path(meta_index_path);
    }
  }
#endif
  if (file != NULL) {
    ResourceMark rm;
    LazyClassPathEntry* cur_entry = NULL;
    GrowableArray<char*> boot_class_path_packages(10);
    char package_name[256];
    bool skipCurrentJar = false;
    while (fgets(package_name, sizeof(package_name), file) != NULL) {
      ++line_no;
      package_name[strlen(package_name) - 1] = '\0';
      switch(package_name[0]) {
        case '%':
        {
          if ((line_no == 1) && (strcmp(package_name, known_version) != 0)) {
            if (TraceClassLoading && Verbose) {
              tty->print("[Unsupported meta index version]");
            }
            fclose(file);
            return;
          }
        }
        case '#':
        case '!':
        case '@':
        {
          if ((cur_entry != NULL) &&
              (boot_class_path_packages.length() > 0)) {
            if ((TraceClassLoading || TraceClassPaths) && Verbose) {
              print_meta_index(cur_entry, boot_class_path_packages);
            }
            MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0),
                                             boot_class_path_packages.length());
            cur_entry->set_meta_index(index);
          }
          cur_entry = NULL;
          boot_class_path_packages.clear();
          int count = 0;
          for (ClassPathEntry* entry = _first_entry; entry != NULL; entry = entry->next(), count++) {
            if (count >= start_index &&
                entry->is_lazy() &&
                string_starts_with(entry->name(), meta_index_dir) &&
                string_ends_with(entry->name(), &package_name[2])) {
              cur_entry = (LazyClassPathEntry*) entry;
              break;
            }
          }
          if (package_name[0] == '@') {
            if (cur_entry != NULL) {
              cur_entry->set_meta_index(new MetaIndex(NULL, 0));
            }
            cur_entry = NULL;
            skipCurrentJar = true;
          } else {
            skipCurrentJar = false;
          }
          break;
        }
        default:
        {
          if (!skipCurrentJar && cur_entry != NULL) {
            char* new_name = strdup(package_name);
            boot_class_path_packages.append(new_name);
          }
        }
      }
    }
    if ((cur_entry != NULL) &&
        (boot_class_path_packages.length() > 0)) {
      if ((TraceClassLoading || TraceClassPaths) && Verbose) {
        print_meta_index(cur_entry, boot_class_path_packages);
      }
      MetaIndex* index = new MetaIndex(boot_class_path_packages.adr_at(0),
                                       boot_class_path_packages.length());
      cur_entry->set_meta_index(index);
    }
    fclose(file);
  }
}
#if INCLUDE_CDS
void ClassLoader::check_shared_classpath(const char *path) {
  if (strcmp(path, "") == 0) {
    exit_with_path_failure("Cannot have empty path in archived classpaths", NULL);
  }
  struct stat st;
  if (os::stat(path, &st) == 0) {
    if ((st.st_mode & S_IFREG) != S_IFREG) { // is directory
      if (!os::dir_is_empty(path)) {
        tty->print_cr("Error: non-empty directory '%s'", path);
        exit_with_path_failure("CDS allows only empty directories in archived classpaths", NULL);
      }
    }
  }
}
#endif
void ClassLoader::setup_bootstrap_search_path() {
  assert(_first_entry == NULL, "should not setup bootstrap class search path twice");
  const char* sys_class_path = Arguments::get_sysclasspath();
  if (PrintSharedArchiveAndExit) {
  } else {
    trace_class_path(tty, "[Bootstrap loader class path=", sys_class_path);
  }
#if INCLUDE_CDS
  if (DumpSharedSpaces) {
    _shared_paths_misc_info->add_boot_classpath(sys_class_path);
  }
#endif
  setup_search_path(sys_class_path);
}
#if INCLUDE_CDS
int ClassLoader::get_shared_paths_misc_info_size() {
  return _shared_paths_misc_info->get_used_bytes();
}
void* ClassLoader::get_shared_paths_misc_info() {
  return _shared_paths_misc_info->buffer();
}
bool ClassLoader::check_shared_paths_misc_info(void *buf, int size) {
  SharedPathsMiscInfo* checker = SharedClassUtil::allocate_shared_paths_misc_info((char*)buf, size);
  bool result = checker->check();
  delete checker;
  return result;
}
#endif
void ClassLoader::setup_search_path(const char *class_path, bool canonicalize) {
  int offset = 0;
  int len = (int)strlen(class_path);
  int end = 0;
  for (int start = 0; start < len; start = end) {
    while (class_path[end] && class_path[end] != os::path_separator()[0]) {
      end++;
    }
    EXCEPTION_MARK;
    ResourceMark rm(THREAD);
    char* path = NEW_RESOURCE_ARRAY(char, end - start + 1);
    strncpy(path, &class_path[start], end - start);
    path[end - start] = '\0';
    if (canonicalize) {
      char* canonical_path = NEW_RESOURCE_ARRAY(char, JVM_MAXPATHLEN + 1);
      if (get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
        path = canonical_path;
      }
    }
    update_class_path_entry_list(path, /*check_for_duplicates=*/canonicalize);
#if INCLUDE_CDS
    if (DumpSharedSpaces) {
      check_shared_classpath(path);
    }
#endif
    while (class_path[end] == os::path_separator()[0]) {
      end++;
    }
  }
}
ClassPathEntry* ClassLoader::create_class_path_entry(const char *path, const struct stat* st,
                                                     bool lazy, bool throw_exception, TRAPS) {
  JavaThread* thread = JavaThread::current();
  if (lazy) {
    return new LazyClassPathEntry(path, st, throw_exception);
  }
  ClassPathEntry* new_entry = NULL;
  if ((st->st_mode & S_IFREG) == S_IFREG) {
    char canonical_path[JVM_MAXPATHLEN];
    if (!get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
      if (throw_exception) {
        THROW_MSG_(vmSymbols::java_io_IOException(), "Bad pathname", NULL);
      } else {
        return NULL;
      }
    }
    char* error_msg = NULL;
    jzfile* zip;
    {
      ThreadToNativeFromVM ttn(thread);
      HandleMark hm(thread);
      zip = (*ZipOpen)(canonical_path, &error_msg);
    }
    if (zip != NULL && error_msg == NULL) {
      new_entry = new ClassPathZipEntry(zip, path);
      if (TraceClassLoading || TraceClassPaths) {
        tty->print_cr("[Opened %s]", path);
      }
    } else {
      ResourceMark rm(thread);
      char *msg;
      if (error_msg == NULL) {
        msg = NEW_RESOURCE_ARRAY(char, strlen(path) + 128); ;
        jio_snprintf(msg, strlen(path) + 127, "error in opening JAR file %s", path);
      } else {
        int len = (int)(strlen(path) + strlen(error_msg) + 128);
        msg = NEW_RESOURCE_ARRAY(char, len); ;
        jio_snprintf(msg, len - 1, "error in opening JAR file <%s> %s", error_msg, path);
      }
      if (throw_exception) {
        THROW_MSG_(vmSymbols::java_lang_ClassNotFoundException(), msg, NULL);
      } else {
        return NULL;
      }
    }
  } else {
    new_entry = new ClassPathDirEntry(path);
    if (TraceClassLoading || TraceClassPaths) {
      tty->print_cr("[Path %s]", path);
    }
  }
  return new_entry;
}
ClassPathZipEntry* ClassLoader::create_class_path_zip_entry(const char *path) {
  struct stat st;
  if (os::stat(path, &st) == 0) {
    if ((st.st_mode & S_IFREG) == S_IFREG) {
      char canonical_path[JVM_MAXPATHLEN];
      if (get_canonical_path(path, canonical_path, JVM_MAXPATHLEN)) {
        char* error_msg = NULL;
        jzfile* zip;
        {
          JavaThread* thread = JavaThread::current();
          ThreadToNativeFromVM ttn(thread);
          HandleMark hm(thread);
          zip = (*ZipOpen)(canonical_path, &error_msg);
        }
        if (zip != NULL && error_msg == NULL) {
          return new ClassPathZipEntry(zip, canonical_path);
        }
      }
    }
  }
  return NULL;
}
bool ClassLoader::contains_entry(ClassPathEntry *entry) {
  ClassPathEntry* e = _first_entry;
  while (e != NULL) {
    if (strcmp(entry->name(), e->name()) == 0) {
      return true;
    }
    e = e->next();
  }
  return false;
}
void ClassLoader::add_to_list(ClassPathEntry *new_entry) {
  if (new_entry != NULL) {
    if (_last_entry == NULL) {
      _first_entry = _last_entry = new_entry;
    } else {
      _last_entry->set_next(new_entry);
      _last_entry = new_entry;
    }
  }
  _num_entries ++;
}
bool ClassLoader::update_class_path_entry_list(const char *path,
                                               bool check_for_duplicates,
                                               bool throw_exception) {
  struct stat st;
  if (os::stat(path, &st) == 0) {
    ClassPathEntry* new_entry = NULL;
    Thread* THREAD = Thread::current();
    new_entry = create_class_path_entry(path, &st, LazyBootClassLoader, throw_exception, CHECK_(false));
    if (new_entry == NULL) {
      return false;
    }
    if (!check_for_duplicates || !contains_entry(new_entry)) {
      ClassLoaderExt::add_class_path_entry(path, check_for_duplicates, new_entry);
    }
    return true;
  } else {
#if INCLUDE_CDS
    if (DumpSharedSpaces) {
      _shared_paths_misc_info->add_nonexist_path(path);
    }
#endif
    return false;
  }
}
void ClassLoader::print_bootclasspath() {
  ClassPathEntry* e = _first_entry;
  tty->print("[bootclasspath= ");
  while (e != NULL) {
    tty->print("%s ;", e->name());
    e = e->next();
  }
  tty->print_cr("]");
}
void ClassLoader::load_zip_library() {
  assert(ZipOpen == NULL, "should not load zip library twice");
  os::native_java_library();
  char path[JVM_MAXPATHLEN];
  char ebuf[1024];
  void* handle = NULL;
  if (os::dll_build_name(path, sizeof(path), Arguments::get_dll_dir(), "zip")) {
    handle = os::dll_load(path, ebuf, sizeof ebuf);
  }
  if (handle == NULL) {
    vm_exit_during_initialization("Unable to load ZIP library", path);
  }
  ZipOpen      = CAST_TO_FN_PTR(ZipOpen_t, os::dll_lookup(handle, "ZIP_Open"));
  ZipClose     = CAST_TO_FN_PTR(ZipClose_t, os::dll_lookup(handle, "ZIP_Close"));
  FindEntry    = CAST_TO_FN_PTR(FindEntry_t, os::dll_lookup(handle, "ZIP_FindEntry"));
  ReadEntry    = CAST_TO_FN_PTR(ReadEntry_t, os::dll_lookup(handle, "ZIP_ReadEntry"));
  ReadMappedEntry = CAST_TO_FN_PTR(ReadMappedEntry_t, os::dll_lookup(handle, "ZIP_ReadMappedEntry"));
  GetNextEntry = CAST_TO_FN_PTR(GetNextEntry_t, os::dll_lookup(handle, "ZIP_GetNextEntry"));
  Crc32        = CAST_TO_FN_PTR(Crc32_t, os::dll_lookup(handle, "ZIP_CRC32"));
  if (ZipOpen == NULL || FindEntry == NULL || ReadEntry == NULL ||
      GetNextEntry == NULL || Crc32 == NULL) {
    vm_exit_during_initialization("Corrupted ZIP library", path);
  }
  void *javalib_handle = os::native_java_library();
  CanonicalizeEntry = CAST_TO_FN_PTR(canonicalize_fn_t, os::dll_lookup(javalib_handle, "Canonicalize"));
}
int ClassLoader::crc32(int crc, const char* buf, int len) {
  assert(Crc32 != NULL, "ZIP_CRC32 is not found");
  return (*Crc32)(crc, (const jbyte*)buf, len);
}
class PackageInfo: public BasicHashtableEntry<mtClass> {
public:
  const char* _pkgname;       // Package name
  int _classpath_index;       // Index of directory or JAR file loaded from
  PackageInfo* next() {
    return (PackageInfo*)BasicHashtableEntry<mtClass>::next();
  }
  const char* pkgname()           { return _pkgname; }
  void set_pkgname(char* pkgname) { _pkgname = pkgname; }
  const char* filename() {
    return ClassLoader::classpath_entry(_classpath_index)->name();
  }
  void set_index(int index) {
    _classpath_index = index;
  }
};
class PackageHashtable : public BasicHashtable<mtClass> {
private:
  inline unsigned int compute_hash(const char *s, int n) {
    unsigned int val = 0;
    while (--n >= 0) {
      val = *s++ + 31 * val;
    }
    return val;
  }
  PackageInfo* bucket(int index) {
    return (PackageInfo*)BasicHashtable<mtClass>::bucket(index);
  }
  PackageInfo* get_entry(int index, unsigned int hash,
                         const char* pkgname, size_t n) {
    for (PackageInfo* pp = bucket(index); pp != NULL; pp = pp->next()) {
      if (pp->hash() == hash &&
          strncmp(pkgname, pp->pkgname(), n) == 0 &&
          pp->pkgname()[n] == '\0') {
        return pp;
      }
    }
    return NULL;
  }
public:
  PackageHashtable(int table_size)
    : BasicHashtable<mtClass>(table_size, sizeof(PackageInfo)) {}
  PackageHashtable(int table_size, HashtableBucket<mtClass>* t, int number_of_entries)
    : BasicHashtable<mtClass>(table_size, sizeof(PackageInfo), t, number_of_entries) {}
  PackageInfo* get_entry(const char* pkgname, int n) {
    unsigned int hash = compute_hash(pkgname, n);
    return get_entry(hash_to_index(hash), hash, pkgname, n);
  }
  PackageInfo* new_entry(char* pkgname, int n) {
    unsigned int hash = compute_hash(pkgname, n);
    PackageInfo* pp;
    pp = (PackageInfo*)BasicHashtable<mtClass>::new_entry(hash);
    pp->set_pkgname(pkgname);
    return pp;
  }
  void add_entry(PackageInfo* pp) {
    int index = hash_to_index(pp->hash());
    BasicHashtable<mtClass>::add_entry(index, pp);
  }
  void copy_pkgnames(const char** packages) {
    int n = 0;
    for (int i = 0; i < table_size(); ++i) {
      for (PackageInfo* pp = bucket(i); pp != NULL; pp = pp->next()) {
        packages[n++] = pp->pkgname();
      }
    }
    assert(n == number_of_entries(), "just checking");
  }
  CDS_ONLY(void copy_table(char** top, char* end, PackageHashtable* table);)
};
#if INCLUDE_CDS
void PackageHashtable::copy_table(char** top, char* end,
                                  PackageHashtable* table) {
  BasicHashtable<mtClass>::copy_table(top, end);
  int i;
  intptr_t* tableSize = (intptr_t*)(*top);
  char* tableStart = *top;
  for (i = 0; i < table_size(); ++i) {
    for (PackageInfo* pp = table->bucket(i);
                      pp != NULL;
                      pp = pp->next()) {
      int n1 = (int)(strlen(pp->pkgname()) + 1);
      if (*top + n1 >= end) {
        report_out_of_shared_space(SharedMiscData);
      }
      pp->set_pkgname((char*)memcpy(*top, pp->pkgname(), n1));
    }
  }
  if (*top >= end) {
    report_out_of_shared_space(SharedMiscData);
  }
  intptr_t len = *top - (char*)tableStart;
}
void ClassLoader::copy_package_info_buckets(char** top, char* end) {
  _package_hash_table->copy_buckets(top, end);
}
void ClassLoader::copy_package_info_table(char** top, char* end) {
  _package_hash_table->copy_table(top, end, _package_hash_table);
}
#endif
PackageInfo* ClassLoader::lookup_package(const char *pkgname) {
  const char *cp = strrchr(pkgname, '/');
  if (cp != NULL) {
    int n = cp - pkgname + 1;
    return _package_hash_table->get_entry(pkgname, n);
  }
  return NULL;
}
bool ClassLoader::add_package(const char *pkgname, int classpath_index, TRAPS) {
  assert(pkgname != NULL, "just checking");
  {
    MutexLocker ml(PackageTable_lock, THREAD);
    PackageInfo* pp = lookup_package(pkgname);
    if (pp != NULL) {
      pp->set_index(classpath_index);
      return true;
    }
    const char *cp = strrchr(pkgname, '/');
    if (cp != NULL) {
      int n = cp - pkgname + 1;
      char* new_pkgname = NEW_C_HEAP_ARRAY(char, n + 1, mtClass);
      if (new_pkgname == NULL) {
        return false;
      }
      memcpy(new_pkgname, pkgname, n);
      new_pkgname[n] = '\0';
      pp = _package_hash_table->new_entry(new_pkgname, n);
      pp->set_index(classpath_index);
      _package_hash_table->add_entry(pp);
    }
    return true;
  }
}
oop ClassLoader::get_system_package(const char* name, TRAPS) {
  PackageInfo* pp;
  {
    MutexLocker ml(PackageTable_lock, THREAD);
    pp = lookup_package(name);
  }
  if (pp == NULL) {
    return NULL;
  } else {
    Handle p = java_lang_String::create_from_str(pp->filename(), THREAD);
    return p();
  }
}
objArrayOop ClassLoader::get_system_packages(TRAPS) {
  ResourceMark rm(THREAD);
  int nof_entries;
  const char** packages;
  {
    MutexLocker ml(PackageTable_lock, THREAD);
    nof_entries = _package_hash_table->number_of_entries();
    if ((packages = NEW_RESOURCE_ARRAY(const char*, nof_entries)) == NULL) {
      return NULL;
    }
    _package_hash_table->copy_pkgnames(packages);
  }
  objArrayOop r = oopFactory::new_objArray(SystemDictionary::String_klass(),
                                           nof_entries, CHECK_0);
  objArrayHandle result(THREAD, r);
  for (int i = 0; i < nof_entries; i++) {
    Handle str = java_lang_String::create_from_str(packages[i], CHECK_0);
    result->obj_at_put(i, str());
  }
  return result();
}
instanceKlassHandle ClassLoader::load_classfile(Symbol* h_name, TRAPS) {
  ResourceMark rm(THREAD);
  const char* class_name = h_name->as_C_string();
  EventMark m("loading class %s", class_name);
  ThreadProfilerMark tpm(ThreadProfilerMark::classLoaderRegion);
  stringStream st;
  st.print_raw(h_name->as_utf8());
  st.print_raw(".class");
  const char* file_name = st.as_string();
  ClassLoaderExt::Context context(class_name, file_name, THREAD);
  ClassFileStream* stream = NULL;
  int classpath_index = 0;
  ClassPathEntry* e = NULL;
  instanceKlassHandle h;
  {
    PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(),
                               ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(),
                               PerfClassTraceTime::CLASS_LOAD);
    e = _first_entry;
    while (e != NULL) {
      stream = e->open_stream(file_name, CHECK_NULL);
      if (!context.check(stream, classpath_index)) {
        return h; // NULL
      }
      if (stream != NULL) {
        break;
      }
      e = e->next();
      ++classpath_index;
    }
  }
  if (stream != NULL) {
    ClassFileParser parser(stream);
    ClassLoaderData* loader_data = ClassLoaderData::the_null_class_loader_data();
    Handle protection_domain;
    TempNewSymbol parsed_name = NULL;
    instanceKlassHandle result = parser.parseClassFile(h_name,
                                                       loader_data,
                                                       protection_domain,
                                                       parsed_name,
                                                       context.should_verify(classpath_index),
                                                       THREAD);
    if (HAS_PENDING_EXCEPTION) {
      ResourceMark rm;
      if (DumpSharedSpaces) {
        tty->print_cr("Preload Error: Failed to load %s", class_name);
      }
      return h;
    }
#if INCLUDE_JFR
  {
    InstanceKlass* ik = result();
    ON_KLASS_CREATION(ik, parser, THREAD);
    result = instanceKlassHandle(ik);
  }
#endif
    h = context.record_result(classpath_index, e, result, THREAD);
  } else {
    if (DumpSharedSpaces) {
      tty->print_cr("Preload Warning: Cannot find %s", class_name);
    }
  }
  return h;
}
void ClassLoader::create_package_info_table(HashtableBucket<mtClass> *t, int length,
                                            int number_of_entries) {
  assert(_package_hash_table == NULL, "One package info table allowed.");
  assert(length == package_hash_table_size * sizeof(HashtableBucket<mtClass>),
         "bad shared package info size.");
  _package_hash_table = new PackageHashtable(package_hash_table_size, t,
                                             number_of_entries);
}
void ClassLoader::create_package_info_table() {
    assert(_package_hash_table == NULL, "shouldn't have one yet");
    _package_hash_table = new PackageHashtable(package_hash_table_size);
}
void ClassLoader::initialize() {
  assert(_package_hash_table == NULL, "should have been initialized by now.");
  EXCEPTION_MARK;
  if (UsePerfData) {
    NEWPERFTICKCOUNTER(_perf_accumulated_time, SUN_CLS, "time");
    NEWPERFTICKCOUNTER(_perf_class_init_time, SUN_CLS, "classInitTime");
    NEWPERFTICKCOUNTER(_perf_class_init_selftime, SUN_CLS, "classInitTime.self");
    NEWPERFTICKCOUNTER(_perf_class_verify_time, SUN_CLS, "classVerifyTime");
    NEWPERFTICKCOUNTER(_perf_class_verify_selftime, SUN_CLS, "classVerifyTime.self");
    NEWPERFTICKCOUNTER(_perf_class_link_time, SUN_CLS, "classLinkedTime");
    NEWPERFTICKCOUNTER(_perf_class_link_selftime, SUN_CLS, "classLinkedTime.self");
    NEWPERFEVENTCOUNTER(_perf_classes_inited, SUN_CLS, "initializedClasses");
    NEWPERFEVENTCOUNTER(_perf_classes_linked, SUN_CLS, "linkedClasses");
    NEWPERFEVENTCOUNTER(_perf_classes_verified, SUN_CLS, "verifiedClasses");
    NEWPERFTICKCOUNTER(_perf_class_parse_time, SUN_CLS, "parseClassTime");
    NEWPERFTICKCOUNTER(_perf_class_parse_selftime, SUN_CLS, "parseClassTime.self");
    NEWPERFTICKCOUNTER(_perf_sys_class_lookup_time, SUN_CLS, "lookupSysClassTime");
    NEWPERFTICKCOUNTER(_perf_shared_classload_time, SUN_CLS, "sharedClassLoadTime");
    NEWPERFTICKCOUNTER(_perf_sys_classload_time, SUN_CLS, "sysClassLoadTime");
    NEWPERFTICKCOUNTER(_perf_app_classload_time, SUN_CLS, "appClassLoadTime");
    NEWPERFTICKCOUNTER(_perf_app_classload_selftime, SUN_CLS, "appClassLoadTime.self");
    NEWPERFEVENTCOUNTER(_perf_app_classload_count, SUN_CLS, "appClassLoadCount");
    NEWPERFTICKCOUNTER(_perf_define_appclasses, SUN_CLS, "defineAppClasses");
    NEWPERFTICKCOUNTER(_perf_define_appclass_time, SUN_CLS, "defineAppClassTime");
    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(_sync_systemLoaderLockContentionRate, SUN_CLS,
                        "systemLoaderLockContentionRate");
    NEWPERFEVENTCOUNTER(_sync_nonSystemLoaderLockContentionRate, SUN_CLS,
                        "nonSystemLoaderLockContentionRate");
    NEWPERFEVENTCOUNTER(_sync_JVMFindLoadedClassLockFreeCounter, SUN_CLS,
                        "jvmFindLoadedClassNoLockCalls");
    NEWPERFEVENTCOUNTER(_sync_JVMDefineClassLockFreeCounter, SUN_CLS,
                        "jvmDefineClassNoLockCalls");
    NEWPERFEVENTCOUNTER(_sync_JNIDefineClassLockFreeCounter, SUN_CLS,
                        "jniDefineClassNoLockCalls");
    NEWPERFEVENTCOUNTER(_unsafe_defineClassCallCounter, SUN_CLS,
                        "unsafeDefineClassCalls");
    NEWPERFEVENTCOUNTER(_isUnsyncloadClass, SUN_CLS, "isUnsyncloadClassSet");
    NEWPERFEVENTCOUNTER(_load_instance_class_failCounter, SUN_CLS,
                        "loadInstanceClassFailRate");
    if (UnsyncloadClass) {
      _isUnsyncloadClass->inc();
    }
  }
  load_zip_library();
#if INCLUDE_CDS
  if (DumpSharedSpaces) {
    _shared_paths_misc_info = SharedClassUtil::allocate_shared_paths_misc_info();
  }
#endif
  setup_bootstrap_search_path();
  if (LazyBootClassLoader) {
    setup_bootstrap_meta_index();
  }
}
#if INCLUDE_CDS
void ClassLoader::initialize_shared_path() {
  if (DumpSharedSpaces) {
    ClassLoaderExt::setup_search_paths();
    _shared_paths_misc_info->write_jint(0); // see comments in SharedPathsMiscInfo::check()
  }
}
#endif
jlong ClassLoader::classloader_time_ms() {
  return UsePerfData ?
    Management::ticks_to_ms(_perf_accumulated_time->get_value()) : -1;
}
jlong ClassLoader::class_init_count() {
  return UsePerfData ? _perf_classes_inited->get_value() : -1;
}
jlong ClassLoader::class_init_time_ms() {
  return UsePerfData ?
    Management::ticks_to_ms(_perf_class_init_time->get_value()) : -1;
}
jlong ClassLoader::class_verify_time_ms() {
  return UsePerfData ?
    Management::ticks_to_ms(_perf_class_verify_time->get_value()) : -1;
}
jlong ClassLoader::class_link_count() {
  return UsePerfData ? _perf_classes_linked->get_value() : -1;
}
jlong ClassLoader::class_link_time_ms() {
  return UsePerfData ?
    Management::ticks_to_ms(_perf_class_link_time->get_value()) : -1;
}
int ClassLoader::compute_Object_vtable() {
  int JDK_1_2_Object_vtable_size = 5;
  return JDK_1_2_Object_vtable_size * vtableEntry::size();
}
void classLoader_init() {
  ClassLoader::initialize();
}
bool ClassLoader::get_canonical_path(const char* orig, char* out, int len) {
  assert(orig != NULL && out != NULL && len > 0, "bad arguments");
  if (CanonicalizeEntry != NULL) {
    JavaThread* THREAD = JavaThread::current();
    JNIEnv* env = THREAD->jni_environment();
    ResourceMark rm(THREAD);
    char* orig_copy = NEW_RESOURCE_ARRAY_IN_THREAD(THREAD, char, strlen(orig)+1);
    strcpy(orig_copy, orig);
    if ((CanonicalizeEntry)(env, os::native_path(orig_copy), out, len) < 0) {
      return false;
    }
  } else {
    strncpy(out, orig, len);
    out[len - 1] = '\0';
  }
  return true;
}
#ifndef PRODUCT
void ClassLoader::verify() {
  _package_hash_table->verify();
}
typedef struct real_jzentry13 {         /* Zip file entry */
    char *name;                 /* entry name */
    jint time;                  /* modification time */
    jint size;                  /* size of uncompressed data */
    jint csize;                 /* size of compressed data (zero if uncompressed) */
    jint crc;                   /* crc of uncompressed data */
    char *comment;              /* optional zip file comment */
    jbyte *extra;               /* optional extra data */
    jint pos;                   /* position of LOC header (if negative) or data */
} real_jzentry13;
typedef struct real_jzfile13 {  /* Zip file */
    char *name;                 /* zip file name */
    jint refs;                  /* number of active references */
    jint fd;                    /* open file descriptor */
    void *lock;                 /* read lock */
    char *comment;              /* zip file comment */
    char *msg;                  /* zip error message */
    void *entries;              /* array of hash cells */
    jint total;                 /* total number of entries */
    unsigned short *table;      /* Hash chain heads: indexes into entries */
    jint tablelen;              /* number of hash eads */
    real_jzfile13 *next;        /* next zip file in search list */
    jzentry *cache;             /* we cache the most recently freed jzentry */
    char **metanames;           /* array of meta names (may have null names) */
    jint metacount;             /* number of slots in metanames array */
    char **comments;
} real_jzfile13;
typedef struct real_jzentry12 {  /* Zip file entry */
    char *name;                  /* entry name */
    jint time;                   /* modification time */
    jint size;                   /* size of uncompressed data */
    jint csize;                  /* size of compressed data (zero if uncompressed) */
    jint crc;                    /* crc of uncompressed data */
    char *comment;               /* optional zip file comment */
    jbyte *extra;                /* optional extra data */
    jint pos;                    /* position of LOC header (if negative) or data */
    struct real_jzentry12 *next; /* next entry in hash table */
} real_jzentry12;
typedef struct real_jzfile12 {  /* Zip file */
    char *name;                 /* zip file name */
    jint refs;                  /* number of active references */
    jint fd;                    /* open file descriptor */
    void *lock;                 /* read lock */
    char *comment;              /* zip file comment */
    char *msg;                  /* zip error message */
    real_jzentry12 *entries;    /* array of zip entries */
    jint total;                 /* total number of entries */
    real_jzentry12 **table;     /* hash table of entries */
    jint tablelen;              /* number of buckets */
    jzfile *next;               /* next zip file in search list */
} real_jzfile12;
void ClassPathDirEntry::compile_the_world(Handle loader, TRAPS) {
  tty->print_cr("CompileTheWorld : Skipped classes in %s", _dir);
  tty->cr();
}
bool ClassPathDirEntry::is_rt_jar() {
  return false;
}
void ClassPathZipEntry::compile_the_world(Handle loader, TRAPS) {
  if (JDK_Version::is_jdk12x_version()) {
    compile_the_world12(loader, THREAD);
  } else {
    compile_the_world13(loader, THREAD);
  }
  if (HAS_PENDING_EXCEPTION) {
    if (PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) {
      CLEAR_PENDING_EXCEPTION;
      tty->print_cr("\nCompileTheWorld : Ran out of memory\n");
      tty->print_cr("Increase class metadata storage if a limit was set");
    } else {
      tty->print_cr("\nCompileTheWorld : Unexpected exception occurred\n");
    }
  }
}
void ClassPathZipEntry::compile_the_world13(Handle loader, TRAPS) {
  real_jzfile13* zip = (real_jzfile13*) _zip;
  tty->print_cr("CompileTheWorld : Compiling all classes in %s", zip->name);
  tty->cr();
  for (int n = 0; ; n++) {
    real_jzentry13 * ze = (real_jzentry13 *)((*GetNextEntry)(_zip, n));
    if (ze == NULL) break;
    ClassLoader::compile_the_world_in(ze->name, loader, CHECK);
  }
}
void ClassPathZipEntry::compile_the_world12(Handle loader, TRAPS) {
  real_jzfile12* zip = (real_jzfile12*) _zip;
  tty->print_cr("CompileTheWorld : Compiling all classes in %s", zip->name);
  tty->cr();
  for (int n = 0; ; n++) {
    real_jzentry12 * ze = (real_jzentry12 *)((*GetNextEntry)(_zip, n));
    if (ze == NULL) break;
    ClassLoader::compile_the_world_in(ze->name, loader, CHECK);
  }
}
bool ClassPathZipEntry::is_rt_jar() {
  if (JDK_Version::is_jdk12x_version()) {
    return is_rt_jar12();
  } else {
    return is_rt_jar13();
  }
}
bool ClassPathZipEntry::is_rt_jar13() {
  real_jzfile13* zip = (real_jzfile13*) _zip;
  int len = (int)strlen(zip->name);
  return (len >= 6) && (strcasecmp(zip->name + len - 6, "rt.jar") == 0);
}
bool ClassPathZipEntry::is_rt_jar12() {
  real_jzfile12* zip = (real_jzfile12*) _zip;
  int len = (int)strlen(zip->name);
  return (len >= 6) && (strcasecmp(zip->name + len - 6, "rt.jar") == 0);
}
void LazyClassPathEntry::compile_the_world(Handle loader, TRAPS) {
  ClassPathEntry* cpe = resolve_entry(THREAD);
  if (cpe != NULL) {
    cpe->compile_the_world(loader, CHECK);
  }
}
bool LazyClassPathEntry::is_rt_jar() {
  Thread* THREAD = Thread::current();
  ClassPathEntry* cpe = resolve_entry(THREAD);
  return (cpe != NULL) ? cpe->is_jar_file() : false;
}
void ClassLoader::compile_the_world() {
  EXCEPTION_MARK;
  HandleMark hm(THREAD);
  ResourceMark rm(THREAD);
  BackgroundCompilation = false;
  Handle system_class_loader (THREAD, SystemDictionary::java_system_loader());
  ClassPathEntry* e = _first_entry;
  jlong start = os::javaTimeMillis();
  while (e != NULL) {
    if (e->is_rt_jar() && e != _first_entry) break;
    e->compile_the_world(system_class_loader, CATCH);
    e = e->next();
  }
  jlong end = os::javaTimeMillis();
  tty->print_cr("CompileTheWorld : Done (%d classes, %d methods, " JLONG_FORMAT " ms)",
                _compile_the_world_class_counter, _compile_the_world_method_counter, (end - start));
  {
    extern void print_statistics();
    print_statistics();
  }
  vm_exit(0);
}
int ClassLoader::_compile_the_world_class_counter = 0;
int ClassLoader::_compile_the_world_method_counter = 0;
static int _codecache_sweep_counter = 0;
static void clear_pending_exception_if_not_oom(TRAPS) {
  if (HAS_PENDING_EXCEPTION &&
      !PENDING_EXCEPTION->is_a(SystemDictionary::OutOfMemoryError_klass())) {
    CLEAR_PENDING_EXCEPTION;
  }
}
static bool can_be_compiled(methodHandle m, int comp_level) {
  assert(CompileTheWorld, "must be");
  vmIntrinsics::ID iid = m->intrinsic_id();
  if (MethodHandles::is_signature_polymorphic(iid) && MethodHandles::has_member_arg(iid)) {
    return false;
  }
  return CompilationPolicy::can_be_compiled(m, comp_level);
}
void ClassLoader::compile_the_world_in(char* name, Handle loader, TRAPS) {
  size_t len = strlen(name);
  if (len > 6 && strcmp(".class", name + len - 6) == 0) {
    char buffer[2048];
    if (len-6 >= sizeof(buffer)) return;
    strncpy(buffer, name, sizeof(buffer));
    buffer[len-6] = 0; // Truncate ".class" suffix.
    if (strchr(buffer, '.') == NULL) {
      _compile_the_world_class_counter++;
      if (_compile_the_world_class_counter > CompileTheWorldStopAt) return;
      TempNewSymbol sym = SymbolTable::new_symbol(buffer, CHECK);
      Klass* ik = SystemDictionary::resolve_or_null(sym, loader, Handle(), THREAD);
      instanceKlassHandle k (THREAD, ik);
      if (k.not_null() && !HAS_PENDING_EXCEPTION) {
        k->initialize(THREAD);
      }
      bool exception_occurred = HAS_PENDING_EXCEPTION;
      clear_pending_exception_if_not_oom(CHECK);
      if (CompileTheWorldPreloadClasses && k.not_null()) {
        ConstantPool::preload_and_initialize_all_classes(k->constants(), THREAD);
        if (HAS_PENDING_EXCEPTION) {
          clear_pending_exception_if_not_oom(CHECK);
          tty->print_cr("Preloading failed for (%d) %s", _compile_the_world_class_counter, buffer);
        }
      }
      if (_compile_the_world_class_counter >= CompileTheWorldStartAt) {
        if (k.is_null() || exception_occurred) {
          tty->print_cr("CompileTheWorld (%d) : Skipping %s", _compile_the_world_class_counter, buffer);
        } else {
          tty->print_cr("CompileTheWorld (%d) : %s", _compile_the_world_class_counter, buffer);
          int comp_level = CompilationPolicy::policy()->initial_compile_level();
          for (int n = 0; n < k->methods()->length(); n++) {
            methodHandle m (THREAD, k->methods()->at(n));
            if (can_be_compiled(m, comp_level)) {
              if (++_codecache_sweep_counter == CompileTheWorldSafepointInterval) {
                VM_ForceSafepoint op;
                VMThread::execute(&op);
                _codecache_sweep_counter = 0;
              }
              CompileBroker::compile_method(m, InvocationEntryBci, comp_level,
                                            methodHandle(), 0, "CTW", THREAD);
              if (HAS_PENDING_EXCEPTION) {
                clear_pending_exception_if_not_oom(CHECK);
                tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string());
              } else {
                _compile_the_world_method_counter++;
              }
              if (TieredCompilation && TieredStopAtLevel >= CompLevel_full_optimization) {
                nmethod* nm = m->code();
                if (nm != NULL && !m->is_method_handle_intrinsic()) {
                  nm->make_not_entrant();
                }
                CompileBroker::compile_method(m, InvocationEntryBci, CompLevel_full_optimization,
                                              methodHandle(), 0, "CTW", THREAD);
                if (HAS_PENDING_EXCEPTION) {
                  clear_pending_exception_if_not_oom(CHECK);
                  tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string());
                } else {
                  _compile_the_world_method_counter++;
                }
              }
            } else {
              tty->print_cr("CompileTheWorld (%d) : Skipping method: %s", _compile_the_world_class_counter, m->name_and_sig_as_C_string());
            }
            nmethod* nm = m->code();
            if (nm != NULL && !m->is_method_handle_intrinsic()) {
              nm->make_not_entrant();
            }
          }
        }
      }
    }
  }
}
#endif //PRODUCT
void PerfClassTraceTime::initialize() {
  if (!UsePerfData) return;
  if (_eventp != NULL) {
    _eventp->inc();
  }
  _prev_active_event = -1;
  for (int i=0; i < EVENT_TYPE_COUNT; i++) {
     if (_timers[i].is_active()) {
       assert(_prev_active_event == -1, "should have only one active timer");
       _prev_active_event = i;
       _timers[i].stop();
     }
  }
  if (_recursion_counters == NULL || (_recursion_counters[_event_type])++ == 0) {
    _t.start();
  }
   if (!_timers[_event_type].is_active()) {
    _timers[_event_type].start();
  }
}
PerfClassTraceTime::~PerfClassTraceTime() {
  if (!UsePerfData) return;
  _timers[_event_type].stop();
  jlong selftime = _timers[_event_type].ticks();
  if (_prev_active_event >= 0) {
    _timers[_prev_active_event].start();
  }
  if (_recursion_counters != NULL && --(_recursion_counters[_event_type]) > 0) return;
  _t.stop();
  _timep->inc(_t.ticks());
  if (_selftimep != NULL) {
    _selftimep->inc(selftime);
  }
  ClassLoader::perf_accumulated_time()->inc(selftime);
  _timers[_event_type].reset();
}
C:\hotspot-69087d08d473\src\share\vm/classfile/classLoader.hpp
#ifndef SHARE_VM_CLASSFILE_CLASSLOADER_HPP
#define SHARE_VM_CLASSFILE_CLASSLOADER_HPP
#include "classfile/classFileParser.hpp"
#include "runtime/perfData.hpp"
#include <sys/stat.h>
class MetaIndex: public CHeapObj<mtClass> {
 private:
  char** _meta_package_names;
  int    _num_meta_package_names;
 public:
  MetaIndex(char** meta_package_names, int num_meta_package_names);
  virtual ~MetaIndex();
  bool may_contain(const char* class_name);
};
class ClassPathEntry: public CHeapObj<mtClass> {
 private:
  ClassPathEntry* _next;
 public:
  ClassPathEntry* next()              { return _next; }
  void set_next(ClassPathEntry* next) {
    OrderAccess::release_store_ptr(&_next, next);
  }
  virtual bool is_jar_file() = 0;
  virtual const char* name() = 0;
  virtual bool is_lazy();
  ClassPathEntry();
  virtual ~ClassPathEntry() {}
  virtual ClassFileStream* open_stream(const char* name, TRAPS) = 0;
  NOT_PRODUCT(virtual void compile_the_world(Handle loader, TRAPS) = 0;)
  NOT_PRODUCT(virtual bool is_rt_jar() = 0;)
};
class ClassPathDirEntry: public ClassPathEntry {
 private:
  const char* _dir;           // Name of directory
 public:
  bool is_jar_file()  { return false;  }
  const char* name()  { return _dir; }
  ClassPathDirEntry(const char* dir);
  virtual ~ClassPathDirEntry() {}
  ClassFileStream* open_stream(const char* name, TRAPS);
  NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
  NOT_PRODUCT(bool is_rt_jar();)
};
typedef void* jzfile;
typedef struct {
  char *name;                   /* entry name */
  jlong time;                   /* modification time */
  jlong size;                   /* size of uncompressed data */
  jlong csize;                  /* size of compressed data (zero if uncompressed) */
  jint crc;                     /* crc of uncompressed data */
  char *comment;                /* optional zip file comment */
  jbyte *extra;                 /* optional extra data */
  jlong pos;                    /* position of LOC header (if negative) or data */
} jzentry;
class ClassPathZipEntry: public ClassPathEntry {
 private:
  jzfile* _zip;              // The zip archive
  const char*   _zip_name;   // Name of zip archive
 public:
  bool is_jar_file()  { return true;  }
  const char* name()  { return _zip_name; }
  ClassPathZipEntry(jzfile* zip, const char* zip_name);
  virtual ~ClassPathZipEntry();
  u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
  ClassFileStream* open_stream(const char* name, TRAPS);
  void contents_do(void f(const char* name, void* context), void* context);
  NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
  NOT_PRODUCT(void compile_the_world12(Handle loader, TRAPS);) // JDK 1.2 version
  NOT_PRODUCT(void compile_the_world13(Handle loader, TRAPS);) // JDK 1.3 version
  NOT_PRODUCT(bool is_rt_jar();)
  NOT_PRODUCT(bool is_rt_jar12();)
  NOT_PRODUCT(bool is_rt_jar13();)
};
class LazyClassPathEntry: public ClassPathEntry {
 private:
  const char* _path; // dir or file
  struct stat _st;
  MetaIndex* _meta_index;
  bool _has_error;
  bool _throw_exception;
  volatile ClassPathEntry* _resolved_entry;
 public:
  ClassPathEntry* resolve_entry(TRAPS);
  bool is_jar_file();
  const char* name()  { return _path; }
  LazyClassPathEntry(const char* path, const struct stat* st, bool throw_exception);
  virtual ~LazyClassPathEntry() {}
  u1* open_entry(const char* name, jint* filesize, bool nul_terminate, TRAPS);
  ClassFileStream* open_stream(const char* name, TRAPS);
  void set_meta_index(MetaIndex* meta_index) { _meta_index = meta_index; }
  virtual bool is_lazy();
  NOT_PRODUCT(void compile_the_world(Handle loader, TRAPS);)
  NOT_PRODUCT(bool is_rt_jar();)
};
class PackageHashtable;
class PackageInfo;
class SharedPathsMiscInfo;
template <MEMFLAGS F> class HashtableBucket;
class ClassLoader: AllStatic {
 public:
  enum SomeConstants {
    package_hash_table_size = 31  // Number of buckets
  };
 protected:
  friend class LazyClassPathEntry;
  static PerfCounter* _perf_accumulated_time;
  static PerfCounter* _perf_classes_inited;
  static PerfCounter* _perf_class_init_time;
  static PerfCounter* _perf_class_init_selftime;
  static PerfCounter* _perf_classes_verified;
  static PerfCounter* _perf_class_verify_time;
  static PerfCounter* _perf_class_verify_selftime;
  static PerfCounter* _perf_classes_linked;
  static PerfCounter* _perf_class_link_time;
  static PerfCounter* _perf_class_link_selftime;
  static PerfCounter* _perf_class_parse_time;
  static PerfCounter* _perf_class_parse_selftime;
  static PerfCounter* _perf_sys_class_lookup_time;
  static PerfCounter* _perf_shared_classload_time;
  static PerfCounter* _perf_sys_classload_time;
  static PerfCounter* _perf_app_classload_time;
  static PerfCounter* _perf_app_classload_selftime;
  static PerfCounter* _perf_app_classload_count;
  static PerfCounter* _perf_define_appclasses;
  static PerfCounter* _perf_define_appclass_time;
  static PerfCounter* _perf_define_appclass_selftime;
  static PerfCounter* _perf_app_classfile_bytes_read;
  static PerfCounter* _perf_sys_classfile_bytes_read;
  static PerfCounter* _sync_systemLoaderLockContentionRate;
  static PerfCounter* _sync_nonSystemLoaderLockContentionRate;
  static PerfCounter* _sync_JVMFindLoadedClassLockFreeCounter;
  static PerfCounter* _sync_JVMDefineClassLockFreeCounter;
  static PerfCounter* _sync_JNIDefineClassLockFreeCounter;
  static PerfCounter* _unsafe_defineClassCallCounter;
  static PerfCounter* _isUnsyncloadClass;
  static PerfCounter* _load_instance_class_failCounter;
  static ClassPathEntry* _first_entry;
  static ClassPathEntry* _last_entry;
  static int _num_entries;
  static PackageHashtable* _package_hash_table;
  static const char* _shared_archive;
  CDS_ONLY(static SharedPathsMiscInfo * _shared_paths_misc_info;)
  static unsigned int hash(const char *s, int n);
  static PackageInfo* lookup_package(const char *pkgname);
  static bool add_package(const char *pkgname, int classpath_index, TRAPS);
  static void setup_bootstrap_meta_index();
  static void setup_meta_index(const char* meta_index_path, const char* meta_index_dir,
                               int start_index);
  static void setup_bootstrap_search_path();
  static void setup_search_path(const char *class_path, bool canonicalize=false);
  static void load_zip_library();
  static ClassPathEntry* create_class_path_entry(const char *path, const struct stat* st,
                                                 bool lazy, bool throw_exception, TRAPS);
  static bool get_canonical_path(const char* orig, char* out, int len);
 public:
  static int crc32(int crc, const char* buf, int len);
  static bool update_class_path_entry_list(const char *path,
                                           bool check_for_duplicates,
                                           bool throw_exception=true);
  static void print_bootclasspath();
  static PerfCounter* perf_accumulated_time()         { return _perf_accumulated_time; }
  static PerfCounter* perf_classes_inited()           { return _perf_classes_inited; }
  static PerfCounter* perf_class_init_time()          { return _perf_class_init_time; }
  static PerfCounter* perf_class_init_selftime()      { return _perf_class_init_selftime; }
  static PerfCounter* perf_classes_verified()         { return _perf_classes_verified; }
  static PerfCounter* perf_class_verify_time()        { return _perf_class_verify_time; }
  static PerfCounter* perf_class_verify_selftime()    { return _perf_class_verify_selftime; }
  static PerfCounter* perf_classes_linked()           { return _perf_classes_linked; }
  static PerfCounter* perf_class_link_time()          { return _perf_class_link_time; }
  static PerfCounter* perf_class_link_selftime()      { return _perf_class_link_selftime; }
  static PerfCounter* perf_class_parse_time()         { return _perf_class_parse_time; }
  static PerfCounter* perf_class_parse_selftime()     { return _perf_class_parse_selftime; }
  static PerfCounter* perf_sys_class_lookup_time()    { return _perf_sys_class_lookup_time; }
  static PerfCounter* perf_shared_classload_time()    { return _perf_shared_classload_time; }
  static PerfCounter* perf_sys_classload_time()       { return _perf_sys_classload_time; }
  static PerfCounter* perf_app_classload_time()       { return _perf_app_classload_time; }
  static PerfCounter* perf_app_classload_selftime()   { return _perf_app_classload_selftime; }
  static PerfCounter* perf_app_classload_count()      { return _perf_app_classload_count; }
  static PerfCounter* perf_define_appclasses()        { return _perf_define_appclasses; }
  static PerfCounter* perf_define_appclass_time()     { return _perf_define_appclass_time; }
  static PerfCounter* perf_define_appclass_selftime() { return _perf_define_appclass_selftime; }
  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* sync_systemLoaderLockContentionRate() {
    return _sync_systemLoaderLockContentionRate;
  }
  static PerfCounter* sync_nonSystemLoaderLockContentionRate() {
    return _sync_nonSystemLoaderLockContentionRate;
  }
  static PerfCounter* sync_JVMFindLoadedClassLockFreeCounter() {
    return _sync_JVMFindLoadedClassLockFreeCounter;
  }
  static PerfCounter* sync_JVMDefineClassLockFreeCounter() {
    return _sync_JVMDefineClassLockFreeCounter;
  }
  static PerfCounter* sync_JNIDefineClassLockFreeCounter() {
    return _sync_JNIDefineClassLockFreeCounter;
  }
  static PerfCounter* unsafe_defineClassCallCounter() {
    return _unsafe_defineClassCallCounter;
  }
  static PerfCounter* load_instance_class_failCounter() {
    return _load_instance_class_failCounter;
  }
  static instanceKlassHandle load_classfile(Symbol* h_name, TRAPS);
  static oop get_system_package(const char* name, TRAPS);
  static objArrayOop get_system_packages(TRAPS);
  static void initialize();
  CDS_ONLY(static void initialize_shared_path();)
  static void create_package_info_table();
  static void create_package_info_table(HashtableBucket<mtClass> *t, int length,
                                        int number_of_entries);
  static int compute_Object_vtable();
  static ClassPathEntry* classpath_entry(int n) {
    ClassPathEntry* e = ClassLoader::_first_entry;
    while (--n >= 0) {
      assert(e != NULL, "Not that many classpath entries.");
      e = e->next();
    }
    return e;
  }
  static int num_classpath_entries() {
    return _num_entries;
  }
#if INCLUDE_CDS
  static void copy_package_info_buckets(char** top, char* end);
  static void copy_package_info_table(char** top, char* end);
  static void  check_shared_classpath(const char *path);
  static void  finalize_shared_paths_misc_info();
  static int   get_shared_paths_misc_info_size();
  static void* get_shared_paths_misc_info();
  static bool  check_shared_paths_misc_info(void* info, int size);
  static void  exit_with_path_failure(const char* error, const char* message);
#endif
  static void  trace_class_path(outputStream* out, const char* msg, const char* name = NULL);
  static jlong classloader_time_ms();
  static jlong class_method_total_size();
  static jlong class_init_count();
  static jlong class_init_time_ms();
  static jlong class_verify_time_ms();
  static jlong class_link_count();
  static jlong class_link_time_ms();
  static bool contains_entry(ClassPathEntry* entry);
  static void add_to_list(ClassPathEntry* new_entry);
  static ClassPathZipEntry* create_class_path_zip_entry(const char *apath);
  static const char* package_from_name(const char* const class_name, bool* bad_class_name = NULL);
  static void verify()              PRODUCT_RETURN;
#ifndef PRODUCT
 protected:
  static int _compile_the_world_class_counter;
  static int _compile_the_world_method_counter;
 public:
  static void compile_the_world();
  static void compile_the_world_in(char* name, Handle loader, TRAPS);
  static int  compile_the_world_counter() { return _compile_the_world_class_counter; }
#endif //PRODUCT
};
class PerfClassTraceTime {
 public:
  enum {
    CLASS_LOAD   = 0,
    PARSE_CLASS  = 1,
    CLASS_LINK   = 2,
    CLASS_VERIFY = 3,
    CLASS_CLINIT = 4,
    DEFINE_CLASS = 5,
    EVENT_TYPE_COUNT = 6
  };
 protected:
  elapsedTimer     _t;
  PerfLongCounter* _timep;
  PerfLongCounter* _selftimep;
  PerfLongCounter* _eventp;
  int*             _recursion_counters;
  elapsedTimer*    _timers;
  int              _event_type;
  int              _prev_active_event;
 public:
  inline PerfClassTraceTime(PerfLongCounter* timep,     /* counter incremented with inclusive time */
                            PerfLongCounter* selftimep, /* counter incremented with exclusive time */
                            PerfLongCounter* eventp,    /* event counter */
                            int* recursion_counters,    /* thread-local recursion counter array */
                            elapsedTimer* timers,       /* thread-local timer array */
                            int type                    /* event type */ ) :
      _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) {
    initialize();
  }
  inline PerfClassTraceTime(PerfLongCounter* timep,     /* counter incremented with inclusive time */
                            elapsedTimer* timers,       /* thread-local timer array */
                            int type                    /* event type */ ) :
      _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) {
    initialize();
  }
  inline void suspend() { _t.stop(); _timers[_event_type].stop(); }
  inline void resume()  { _t.start(); _timers[_event_type].start(); }
  ~PerfClassTraceTime();
  void initialize();
};
#endif // SHARE_VM_CLASSFILE_CLASSLOADER_HPP
C:\hotspot-69087d08d473\src\share\vm/classfile/classLoaderData.cpp
#include "precompiled.hpp"
#include "classfile/classLoaderData.hpp"
#include "classfile/classLoaderData.inline.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/metadataOnStackMark.hpp"
#include "classfile/systemDictionary.hpp"
#include "code/codeCache.hpp"
#include "memory/gcLocker.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/metaspaceShared.hpp"
#include "memory/oopFactory.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/mutex.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/synchronizer.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#include "utilities/ostream.hpp"
ClassLoaderData * ClassLoaderData::_the_null_class_loader_data = NULL;
ClassLoaderData::ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies) :
  _class_loader(h_class_loader()),
  _is_anonymous(is_anonymous),
  _keep_alive(is_anonymous || h_class_loader.is_null()),
  _metaspace(NULL), _unloading(false), _klasses(NULL),
  _claimed(0), _jmethod_ids(NULL), _handles(), _deallocate_list(NULL),
  _next(NULL), _dependencies(dependencies),
  _metaspace_lock(new Mutex(Monitor::leaf+1, "Metaspace allocation lock", true)) {
  JFR_ONLY(INIT_ID(this);)
}
void ClassLoaderData::init_dependencies(TRAPS) {
  assert(!Universe::is_fully_initialized(), "should only be called when initializing");
  assert(is_the_null_class_loader_data(), "should only call this for the null class loader");
  _dependencies.init(CHECK);
}
void ClassLoaderData::Dependencies::init(TRAPS) {
  _list_head = oopFactory::new_objectArray(2, CHECK);
}
ClassLoaderData::ChunkedHandleList::~ChunkedHandleList() {
  Chunk* c = _head;
  while (c != NULL) {
    Chunk* next = c->_next;
    delete c;
    c = next;
  }
}
oop* ClassLoaderData::ChunkedHandleList::add(oop o) {
  if (_head == NULL || _head->_size == Chunk::CAPACITY) {
    Chunk* next = new Chunk(_head);
    OrderAccess::release_store_ptr(&_head, next);
  }
  oop* handle = &_head->_data[_head->_size];
  OrderAccess::release_store(&_head->_size, _head->_size + 1);
  return handle;
}
inline void ClassLoaderData::ChunkedHandleList::oops_do_chunk(OopClosure* f, Chunk* c, const juint size) {
  for (juint i = 0; i < size; i++) {
    if (c->_data[i] != NULL) {
      f->do_oop(&c->_data[i]);
    }
  }
}
void ClassLoaderData::ChunkedHandleList::oops_do(OopClosure* f) {
  Chunk* head = (Chunk*) OrderAccess::load_ptr_acquire(&_head);
  if (head != NULL) {
    oops_do_chunk(f, head, OrderAccess::load_acquire(&head->_size));
    for (Chunk* c = head->_next; c != NULL; c = c->_next) {
      oops_do_chunk(f, c, c->_size);
    }
  }
}
bool ClassLoaderData::claim() {
  if (_claimed == 1) {
    return false;
  }
  return (int) Atomic::cmpxchg(1, &_claimed, 0) == 0;
}
void ClassLoaderData::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
  if (must_claim && !claim()) {
    return;
  }
  f->do_oop(&_class_loader);
  _dependencies.oops_do(f);
  _handles.oops_do(f);
  if (klass_closure != NULL) {
    classes_do(klass_closure);
  }
}
void ClassLoaderData::Dependencies::oops_do(OopClosure* f) {
  f->do_oop((oop*)&_list_head);
}
void ClassLoaderData::classes_do(KlassClosure* klass_closure) {
  for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
    klass_closure->do_klass(k);
    assert(k != k->next_link(), "no loops!");
  }
}
void ClassLoaderData::classes_do(void f(Klass * const)) {
  for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
    f(k);
  }
}
void ClassLoaderData::loaded_classes_do(KlassClosure* klass_closure) {
  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
  for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
    if (k->oop_is_array() || (k->oop_is_instance() && InstanceKlass::cast(k)->is_loaded())) {
      klass_closure->do_klass(k);
    }
  }
}
void ClassLoaderData::classes_do(void f(InstanceKlass*)) {
  for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
    if (k->oop_is_instance()) {
      f(InstanceKlass::cast(k));
    }
    assert(k != k->next_link(), "no loops!");
  }
}
void ClassLoaderData::record_dependency(Klass* k, TRAPS) {
  ClassLoaderData * const from_cld = this;
  ClassLoaderData * const to_cld = k->class_loader_data();
  if (to_cld->is_the_null_class_loader_data()) {
    return;
  }
  oop to;
  if (to_cld->is_anonymous()) {
    to = k->java_mirror();
  } else {
    to = to_cld->class_loader();
    if (!from_cld->is_anonymous()) {
      oop from = from_cld->class_loader();
      oop curr = from;
      while (curr != NULL) {
        if (curr == to) {
          return; // this class loader is in the parent list, no need to add it.
        }
        curr = java_lang_ClassLoader::parent(curr);
      }
    }
  }
  Handle dependency(THREAD, to);
  from_cld->_dependencies.add(dependency, CHECK);
}
void ClassLoaderData::Dependencies::add(Handle dependency, TRAPS) {
  objArrayOop ok = _list_head;
  objArrayOop last = NULL;
  while (ok != NULL) {
    last = ok;
    if (ok->obj_at(0) == dependency()) {
      return;
    }
    ok = (objArrayOop)ok->obj_at(1);
  }
  assert (last != NULL, "dependencies should be initialized");
  objArrayHandle last_handle(THREAD, last);
  objArrayOop deps = oopFactory::new_objectArray(2, CHECK);
  deps->obj_at_put(0, dependency());
  objArrayHandle new_dependency(THREAD, deps);
  locked_add(last_handle, new_dependency, THREAD);
}
void ClassLoaderData::Dependencies::locked_add(objArrayHandle last_handle,
                                               objArrayHandle new_dependency,
                                               Thread* THREAD) {
  ObjectLocker ol(Handle(THREAD, _list_head), THREAD);
  oop loader_or_mirror = new_dependency->obj_at(0);
  objArrayOop end = last_handle();
  objArrayOop last = NULL;
  while (end != NULL) {
    last = end;
    if (end->obj_at(0) == loader_or_mirror) {
      return;
    }
    end = (objArrayOop)end->obj_at(1);
  }
  assert (last != NULL, "dependencies should be initialized");
  if (last->obj_at(0) == NULL) {
    last->obj_at_put(0, new_dependency->obj_at(0));
  } else {
    last->obj_at_put(1, new_dependency());
  }
}
void ClassLoaderDataGraph::clear_claimed_marks() {
  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
    cld->clear_claimed();
  }
}
void ClassLoaderData::add_class(Klass* k) {
  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
  Klass* old_value = _klasses;
  k->set_next_link(old_value);
  _klasses = k;
  if (TraceClassLoaderData && Verbose && k->class_loader_data() != NULL) {
    ResourceMark rm;
    tty->print_cr("[TraceClassLoaderData] Adding k: " PTR_FORMAT " %s to CLD: "
                  PTR_FORMAT " loader: " PTR_FORMAT " %s",
                  p2i(k),
                  k->external_name(),
                  p2i(k->class_loader_data()),
                  p2i((void *)k->class_loader()),
                  loader_name());
  }
}
void ClassLoaderData::remove_class(Klass* scratch_class) {
  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
  Klass* prev = NULL;
  for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
    if (k == scratch_class) {
      if (prev == NULL) {
        _klasses = k->next_link();
      } else {
        Klass* next = k->next_link();
        prev->set_next_link(next);
      }
      return;
    }
    prev = k;
    assert(k != k->next_link(), "no loops!");
  }
  ShouldNotReachHere();   // should have found this class!!
}
void ClassLoaderData::unload() {
  _unloading = true;
  classes_do(InstanceKlass::notify_unload_class);
  if (TraceClassLoaderData) {
    ResourceMark rm;
    tty->print("[ClassLoaderData: unload loader data " INTPTR_FORMAT, p2i(this));
    tty->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)class_loader()),
               loader_name());
    if (is_anonymous()) {
      tty->print(" for anonymous class  " INTPTR_FORMAT " ", p2i(_klasses));
    }
    tty->print_cr("]");
  }
}
oop ClassLoaderData::keep_alive_object() const {
  assert(!keep_alive(), "Don't use with CLDs that are artificially kept alive");
  return is_anonymous() ? _klasses->java_mirror() : class_loader();
}
bool ClassLoaderData::is_alive(BoolObjectClosure* is_alive_closure) const {
  bool alive = keep_alive() // null class loader and incomplete anonymous klasses.
      || is_alive_closure->do_object_b(keep_alive_object());
  return alive;
}
ClassLoaderData::~ClassLoaderData() {
  classes_do(InstanceKlass::release_C_heap_structures);
  Metaspace *m = _metaspace;
  if (m != NULL) {
    _metaspace = NULL;
    delete m;
  }
  if (_jmethod_ids != NULL) {
    Method::clear_jmethod_ids(this);
  }
  delete _metaspace_lock;
  if (_deallocate_list != NULL) {
    delete _deallocate_list;
  }
}
bool ClassLoaderData::is_ext_class_loader_data() const {
  return SystemDictionary::is_ext_class_loader(class_loader());
}
Metaspace* ClassLoaderData::metaspace_non_null() {
  assert(!DumpSharedSpaces, "wrong metaspace!");
  if (_metaspace == NULL) {
    MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
    if (_metaspace != NULL) {
      return _metaspace;
    }
    if (this == the_null_class_loader_data()) {
      assert (class_loader() == NULL, "Must be");
      set_metaspace(new Metaspace(_metaspace_lock, Metaspace::BootMetaspaceType));
    } else if (is_anonymous()) {
      if (TraceClassLoaderData && Verbose && class_loader() != NULL) {
        tty->print_cr("is_anonymous: %s", class_loader()->klass()->internal_name());
      }
      set_metaspace(new Metaspace(_metaspace_lock, Metaspace::AnonymousMetaspaceType));
    } else if (class_loader()->is_a(SystemDictionary::reflect_DelegatingClassLoader_klass())) {
      if (TraceClassLoaderData && Verbose && class_loader() != NULL) {
        tty->print_cr("is_reflection: %s", class_loader()->klass()->internal_name());
      }
      set_metaspace(new Metaspace(_metaspace_lock, Metaspace::ReflectionMetaspaceType));
    } else {
      set_metaspace(new Metaspace(_metaspace_lock, Metaspace::StandardMetaspaceType));
    }
  }
  return _metaspace;
}
jobject ClassLoaderData::add_handle(Handle h) {
  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
  return (jobject) _handles.add(h());
}
void ClassLoaderData::add_to_deallocate_list(Metadata* m) {
  if (!m->is_shared()) {
    MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
    if (_deallocate_list == NULL) {
      _deallocate_list = new (ResourceObj::C_HEAP, mtClass) GrowableArray<Metadata*>(100, true);
    }
    _deallocate_list->append_if_missing(m);
  }
}
void ClassLoaderData::free_deallocate_list() {
  assert(SafepointSynchronize::is_at_safepoint(), "only called at safepoint");
  if (_deallocate_list == NULL) {
    return;
  }
  for (int i = _deallocate_list->length() - 1; i >= 0; i--) {
    Metadata* m = _deallocate_list->at(i);
    if (!m->on_stack()) {
      _deallocate_list->remove_at(i);
      if (m->is_method()) {
        MetadataFactory::free_metadata(this, (Method*)m);
      } else if (m->is_constantPool()) {
        MetadataFactory::free_metadata(this, (ConstantPool*)m);
      } else if (m->is_klass()) {
        MetadataFactory::free_metadata(this, (InstanceKlass*)m);
      } else {
        ShouldNotReachHere();
      }
    }
  }
}
ClassLoaderData* ClassLoaderData::anonymous_class_loader_data(oop loader, TRAPS) {
  return ClassLoaderDataGraph::add(loader, true, THREAD);
}
const char* ClassLoaderData::loader_name() {
  return SystemDictionary::loader_name(class_loader());
}
#ifndef PRODUCT
#undef CLD_DUMP_KLASSES
void ClassLoaderData::dump(outputStream * const out) {
  ResourceMark rm;
  out->print("ClassLoaderData CLD: " PTR_FORMAT ", loader: " PTR_FORMAT ", loader_klass: " PTR_FORMAT " %s {",
      p2i(this), p2i((void *)class_loader()),
      p2i(class_loader() != NULL ? class_loader()->klass() : NULL), loader_name());
  if (claimed()) out->print(" claimed ");
  if (is_unloading()) out->print(" unloading ");
  out->cr();
  if (metaspace_or_null() != NULL) {
    out->print_cr("metaspace: " INTPTR_FORMAT, p2i(metaspace_or_null()));
    metaspace_or_null()->dump(out);
  } else {
    out->print_cr("metaspace: NULL");
  }
#ifdef CLD_DUMP_KLASSES
  if (Verbose) {
    ResourceMark rm;
    Klass* k = _klasses;
    while (k != NULL) {
      out->print_cr("klass " PTR_FORMAT ", %s, CT: %d, MUT: %d", k, k->name()->as_C_string(),
          k->has_modified_oops(), k->has_accumulated_modified_oops());
      assert(k != k->next_link(), "no loops!");
      k = k->next_link();
    }
  }
#endif  // CLD_DUMP_KLASSES
#undef CLD_DUMP_KLASSES
  if (_jmethod_ids != NULL) {
    Method::print_jmethod_ids(this, out);
  }
  out->print_cr("}");
}
#endif // PRODUCT
void ClassLoaderData::verify() {
  oop cl = class_loader();
  guarantee(this == class_loader_data(cl) || is_anonymous(), "Must be the same");
  guarantee(cl != NULL || this == ClassLoaderData::the_null_class_loader_data() || is_anonymous(), "must be");
  if (metaspace_or_null() != NULL) {
    metaspace_or_null()->verify();
  }
  for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
    guarantee(k->class_loader_data() == this, "Must be the same");
    k->verify();
    assert(k != k->next_link(), "no loops!");
  }
}
bool ClassLoaderData::contains_klass(Klass* klass) {
  for (Klass* k = _klasses; k != NULL; k = k->next_link()) {
    if (k == klass) return true;
  }
  return false;
}
ClassLoaderData* ClassLoaderDataGraph::_head = NULL;
ClassLoaderData* ClassLoaderDataGraph::_unloading = NULL;
ClassLoaderData* ClassLoaderDataGraph::_saved_unloading = NULL;
ClassLoaderData* ClassLoaderDataGraph::_saved_head = NULL;
bool ClassLoaderDataGraph::_should_purge = false;
ClassLoaderData* ClassLoaderDataGraph::add(Handle loader, bool is_anonymous, TRAPS) {
  ClassLoaderData::Dependencies dependencies(CHECK_NULL);
  No_Safepoint_Verifier no_safepoints; // we mustn't GC until we've installed the
  ClassLoaderData* cld = new ClassLoaderData(loader, is_anonymous, dependencies);
  if (!is_anonymous) {
    ClassLoaderData** cld_addr = java_lang_ClassLoader::loader_data_addr(loader());
    ClassLoaderData* old = (ClassLoaderData*) Atomic::cmpxchg_ptr(cld, cld_addr, NULL);
    if (old != NULL) {
      delete cld;
      return old;
    }
  }
  ClassLoaderData** list_head = &_head;
  ClassLoaderData* next = _head;
  do {
    cld->set_next(next);
    ClassLoaderData* exchanged = (ClassLoaderData*)Atomic::cmpxchg_ptr(cld, list_head, next);
    if (exchanged == next) {
      if (TraceClassLoaderData) {
        ResourceMark rm;
        tty->print("[ClassLoaderData: ");
        tty->print("create class loader data " INTPTR_FORMAT, p2i(cld));
        tty->print(" for instance " INTPTR_FORMAT " of %s", p2i((void *)cld->class_loader()),
                   cld->loader_name());
        tty->print_cr("]");
      }
      return cld;
    }
    next = exchanged;
  } while (true);
}
void ClassLoaderDataGraph::oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
    cld->oops_do(f, klass_closure, must_claim);
  }
}
void ClassLoaderDataGraph::keep_alive_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
    if (cld->keep_alive()) {
      cld->oops_do(f, klass_closure, must_claim);
    }
  }
}
void ClassLoaderDataGraph::always_strong_oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim) {
  if (ClassUnloading) {
    keep_alive_oops_do(f, klass_closure, must_claim);
  } else {
    oops_do(f, klass_closure, must_claim);
  }
}
void ClassLoaderDataGraph::cld_do(CLDClosure* cl) {
  for (ClassLoaderData* cld = _head; cl != NULL && cld != NULL; cld = cld->next()) {
    cl->do_cld(cld);
  }
}
void ClassLoaderDataGraph::cld_unloading_do(CLDClosure* cl) {
  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
  for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
    assert(cld->is_unloading(), "invariant");
    cl->do_cld(cld);
  }
}
void ClassLoaderDataGraph::roots_cld_do(CLDClosure* strong, CLDClosure* weak) {
  for (ClassLoaderData* cld = _head;  cld != NULL; cld = cld->_next) {
    CLDClosure* closure = cld->keep_alive() ? strong : weak;
    if (closure != NULL) {
      closure->do_cld(cld);
    }
  }
}
void ClassLoaderDataGraph::keep_alive_cld_do(CLDClosure* cl) {
  roots_cld_do(cl, NULL);
}
void ClassLoaderDataGraph::always_strong_cld_do(CLDClosure* cl) {
  if (ClassUnloading) {
    keep_alive_cld_do(cl);
  } else {
    cld_do(cl);
  }
}
void ClassLoaderDataGraph::classes_do(KlassClosure* klass_closure) {
  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
    cld->classes_do(klass_closure);
  }
}
void ClassLoaderDataGraph::classes_do(void f(Klass* const)) {
  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
    cld->classes_do(f);
  }
}
void ClassLoaderDataGraph::loaded_classes_do(KlassClosure* klass_closure) {
  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
    cld->loaded_classes_do(klass_closure);
  }
}
void ClassLoaderDataGraph::classes_unloading_do(void f(Klass* const)) {
  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
  for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
    cld->classes_do(f);
  }
}
GrowableArray<ClassLoaderData*>* ClassLoaderDataGraph::new_clds() {
  assert(_head == NULL || _saved_head != NULL, "remember_new_clds(true) not called?");
  GrowableArray<ClassLoaderData*>* array = new GrowableArray<ClassLoaderData*>();
  ClassLoaderData* curr = _head;
  while (curr != _saved_head) {
    if (!curr->claimed()) {
      array->push(curr);
      if (TraceClassLoaderData) {
        tty->print("[ClassLoaderData] found new CLD: ");
        curr->print_value_on(tty);
        tty->cr();
      }
    }
    curr = curr->_next;
  }
  return array;
}
bool ClassLoaderDataGraph::unload_list_contains(const void* x) {
  assert(SafepointSynchronize::is_at_safepoint(), "only safe to call at safepoint");
  for (ClassLoaderData* cld = _unloading; cld != NULL; cld = cld->next()) {
    if (cld->metaspace_or_null() != NULL && cld->metaspace_or_null()->contains(x)) {
      return true;
    }
  }
  return false;
}
#ifndef PRODUCT
bool ClassLoaderDataGraph::contains_loader_data(ClassLoaderData* loader_data) {
  for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
    if (loader_data == data) {
      return true;
    }
  }
  return false;
}
#endif // PRODUCT
bool ClassLoaderDataGraph::do_unloading(BoolObjectClosure* is_alive_closure, bool clean_alive) {
  ClassLoaderData* data = _head;
  ClassLoaderData* prev = NULL;
  bool seen_dead_loader = false;
  _saved_unloading = _unloading;
  while (data != NULL) {
    if (data->is_alive(is_alive_closure)) {
      prev = data;
      data = data->next();
      continue;
    }
    seen_dead_loader = true;
    ClassLoaderData* dead = data;
    dead->unload();
    data = data->next();
    if (prev != NULL) {
      prev->set_next(data);
    } else {
      assert(dead == _head, "sanity check");
      _head = data;
    }
    dead->set_next(_unloading);
    _unloading = dead;
  }
  if (clean_alive) {
    ClassLoaderDataGraph::clean_metaspaces();
  }
  return seen_dead_loader;
}
void ClassLoaderDataGraph::clean_metaspaces() {
  bool has_redefined_a_class = JvmtiExport::has_redefined_a_class();
  MetadataOnStackMark md_on_stack(has_redefined_a_class);
  if (has_redefined_a_class) {
    for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
      data->classes_do(InstanceKlass::purge_previous_versions);
    }
  }
  free_deallocate_lists();
}
void ClassLoaderDataGraph::purge() {
  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint!");
  ClassLoaderData* list = _unloading;
  _unloading = NULL;
  ClassLoaderData* next = list;
  while (next != NULL) {
    ClassLoaderData* purge_me = next;
    next = purge_me->next();
    delete purge_me;
  }
  Metaspace::purge();
}
void ClassLoaderDataGraph::free_deallocate_lists() {
  for (ClassLoaderData* cld = _head; cld != NULL; cld = cld->next()) {
    cld->free_deallocate_list();
  }
  for (ClassLoaderData* cld = _unloading; cld != _saved_unloading; cld = cld->next()) {
    cld->free_deallocate_list();
  }
}
Metaspace* ClassLoaderData::_ro_metaspace = NULL;
Metaspace* ClassLoaderData::_rw_metaspace = NULL;
static bool _shared_metaspaces_initialized = false;
void ClassLoaderData::initialize_shared_metaspaces() {
  assert(DumpSharedSpaces, "only use this for dumping shared spaces");
  assert(this == ClassLoaderData::the_null_class_loader_data(),
         "only supported for null loader data for now");
  assert (!_shared_metaspaces_initialized, "only initialize once");
  MutexLockerEx ml(metaspace_lock(),  Mutex::_no_safepoint_check_flag);
  _ro_metaspace = new Metaspace(_metaspace_lock, Metaspace::ROMetaspaceType);
  _rw_metaspace = new Metaspace(_metaspace_lock, Metaspace::ReadWriteMetaspaceType);
  _shared_metaspaces_initialized = true;
}
Metaspace* ClassLoaderData::ro_metaspace() {
  assert(_ro_metaspace != NULL, "should already be initialized");
  return _ro_metaspace;
}
Metaspace* ClassLoaderData::rw_metaspace() {
  assert(_rw_metaspace != NULL, "should already be initialized");
  return _rw_metaspace;
}
ClassLoaderDataGraphKlassIteratorAtomic::ClassLoaderDataGraphKlassIteratorAtomic()
    : _next_klass(NULL) {
  ClassLoaderData* cld = ClassLoaderDataGraph::_head;
  Klass* klass = NULL;
  while (cld != NULL) {
    klass = cld->_klasses;
    if (klass != NULL) {
      _next_klass = klass;
      return;
    }
    cld = cld->next();
  }
}
Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass_in_cldg(Klass* klass) {
  Klass* next = klass->next_link();
  if (next != NULL) {
    return next;
  }
  ClassLoaderData* cld = klass->class_loader_data();
  while (next == NULL) {
    cld = cld->next();
    if (cld == NULL) {
      break;
    }
    next = cld->_klasses;
  }
  return next;
}
Klass* ClassLoaderDataGraphKlassIteratorAtomic::next_klass() {
  Klass* head = _next_klass;
  while (head != NULL) {
    Klass* next = next_klass_in_cldg(head);
    Klass* old_head = (Klass*)Atomic::cmpxchg_ptr(next, &_next_klass, head);
    if (old_head == head) {
      return head; // Won the CAS.
    }
    head = old_head;
  }
  assert(head == NULL, err_msg("head is " PTR_FORMAT ", expected not null:", p2i(head)));
  return NULL;
}
ClassLoaderDataGraphMetaspaceIterator::ClassLoaderDataGraphMetaspaceIterator() {
  _data = ClassLoaderDataGraph::_head;
}
ClassLoaderDataGraphMetaspaceIterator::~ClassLoaderDataGraphMetaspaceIterator() {}
#ifndef PRODUCT
extern "C" int print_loader_data_graph() {
  ClassLoaderDataGraph::dump_on(tty);
  return 0;
}
void ClassLoaderDataGraph::verify() {
  for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
    data->verify();
  }
}
void ClassLoaderDataGraph::dump_on(outputStream * const out) {
  for (ClassLoaderData* data = _head; data != NULL; data = data->next()) {
    data->dump(out);
  }
  MetaspaceAux::dump(out);
}
#endif // PRODUCT
void ClassLoaderData::print_value_on(outputStream* out) const {
  if (class_loader() == NULL) {
    out->print("NULL class_loader");
  } else {
    out->print("class loader " INTPTR_FORMAT, p2i(this));
    class_loader()->print_value_on(out);
  }
}
C:\hotspot-69087d08d473\src\share\vm/classfile/classLoaderData.hpp
#ifndef SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP
#define SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP
#include "memory/allocation.hpp"
#include "memory/memRegion.hpp"
#include "memory/metaspace.hpp"
#include "memory/metaspaceCounters.hpp"
#include "runtime/mutex.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/macros.hpp"
#if INCLUDE_JFR
#include "jfr/support/jfrTraceIdExtension.hpp"
#endif
class ClassLoaderData;
class JNIMethodBlock;
class Metadebug;
class ClassLoaderDataGraph : public AllStatic {
  friend class ClassLoaderData;
  friend class ClassLoaderDataGraphMetaspaceIterator;
  friend class ClassLoaderDataGraphKlassIteratorAtomic;
  friend class VMStructs;
 private:
  static ClassLoaderData* _head;
  static ClassLoaderData* _unloading;
  static ClassLoaderData* _saved_head;
  static ClassLoaderData* _saved_unloading;
  static bool _should_purge;
  static ClassLoaderData* add(Handle class_loader, bool anonymous, TRAPS);
  static void clean_metaspaces();
 public:
  static ClassLoaderData* find_or_create(Handle class_loader, TRAPS);
  static void purge();
  static void clear_claimed_marks();
  static void oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim);
  static void keep_alive_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
  static void always_strong_oops_do(OopClosure* blk, KlassClosure* klass_closure, bool must_claim);
  static void cld_do(CLDClosure* cl);
  static void cld_unloading_do(CLDClosure* cl);
  static void roots_cld_do(CLDClosure* strong, CLDClosure* weak);
  static void keep_alive_cld_do(CLDClosure* cl);
  static void always_strong_cld_do(CLDClosure* cl);
  static void classes_do(KlassClosure* klass_closure);
  static void classes_do(void f(Klass* const));
  static void loaded_classes_do(KlassClosure* klass_closure);
  static void classes_unloading_do(void f(Klass* const));
  static bool do_unloading(BoolObjectClosure* is_alive, bool clean_alive);
  static void remember_new_clds(bool remember) { _saved_head = (remember ? _head : NULL); }
  static GrowableArray<ClassLoaderData*>* new_clds();
  static void set_should_purge(bool b) { _should_purge = b; }
  static void purge_if_needed() {
    if (_should_purge) {
      purge();
      set_should_purge(false);
    }
  }
  static void free_deallocate_lists();
  static void dump_on(outputStream * const out) PRODUCT_RETURN;
  static void dump() { dump_on(tty); }
  static void verify();
  static bool unload_list_contains(const void* x);
#ifndef PRODUCT
  static bool contains_loader_data(ClassLoaderData* loader_data);
#endif
};
class ClassLoaderData : public CHeapObj<mtClass> {
  friend class VMStructs;
 private:
  class Dependencies VALUE_OBJ_CLASS_SPEC {
    objArrayOop _list_head;
    void locked_add(objArrayHandle last,
                    objArrayHandle new_dependency,
                    Thread* THREAD);
   public:
    Dependencies() : _list_head(NULL) {}
    Dependencies(TRAPS) : _list_head(NULL) {
      init(CHECK);
    }
    void add(Handle dependency, TRAPS);
    void init(TRAPS);
    void oops_do(OopClosure* f);
  };
  class ChunkedHandleList VALUE_OBJ_CLASS_SPEC {
    struct Chunk : public CHeapObj<mtClass> {
      static const size_t CAPACITY = 32;
      oop _data[CAPACITY];
      volatile juint _size;
      Chunk* _next;
      Chunk(Chunk* c) : _next(c), _size(0) { }
    };
    Chunk* _head;
    void oops_do_chunk(OopClosure* f, Chunk* c, const juint size);
   public:
    ChunkedHandleList() : _head(NULL) {}
    ~ChunkedHandleList();
    oop* add(oop o);
    void oops_do(OopClosure* f);
  };
  friend class ClassLoaderDataGraph;
  friend class ClassLoaderDataGraphKlassIteratorAtomic;
  friend class ClassLoaderDataGraphMetaspaceIterator;
  friend class MetaDataFactory;
  friend class Method;
  static ClassLoaderData * _the_null_class_loader_data;
  oop _class_loader;          // oop used to uniquely identify a class loader
  Dependencies _dependencies; // holds dependencies from this class loader
  Metaspace * _metaspace;  // Meta-space where meta-data defined by the
  Mutex* _metaspace_lock;  // Locks the metaspace for allocations and setup.
  bool _unloading;         // true if this class loader goes away
  bool _keep_alive;        // if this CLD is kept alive without a keep_alive_object().
  bool _is_anonymous;      // if this CLD is for an anonymous class
  volatile int _claimed;   // true if claimed, for example during GC traces.
  Klass* _klasses;         // The classes defined by the class loader.
  ChunkedHandleList _handles; // Handles to constant pool arrays, etc, which
  JNIMethodBlock*                  _jmethod_ids;
  GrowableArray<Metadata*>*      _deallocate_list;
  ClassLoaderData* _next; /// Next loader_datas created
  static Metaspace* _ro_metaspace;
  static Metaspace* _rw_metaspace;
  JFR_ONLY(DEFINE_TRACE_ID_FIELD;)
  void set_next(ClassLoaderData* next) { _next = next; }
  ClassLoaderData* next() const        { return _next; }
  ClassLoaderData(Handle h_class_loader, bool is_anonymous, Dependencies dependencies);
  ~ClassLoaderData();
  void set_metaspace(Metaspace* m) { _metaspace = m; }
  Mutex* metaspace_lock() const { return _metaspace_lock; }
  void unload();
  bool keep_alive() const       { return _keep_alive; }
  void classes_do(void f(Klass*));
  void loaded_classes_do(KlassClosure* klass_closure);
  void classes_do(void f(InstanceKlass*));
  void free_deallocate_list();
  MetaWord* allocate(size_t size);
 public:
  void clear_claimed()          { _claimed = 0; }
  bool claimed() const          { return _claimed == 1; }
  bool claim();
  bool is_alive(BoolObjectClosure* is_alive_closure) const;
  Metaspace* metaspace_or_null() const     { return _metaspace; }
  static ClassLoaderData* the_null_class_loader_data() {
    return _the_null_class_loader_data;
  }
  bool is_anonymous() const { return _is_anonymous; }
  static void init_null_class_loader_data() {
    assert(_the_null_class_loader_data == NULL, "cannot initialize twice");
    assert(ClassLoaderDataGraph::_head == NULL, "cannot initialize twice");
    _the_null_class_loader_data = new ClassLoaderData((oop)NULL, false, Dependencies());
    ClassLoaderDataGraph::_head = _the_null_class_loader_data;
    assert(_the_null_class_loader_data->is_the_null_class_loader_data(), "Must be");
    if (DumpSharedSpaces) {
      _the_null_class_loader_data->initialize_shared_metaspaces();
    }
  }
  bool is_the_null_class_loader_data() const {
    return this == _the_null_class_loader_data;
  }
  bool is_ext_class_loader_data() const;
  Metaspace* metaspace_non_null();
  oop class_loader() const      { return _class_loader; }
  oop keep_alive_object() const;
  bool is_unloading() const     {
    assert(!(is_the_null_class_loader_data() && _unloading), "The null class loader can never be unloaded");
    return _unloading;
  }
  void set_keep_alive(bool value) { _keep_alive = value; }
  unsigned int identity_hash() {
    return _class_loader == NULL ? 0 : _class_loader->identity_hash();
  }
  void oops_do(OopClosure* f, KlassClosure* klass_closure, bool must_claim);
  void classes_do(KlassClosure* klass_closure);
  JNIMethodBlock* jmethod_ids() const              { return _jmethod_ids; }
  void set_jmethod_ids(JNIMethodBlock* new_block)  { _jmethod_ids = new_block; }
  void print_value() { print_value_on(tty); }
  void print_value_on(outputStream* out) const;
  void dump(outputStream * const out) PRODUCT_RETURN;
  void verify();
  const char* loader_name();
  jobject add_handle(Handle h);
  void add_class(Klass* k);
  void remove_class(Klass* k);
  bool contains_klass(Klass* k);
  void record_dependency(Klass* to, TRAPS);
  void init_dependencies(TRAPS);
  void add_to_deallocate_list(Metadata* m);
  static ClassLoaderData* class_loader_data(oop loader);
  static ClassLoaderData* class_loader_data_or_null(oop loader);
  static ClassLoaderData* anonymous_class_loader_data(oop loader, TRAPS);
  static void print_loader(ClassLoaderData *loader_data, outputStream *out);
  Metaspace* ro_metaspace();
  Metaspace* rw_metaspace();
  void initialize_shared_metaspaces();
  JFR_ONLY(DEFINE_TRACE_ID_METHODS;)
};
class ClassLoaderDataGraphKlassIteratorAtomic : public StackObj {
 Klass* volatile _next_klass;
 public:
  ClassLoaderDataGraphKlassIteratorAtomic();
  Klass* next_klass();
 private:
  static Klass* next_klass_in_cldg(Klass* klass);
};
class ClassLoaderDataGraphMetaspaceIterator : public StackObj {
  ClassLoaderData* _data;
 public:
  ClassLoaderDataGraphMetaspaceIterator();
  ~ClassLoaderDataGraphMetaspaceIterator();
  bool repeat() { return _data != NULL; }
  Metaspace* get_next() {
    assert(_data != NULL, "Should not be NULL in call to the iterator");
    Metaspace* result = _data->metaspace_or_null();
    _data = _data->next();
    return result;
  }
};
#endif // SHARE_VM_CLASSFILE_CLASSLOADERDATA_HPP
C:\hotspot-69087d08d473\src\share\vm/classfile/classLoaderData.inline.hpp
#include "classfile/classLoaderData.hpp"
#include "classfile/javaClasses.hpp"
inline ClassLoaderData* ClassLoaderData::class_loader_data_or_null(oop loader) {
  if (loader == NULL) {
    return ClassLoaderData::the_null_class_loader_data();
  }
  return java_lang_ClassLoader::loader_data(loader);
}
inline ClassLoaderData* ClassLoaderData::class_loader_data(oop loader) {
  ClassLoaderData* loader_data = class_loader_data_or_null(loader);
  assert(loader_data != NULL, "Must be");
  return loader_data;
}
inline ClassLoaderData *ClassLoaderDataGraph::find_or_create(Handle loader, TRAPS) {
  guarantee(loader() != NULL && loader()->is_oop(), "Loader must be oop");
  ClassLoaderData* loader_data= java_lang_ClassLoader::loader_data(loader());
  if (loader_data) {
     return loader_data;
  }
  return ClassLoaderDataGraph::add(loader, false, THREAD);
}
C:\hotspot-69087d08d473\src\share\vm/classfile/classLoaderExt.hpp
#ifndef SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
#define SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
#include "classfile/classLoader.hpp"
class ClassLoaderExt: public ClassLoader { // AllStatic
public:
  class Context {
    const char* _file_name;
  public:
    Context(const char* class_name, const char* file_name, TRAPS) {
      _file_name = file_name;
    }
    bool check(ClassFileStream* stream, const int classpath_index) {
      return true;
    }
    bool should_verify(int classpath_index) {
      return false;
    }
    instanceKlassHandle record_result(const int classpath_index,
                                      ClassPathEntry* e, instanceKlassHandle result, TRAPS) {
      if (ClassLoader::add_package(_file_name, classpath_index, THREAD)) {
        if (DumpSharedSpaces) {
          result->set_shared_classpath_index(classpath_index);
        }
        return result;
      } else {
        return instanceKlassHandle(); // NULL
      }
    }
  };
  static void add_class_path_entry(const char* path, bool check_for_duplicates,
                                   ClassPathEntry* new_entry) {
    ClassLoader::add_to_list(new_entry);
  }
  static void append_boot_classpath(ClassPathEntry* new_entry) {
    ClassLoader::add_to_list(new_entry);
  }
  static void setup_search_paths() {}
  static void init_lookup_cache(TRAPS) {}
  static void copy_lookup_cache_to_archive(char** top, char* end) {}
  static char* restore_lookup_cache_from_archive(char* buffer) {return buffer;}
  static inline bool is_lookup_cache_enabled() {return false;}
  static bool known_to_not_exist(JNIEnv *env, jobject loader, const char *classname, TRAPS) {return false;}
  static jobjectArray get_lookup_cache_urls(JNIEnv *env, jobject loader, TRAPS) {return NULL;}
  static jintArray get_lookup_cache(JNIEnv *env, jobject loader, const char *pkgname, TRAPS) {return NULL;}
};
#endif // SHARE_VM_CLASSFILE_CLASSLOADEREXT_HPP
C:\hotspot-69087d08d473\src\share\vm/classfile/classLoaderStats.cpp
#include "precompiled.hpp"
#include "classfile/classLoaderStats.hpp"
#include "utilities/globalDefinitions.hpp"
class ClassStatsClosure : public KlassClosure {
public:
  int _num_classes;
  ClassStatsClosure() :
    _num_classes(0) {
  }
  virtual void do_klass(Klass* k) {
    _num_classes++;
  }
};
void ClassLoaderStatsClosure::do_cld(ClassLoaderData* cld) {
  oop cl = cld->class_loader();
  ClassLoaderStats* cls;
  ClassLoaderStats** cls_ptr = _stats->get(cl);
  if (cls_ptr == NULL) {
    cls = new ClassLoaderStats();
    _stats->put(cl, cls);
    _total_loaders++;
  } else {
    cls = *cls_ptr;
  }
  if (!cld->is_anonymous()) {
    cls->_cld = cld;
  }
  cls->_class_loader = cl;
  if (cl != NULL) {
    cls->_parent = java_lang_ClassLoader::parent(cl);
    addEmptyParents(cls->_parent);
  }
  ClassStatsClosure csc;
  cld->classes_do(&csc);
  if(cld->is_anonymous()) {
    cls->_anon_classes_count += csc._num_classes;
  } else {
    cls->_classes_count = csc._num_classes;
  }
  _total_classes += csc._num_classes;
  Metaspace* ms = cld->metaspace_or_null();
  if (ms != NULL) {
    if(cld->is_anonymous()) {
      cls->_anon_chunk_sz += ms->allocated_chunks_bytes();
      cls->_anon_block_sz += ms->allocated_blocks_bytes();
    } else {
      cls->_chunk_sz = ms->allocated_chunks_bytes();
      cls->_block_sz = ms->allocated_blocks_bytes();
    }
    _total_chunk_sz += ms->allocated_chunks_bytes();
    _total_block_sz += ms->allocated_blocks_bytes();
  }
}
#ifdef _LP64
  #define SPACE "%8s"
#else
  #define SPACE "%s"
#endif
bool ClassLoaderStatsClosure::do_entry(oop const& key, ClassLoaderStats* const& cls) {
  Klass* class_loader_klass = (cls->_class_loader == NULL ? NULL : cls->_class_loader->klass());
  Klass* parent_klass = (cls->_parent == NULL ? NULL : cls->_parent->klass());
  _out->print(INTPTR_FORMAT "  " INTPTR_FORMAT "  " INTPTR_FORMAT "  " UINTX_FORMAT_W(6) "  " SIZE_FORMAT_W(8) "  " SIZE_FORMAT_W(8) "  ",
      p2i(class_loader_klass), p2i(parent_klass), p2i(cls->_cld),
      cls->_classes_count,
      cls->_chunk_sz, cls->_block_sz);
  if (class_loader_klass != NULL) {
    _out->print("%s", class_loader_klass->external_name());
  } else {
    _out->print("<boot class loader>");
  }
  _out->cr();
  if (cls->_anon_classes_count > 0) {
    _out->print_cr(SPACE SPACE SPACE "                                    " UINTX_FORMAT_W(6) "  " SIZE_FORMAT_W(8) "  " SIZE_FORMAT_W(8) "   + unsafe anonymous classes",
        "", "", "",
        cls->_anon_classes_count,
        cls->_anon_chunk_sz, cls->_anon_block_sz);
  }
  return true;
}
void ClassLoaderStatsClosure::print() {
  _out->print_cr("ClassLoader" SPACE " Parent" SPACE "      CLD*" SPACE "       Classes   ChunkSz   BlockSz  Type", "", "", "");
  _stats->iterate(this);
  _out->print("Total = " UINTX_FORMAT_W(-6), _total_loaders);
  _out->print(SPACE SPACE SPACE "                      ", "", "", "");
  _out->print_cr(UINTX_FORMAT_W(6) "  " SIZE_FORMAT_W(8) "  " SIZE_FORMAT_W(8) "  ",
      _total_classes,
      _total_chunk_sz,
      _total_block_sz);
  _out->print_cr("ChunkSz: Total size of all allocated metaspace chunks");
  _out->print_cr("BlockSz: Total size of all allocated metaspace blocks (each chunk has several blocks)");
}
void ClassLoaderStatsClosure::addEmptyParents(oop cl) {
  while (cl != NULL && java_lang_ClassLoader::loader_data(cl) == NULL) {
    ClassLoaderStats** cls_ptr = _stats->get(cl);
    if (cls_ptr == NULL) {
      ClassLoaderStats* cls = new ClassLoaderStats();
      cls->_class_loader = cl;
      cls->_parent = java_lang_ClassLoader::parent(cl);
      _stats->put(cl, cls);
      _total_loaders++;
    }
    cl = java_lang_ClassLoader::parent(cl);
  }
}
void ClassLoaderStatsVMOperation::doit() {
  ClassLoaderStatsClosure clsc (_out);
  ClassLoaderDataGraph::cld_do(&clsc);
  clsc.print();
}
void ClassLoaderStatsDCmd::execute(DCmdSource source, TRAPS) {
  ClassLoaderStatsVMOperation op(output());
  VMThread::execute(&op);
}
C:\hotspot-69087d08d473\src\share\vm/classfile/classLoaderStats.hpp
#ifndef SHARE_VM_CLASSFILE_CLASSLOADERSTATS_HPP
#define SHARE_VM_CLASSFILE_CLASSLOADERSTATS_HPP
#include "classfile/classLoaderData.hpp"
#include "oops/klass.hpp"
#include "oops/oopsHierarchy.hpp"
#include "runtime/vm_operations.hpp"
#include "services/diagnosticCommand.hpp"
#include "utilities/resourceHash.hpp"
class ClassLoaderStatsDCmd : public DCmd {
public:
  ClassLoaderStatsDCmd(outputStream* output, bool heap) :
    DCmd(output, heap) {
  }
  static const char* name() {
    return "VM.classloader_stats";
  }
  static const char* description() {
    return "Print statistics about all ClassLoaders.";
  }
  static const char* impact() {
    return "Low";
  }
  virtual void execute(DCmdSource source, TRAPS);
  static int num_arguments() {
    return 0;
  }
  static const JavaPermission permission() {
    JavaPermission p = {"java.lang.management.ManagementPermission",
                        "monitor", NULL};
    return p;
  }
};
class ClassLoaderStats : public ResourceObj {
public:
  ClassLoaderData*  _cld;
  oop               _class_loader;
  oop               _parent;
  size_t            _chunk_sz;
  size_t            _block_sz;
  uintx             _classes_count;
  size_t            _anon_chunk_sz;
  size_t            _anon_block_sz;
  uintx             _anon_classes_count;
  ClassLoaderStats() :
    _cld(0),
    _class_loader(0),
    _parent(0),
    _chunk_sz(0),
    _block_sz(0),
    _classes_count(0),
    _anon_block_sz(0),
    _anon_chunk_sz(0),
    _anon_classes_count(0) {
  }
};
class ClassLoaderStatsClosure : public CLDClosure {
protected:
  static bool oop_equals(oop const& s1, oop const& s2) {
    return s1 == s2;
  }
  static unsigned oop_hash(oop const& s1) {
    uintptr_t tmp = cast_from_oop<uintptr_t>(s1);
    unsigned hash = (unsigned)tmp;
    hash = ~hash + (hash << 15);
    hash = hash ^ (hash >> 12);
    hash = hash + (hash << 2);
    hash = hash ^ (hash >> 4);
    hash = hash * 2057;
    hash = hash ^ (hash >> 16);
    return hash;
  }
  typedef ResourceHashtable<oop, ClassLoaderStats*,
      ClassLoaderStatsClosure::oop_hash, ClassLoaderStatsClosure::oop_equals> StatsTable;
  outputStream* _out;
  StatsTable* _stats;
  uintx   _total_loaders;
  uintx   _total_classes;
  size_t  _total_chunk_sz;
  size_t  _total_block_sz;
public:
  ClassLoaderStatsClosure(outputStream* out) :
    _out(out),
    _total_loaders(0),
    _total_block_sz(0),
    _total_chunk_sz(0),
    _total_classes(0),
    _stats(new StatsTable()) {
  }
  virtual void do_cld(ClassLoaderData* cld);
  virtual bool do_entry(oop const& key, ClassLoaderStats* const& cls);
  void print();
private:
  void addEmptyParents(oop cl);
};
class ClassLoaderStatsVMOperation : public VM_Operation {
  outputStream* _out;
public:
  ClassLoaderStatsVMOperation(outputStream* out) :
    _out(out) {
  }
  VMOp_Type type() const {
    return VMOp_ClassLoaderStatsOperation;
  }
  void doit();
};
#endif // SHARE_VM_CLASSFILE_CLASSLOADERSTATS_HPP
C:\hotspot-69087d08d473\src\share\vm/classfile/defaultMethods.cpp
#include "precompiled.hpp"
#include "classfile/bytecodeAssembler.hpp"
#include "classfile/defaultMethods.hpp"
#include "classfile/symbolTable.hpp"
#include "memory/allocation.hpp"
#include "memory/metadataFactory.hpp"
#include "memory/resourceArea.hpp"
#include "runtime/signature.hpp"
#include "runtime/thread.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/klass.hpp"
#include "oops/method.hpp"
#include "utilities/accessFlags.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/ostream.hpp"
#include "utilities/pair.hpp"
#include "utilities/resourceHash.hpp"
typedef enum { QUALIFIED, DISQUALIFIED } QualifiedState;
class PseudoScopeMark : public ResourceObj {
 public:
  virtual void destroy() = 0;
};
class PseudoScope : public ResourceObj {
 private:
  GrowableArray<PseudoScopeMark*> _marks;
 public:
  static PseudoScope* cast(void* data) {
    return static_cast<PseudoScope*>(data);
  }
  void add_mark(PseudoScopeMark* psm) {
   _marks.append(psm);
  }
  void destroy() {
    for (int i = 0; i < _marks.length(); ++i) {
      _marks.at(i)->destroy();
    }
  }
};
#ifndef PRODUCT
static void print_slot(outputStream* str, Symbol* name, Symbol* signature) {
  ResourceMark rm;
  str->print("%s%s", name->as_C_string(), signature->as_C_string());
}
static void print_method(outputStream* str, Method* mo, bool with_class=true) {
  ResourceMark rm;
  if (with_class) {
    str->print("%s.", mo->klass_name()->as_C_string());
  }
  print_slot(str, mo->name(), mo->signature());
}
#endif // ndef PRODUCT
template <class ALGO>
class HierarchyVisitor : StackObj {
 private:
  class Node : public ResourceObj {
   public:
    InstanceKlass* _class;
    bool _super_was_visited;
    int _interface_index;
    void* _algorithm_data;
    Node(InstanceKlass* cls, void* data, bool visit_super)
        : _class(cls), _super_was_visited(!visit_super),
          _interface_index(0), _algorithm_data(data) {}
    int number_of_interfaces() { return _class->local_interfaces()->length(); }
    int interface_index() { return _interface_index; }
    void set_super_visited() { _super_was_visited = true; }
    void increment_visited_interface() { ++_interface_index; }
    void set_all_interfaces_visited() {
      _interface_index = number_of_interfaces();
    }
    bool has_visited_super() { return _super_was_visited; }
    bool has_visited_all_interfaces() {
      return interface_index() >= number_of_interfaces();
    }
    InstanceKlass* interface_at(int index) {
      return InstanceKlass::cast(_class->local_interfaces()->at(index));
    }
    InstanceKlass* next_super() { return _class->java_super(); }
    InstanceKlass* next_interface() {
      return interface_at(interface_index());
    }
  };
  bool _cancelled;
  GrowableArray<Node*> _path;
  Node* current_top() const { return _path.top(); }
  bool has_more_nodes() const { return !_path.is_empty(); }
  void push(InstanceKlass* cls, void* data) {
    assert(cls != NULL, "Requires a valid instance class");
    Node* node = new Node(cls, data, has_super(cls));
    _path.push(node);
  }
  void pop() { _path.pop(); }
  void reset_iteration() {
    _cancelled = false;
    _path.clear();
  }
  bool is_cancelled() const { return _cancelled; }
  static bool has_super(InstanceKlass* cls) {
    return cls->super() != NULL;
  }
  Node* node_at_depth(int i) const {
    return (i >= _path.length()) ? NULL : _path.at(_path.length() - i - 1);
  }
 protected:
  int current_depth() const { return _path.length() - 1; }
  InstanceKlass* class_at_depth(int i) {
    Node* n = node_at_depth(i);
    return n == NULL ? NULL : n->_class;
  }
  InstanceKlass* current_class() { return class_at_depth(0); }
  void* data_at_depth(int i) {
    Node* n = node_at_depth(i);
    return n == NULL ? NULL : n->_algorithm_data;
  }
  void* current_data() { return data_at_depth(0); }
  void cancel_iteration() { _cancelled = true; }
 public:
  void run(InstanceKlass* root) {
    ALGO* algo = static_cast<ALGO*>(this);
    reset_iteration();
    void* algo_data = algo->new_node_data(root);
    push(root, algo_data);
    bool top_needs_visit = true;
    do {
      Node* top = current_top();
      if (top_needs_visit) {
        if (algo->visit() == false) {
          top->set_super_visited();
          top->set_all_interfaces_visited();
        }
        top_needs_visit = false;
      }
      if (top->has_visited_super() && top->has_visited_all_interfaces()) {
        algo->free_node_data(top->_algorithm_data);
        pop();
      } else {
        InstanceKlass* next = NULL;
        if (top->has_visited_super() == false) {
          next = top->next_super();
          top->set_super_visited();
        } else {
          next = top->next_interface();
          top->increment_visited_interface();
        }
        assert(next != NULL, "Otherwise we shouldn't be here");
        algo_data = algo->new_node_data(next);
        push(next, algo_data);
        top_needs_visit = true;
      }
    } while (!is_cancelled() && has_more_nodes());
  }
};
#ifndef PRODUCT
class PrintHierarchy : public HierarchyVisitor<PrintHierarchy> {
 public:
  bool visit() {
    InstanceKlass* cls = current_class();
    streamIndentor si(tty, current_depth() * 2);
    tty->indent().print_cr("%s", cls->name()->as_C_string());
    return true;
  }
  void* new_node_data(InstanceKlass* cls) { return NULL; }
  void free_node_data(void* data) { return; }
};
#endif // ndef PRODUCT
class KeepAliveRegistrar : public StackObj {
 private:
  Thread* _thread;
  GrowableArray<ConstantPool*> _keep_alive;
 public:
  KeepAliveRegistrar(Thread* thread) : _thread(thread), _keep_alive(20) {
    assert(thread == Thread::current(), "Must be current thread");
  }
  ~KeepAliveRegistrar() {
    for (int i = _keep_alive.length() - 1; i >= 0; --i) {
      ConstantPool* cp = _keep_alive.at(i);
      int idx = _thread->metadata_handles()->find_from_end(cp);
      assert(idx > 0, "Must be in the list");
      _thread->metadata_handles()->remove_at(idx);
    }
  }
  void register_class(InstanceKlass* ik) {
    ConstantPool* cp = ik->constants();
    _keep_alive.push(cp);
    _thread->metadata_handles()->push(cp);
  }
};
class KeepAliveVisitor : public HierarchyVisitor<KeepAliveVisitor> {
 private:
  KeepAliveRegistrar* _registrar;
 public:
  KeepAliveVisitor(KeepAliveRegistrar* registrar) : _registrar(registrar) {}
  void* new_node_data(InstanceKlass* cls) { return NULL; }
  void free_node_data(void* data) { return; }
  bool visit() {
    _registrar->register_class(current_class());
    return true;
  }
};
class MethodFamily : public ResourceObj {
 private:
  GrowableArray<Pair<Method*,QualifiedState> > _members;
  ResourceHashtable<Method*, int> _member_index;
  Method* _selected_target;  // Filled in later, if a unique target exists
  Symbol* _exception_message; // If no unique target is found
  Symbol* _exception_name;    // If no unique target is found
  bool contains_method(Method* method) {
    int* lookup = _member_index.get(method);
    return lookup != NULL;
  }
  void add_method(Method* method, QualifiedState state) {
    Pair<Method*,QualifiedState> entry(method, state);
    _member_index.put(method, _members.length());
    _members.append(entry);
  }
  void disqualify_method(Method* method) {
    int* index = _member_index.get(method);
    guarantee(index != NULL && *index >= 0 && *index < _members.length(), "bad index");
    _members.at(*index).second = DISQUALIFIED;
  }
  Symbol* generate_no_defaults_message(TRAPS) const;
  Symbol* generate_method_message(Symbol *klass_name, Method* method, TRAPS) const;
  Symbol* generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const;
 public:
  MethodFamily()
      : _selected_target(NULL), _exception_message(NULL), _exception_name(NULL) {}
  void set_target_if_empty(Method* m) {
    if (_selected_target == NULL && !m->is_overpass()) {
      _selected_target = m;
    }
  }
  void record_qualified_method(Method* m) {
    if (!contains_method(m)) {
      add_method(m, QUALIFIED);
    }
  }
  void record_disqualified_method(Method* m) {
    if (!contains_method(m)) {
      add_method(m, DISQUALIFIED);
    } else {
      disqualify_method(m);
    }
  }
  bool has_target() const { return _selected_target != NULL; }
  bool throws_exception() { return _exception_message != NULL; }
  Method* get_selected_target() { return _selected_target; }
  Symbol* get_exception_message() { return _exception_message; }
  Symbol* get_exception_name() { return _exception_name; }
  void determine_target(InstanceKlass* root, TRAPS) {
    if (has_target() || throws_exception()) {
      return;
    }
    GrowableArray<Method*> qualified_methods;
    int num_defaults = 0;
    int default_index = -1;
    int qualified_index = -1;
    for (int i = 0; i < _members.length(); ++i) {
      Pair<Method*,QualifiedState> entry = _members.at(i);
      if (entry.second == QUALIFIED) {
        qualified_methods.append(entry.first);
        qualified_index++;
        if (entry.first->is_default_method()) {
          num_defaults++;
          default_index = qualified_index;
        }
      }
    }
    if (num_defaults == 0) {
      if (qualified_methods.length() == 0) {
        _exception_message = generate_no_defaults_message(CHECK);
      } else {
        assert(root != NULL, "Null root class");
        _exception_message = generate_method_message(root->name(), qualified_methods.at(0), CHECK);
      }
      _exception_name = vmSymbols::java_lang_AbstractMethodError();
    } else if (num_defaults == 1) {
        _selected_target = qualified_methods.at(default_index);
    } else if (num_defaults > 1) {
      _exception_message = generate_conflicts_message(&qualified_methods,CHECK);
      _exception_name = vmSymbols::java_lang_IncompatibleClassChangeError();
      if (TraceDefaultMethods) {
        _exception_message->print_value_on(tty);
        tty->cr();
      }
    }
  }
  bool contains_signature(Symbol* query) {
    for (int i = 0; i < _members.length(); ++i) {
      if (query == _members.at(i).first->signature()) {
        return true;
      }
    }
    return false;
  }
#ifndef PRODUCT
  void print_sig_on(outputStream* str, Symbol* signature, int indent) const {
    streamIndentor si(str, indent * 2);
    str->indent().print_cr("Logical Method %s:", signature->as_C_string());
    streamIndentor si2(str);
    for (int i = 0; i < _members.length(); ++i) {
      str->indent();
      print_method(str, _members.at(i).first);
      if (_members.at(i).second == DISQUALIFIED) {
        str->print(" (disqualified)");
      }
      str->cr();
    }
    if (_selected_target != NULL) {
      print_selected(str, 1);
    }
  }
  void print_selected(outputStream* str, int indent) const {
    assert(has_target(), "Should be called otherwise");
    streamIndentor si(str, indent * 2);
    str->indent().print("Selected method: ");
    print_method(str, _selected_target);
    Klass* method_holder = _selected_target->method_holder();
    if (!method_holder->is_interface()) {
      tty->print(" : in superclass");
    }
    str->cr();
  }
  void print_exception(outputStream* str, int indent) {
    assert(throws_exception(), "Should be called otherwise");
    assert(_exception_name != NULL, "exception_name should be set");
    streamIndentor si(str, indent * 2);
    str->indent().print_cr("%s: %s", _exception_name->as_C_string(), _exception_message->as_C_string());
  }
#endif // ndef PRODUCT
};
Symbol* MethodFamily::generate_no_defaults_message(TRAPS) const {
  return SymbolTable::new_symbol("No qualifying defaults found", THREAD);
}
Symbol* MethodFamily::generate_method_message(Symbol *klass_name, Method* method, TRAPS) const {
  stringStream ss;
  ss.print("Method ");
  Symbol* name = method->name();
  Symbol* signature = method->signature();
  ss.write((const char*)klass_name->bytes(), klass_name->utf8_length());
  ss.print(".");
  ss.write((const char*)name->bytes(), name->utf8_length());
  ss.write((const char*)signature->bytes(), signature->utf8_length());
  ss.print(" is abstract");
  return SymbolTable::new_symbol(ss.base(), (int)ss.size(), THREAD);
}
Symbol* MethodFamily::generate_conflicts_message(GrowableArray<Method*>* methods, TRAPS) const {
  stringStream ss;
  ss.print("Conflicting default methods:");
  for (int i = 0; i < methods->length(); ++i) {
    Method* method = methods->at(i);
    Symbol* klass = method->klass_name();
    Symbol* name = method->name();
    ss.print(" ");
    ss.write((const char*)klass->bytes(), klass->utf8_length());
    ss.print(".");
    ss.write((const char*)name->bytes(), name->utf8_length());
  }
  return SymbolTable::new_symbol(ss.base(), (int)ss.size(), THREAD);
}
class StateRestorer;
class StatefulMethodFamily : public ResourceObj {
  friend class StateRestorer;
 private:
  QualifiedState _qualification_state;
  void set_qualification_state(QualifiedState state) {
    _qualification_state = state;
  }
 protected:
  MethodFamily* _method_family;
 public:
  StatefulMethodFamily() {
   _method_family = new MethodFamily();
   _qualification_state = QUALIFIED;
  }
  StatefulMethodFamily(MethodFamily* mf) {
   _method_family = mf;
   _qualification_state = QUALIFIED;
  }
  void set_target_if_empty(Method* m) { _method_family->set_target_if_empty(m); }
  MethodFamily* get_method_family() { return _method_family; }
  StateRestorer* record_method_and_dq_further(Method* mo);
};
class StateRestorer : public PseudoScopeMark {
 private:
  StatefulMethodFamily* _method;
  QualifiedState _state_to_restore;
 public:
  StateRestorer(StatefulMethodFamily* dm, QualifiedState state)
      : _method(dm), _state_to_restore(state) {}
  ~StateRestorer() { destroy(); }
  void restore_state() { _method->set_qualification_state(_state_to_restore); }
  virtual void destroy() { restore_state(); }
};
StateRestorer* StatefulMethodFamily::record_method_and_dq_further(Method* mo) {
  StateRestorer* mark = new StateRestorer(this, _qualification_state);
  if (_qualification_state == QUALIFIED) {
    _method_family->record_qualified_method(mo);
  } else {
    _method_family->record_disqualified_method(mo);
  }
  set_qualification_state(DISQUALIFIED);
  return mark;
}
class EmptyVtableSlot : public ResourceObj {
 private:
  Symbol* _name;
  Symbol* _signature;
  int _size_of_parameters;
  MethodFamily* _binding;
 public:
  EmptyVtableSlot(Method* method)
      : _name(method->name()), _signature(method->signature()),
        _size_of_parameters(method->size_of_parameters()), _binding(NULL) {}
  Symbol* name() const { return _name; }
  Symbol* signature() const { return _signature; }
  int size_of_parameters() const { return _size_of_parameters; }
  void bind_family(MethodFamily* lm) { _binding = lm; }
  bool is_bound() { return _binding != NULL; }
  MethodFamily* get_binding() { return _binding; }
#ifndef PRODUCT
  void print_on(outputStream* str) const {
    print_slot(str, name(), signature());
  }
#endif // ndef PRODUCT
};
static bool already_in_vtable_slots(GrowableArray<EmptyVtableSlot*>* slots, Method* m) {
  bool found = false;
  for (int j = 0; j < slots->length(); ++j) {
    if (slots->at(j)->name() == m->name() &&
        slots->at(j)->signature() == m->signature() ) {
      found = true;
      break;
    }
  }
  return found;
}
static GrowableArray<EmptyVtableSlot*>* find_empty_vtable_slots(
    InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) {
  assert(klass != NULL, "Must be valid class");
  GrowableArray<EmptyVtableSlot*>* slots = new GrowableArray<EmptyVtableSlot*>();
  for (int i = 0; i < mirandas->length(); ++i) {
    Method* m = mirandas->at(i);
    if (!already_in_vtable_slots(slots, m)) {
      slots->append(new EmptyVtableSlot(m));
    }
  }
  InstanceKlass* super = klass->java_super();
  while (super != NULL) {
    for (int i = 0; i < super->methods()->length(); ++i) {
      Method* m = super->methods()->at(i);
      if (m->is_overpass() || m->is_static()) {
        Method* impl = klass->lookup_method(m->name(), m->signature());
        if (impl == NULL || impl->is_overpass() || impl->is_static()) {
          if (!already_in_vtable_slots(slots, m)) {
            slots->append(new EmptyVtableSlot(m));
          }
        }
      }
    }
    if (super->default_methods() != NULL) {
      for (int i = 0; i < super->default_methods()->length(); ++i) {
        Method* m = super->default_methods()->at(i);
        Method* impl = klass->lookup_method(m->name(), m->signature());
        if (impl == NULL || impl->is_overpass() || impl->is_static()) {
          if (!already_in_vtable_slots(slots, m)) {
            slots->append(new EmptyVtableSlot(m));
          }
        }
      }
    }
    super = super->java_super();
  }
#ifndef PRODUCT
  if (TraceDefaultMethods) {
    tty->print_cr("Slots that need filling:");
    streamIndentor si(tty);
    for (int i = 0; i < slots->length(); ++i) {
      tty->indent();
      slots->at(i)->print_on(tty);
      tty->cr();
    }
  }
#endif // ndef PRODUCT
  return slots;
}
class FindMethodsByErasedSig : public HierarchyVisitor<FindMethodsByErasedSig> {
 private:
  Symbol* _method_name;
  Symbol* _method_signature;
  StatefulMethodFamily*  _family;
 public:
  FindMethodsByErasedSig(Symbol* name, Symbol* signature) :
      _method_name(name), _method_signature(signature),
      _family(NULL) {}
  void get_discovered_family(MethodFamily** family) {
      if (_family != NULL) {
      } else {
      }
  }
  void* new_node_data(InstanceKlass* cls) { return new PseudoScope(); }
  void free_node_data(void* node_data) {
    PseudoScope::cast(node_data)->destroy();
  }
  bool visit() {
    PseudoScope* scope = PseudoScope::cast(current_data());
    InstanceKlass* iklass = current_class();
    Method* m = iklass->find_method(_method_name, _method_signature);
    if (m != NULL && !m->is_static() && !m->is_overpass() && !m->is_private()) {
      if (_family == NULL) {
        _family = new StatefulMethodFamily();
      }
      if (iklass->is_interface()) {
        StateRestorer* restorer = _family->record_method_and_dq_further(m);
        scope->add_mark(restorer);
      } else {
        _family->set_target_if_empty(m);
      }
    }
    return true;
  }
};
static void create_defaults_and_exceptions(
    GrowableArray<EmptyVtableSlot*>* slots, InstanceKlass* klass, TRAPS);
static void generate_erased_defaults(
     InstanceKlass* klass, GrowableArray<EmptyVtableSlot*>* empty_slots,
     EmptyVtableSlot* slot, TRAPS) {
  FindMethodsByErasedSig visitor(slot->name(), slot->signature());
  visitor.run(klass);
  MethodFamily* family;
  visitor.get_discovered_family(&family);
  if (family != NULL) {
    family->determine_target(klass, CHECK);
    slot->bind_family(family);
  }
}
static void merge_in_new_methods(InstanceKlass* klass,
    GrowableArray<Method*>* new_methods, TRAPS);
static void create_default_methods( InstanceKlass* klass,
    GrowableArray<Method*>* new_methods, TRAPS);
void DefaultMethods::generate_default_methods(
    InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS) {
  ResourceMark rm(THREAD);
  KeepAliveRegistrar keepAlive(THREAD);
  KeepAliveVisitor loadKeepAlive(&keepAlive);
  loadKeepAlive.run(klass);
#ifndef PRODUCT
  if (TraceDefaultMethods) {
    ResourceMark rm;  // be careful with these!
    tty->print_cr("%s %s requires default method processing",
        klass->is_interface() ? "Interface" : "Class",
        klass->name()->as_klass_external_name());
    PrintHierarchy printer;
    printer.run(klass);
  }
#endif // ndef PRODUCT
  GrowableArray<EmptyVtableSlot*>* empty_slots =
      find_empty_vtable_slots(klass, mirandas, CHECK);
  for (int i = 0; i < empty_slots->length(); ++i) {
    EmptyVtableSlot* slot = empty_slots->at(i);
#ifndef PRODUCT
    if (TraceDefaultMethods) {
      streamIndentor si(tty, 2);
      tty->indent().print("Looking for default methods for slot ");
      slot->print_on(tty);
      tty->cr();
    }
#endif // ndef PRODUCT
    generate_erased_defaults(klass, empty_slots, slot, CHECK);
 }
#ifndef PRODUCT
  if (TraceDefaultMethods) {
    tty->print_cr("Creating defaults and overpasses...");
  }
#endif // ndef PRODUCT
  create_defaults_and_exceptions(empty_slots, klass, CHECK);
#ifndef PRODUCT
  if (TraceDefaultMethods) {
    tty->print_cr("Default method processing complete");
  }
#endif // ndef PRODUCT
}
static int assemble_method_error(
    BytecodeConstantPool* cp, BytecodeBuffer* buffer, Symbol* errorName, Symbol* message, TRAPS) {
  Symbol* init = vmSymbols::object_initializer_name();
  Symbol* sig = vmSymbols::string_void_signature();
  BytecodeAssembler assem(buffer, cp);
  assem._new(errorName);
  assem.dup();
  assem.load_string(message);
  assem.invokespecial(errorName, init, sig);
  assem.athrow();
  return 3; // max stack size: [ exception, exception, string ]
}
static Method* new_method(
    BytecodeConstantPool* cp, BytecodeBuffer* bytecodes, Symbol* name,
    Symbol* sig, AccessFlags flags, int max_stack, int params,
    ConstMethod::MethodType mt, TRAPS) {
  address code_start = 0;
  int code_length = 0;
  InlineTableSizes sizes;
  if (bytecodes != NULL && bytecodes->length() > 0) {
    code_start = static_cast<address>(bytecodes->adr_at(0));
    code_length = bytecodes->length();
  }
  Method* m = Method::allocate(cp->pool_holder()->class_loader_data(),
                               code_length, flags, &sizes,
                               mt, CHECK_NULL);
  m->set_constants(NULL); // This will get filled in later
  m->set_name_index(cp->utf8(name));
  m->set_signature_index(cp->utf8(sig));
  ResultTypeFinder rtf(sig);
  m->constMethod()->set_result_type(rtf.type());
  m->set_size_of_parameters(params);
  m->set_max_stack(max_stack);
  m->set_max_locals(params);
  m->constMethod()->set_stackmap_data(NULL);
  m->set_code(code_start);
  return m;
}
static void switchover_constant_pool(BytecodeConstantPool* bpool,
    InstanceKlass* klass, GrowableArray<Method*>* new_methods, TRAPS) {
  if (new_methods->length() > 0) {
    ConstantPool* cp = bpool->create_constant_pool(CHECK);
    if (cp != klass->constants()) {
      klass->class_loader_data()->add_to_deallocate_list(klass->constants());
      klass->set_constants(cp);
      cp->set_pool_holder(klass);
      for (int i = 0; i < new_methods->length(); ++i) {
        new_methods->at(i)->set_constants(cp);
      }
      for (int i = 0; i < klass->methods()->length(); ++i) {
        Method* mo = klass->methods()->at(i);
        mo->set_constants(cp);
      }
    }
  }
}
static void create_defaults_and_exceptions(
    GrowableArray<EmptyVtableSlot*>* slots,
    InstanceKlass* klass, TRAPS) {
  GrowableArray<Method*> overpasses;
  GrowableArray<Method*> defaults;
  BytecodeConstantPool bpool(klass->constants());
  for (int i = 0; i < slots->length(); ++i) {
    EmptyVtableSlot* slot = slots->at(i);
    if (slot->is_bound()) {
      MethodFamily* method = slot->get_binding();
      BytecodeBuffer buffer;
#ifndef PRODUCT
      if (TraceDefaultMethods) {
        tty->print("for slot: ");
        slot->print_on(tty);
        tty->cr();
        if (method->has_target()) {
          method->print_selected(tty, 1);
        } else if (method->throws_exception()) {
          method->print_exception(tty, 1);
        }
      }
#endif // ndef PRODUCT
      if (method->has_target()) {
        Method* selected = method->get_selected_target();
        if (selected->method_holder()->is_interface()) {
          defaults.push(selected);
        }
      } else if (method->throws_exception()) {
        int max_stack = assemble_method_error(&bpool, &buffer,
           method->get_exception_name(), method->get_exception_message(), CHECK);
        AccessFlags flags = accessFlags_from(
          JVM_ACC_PUBLIC | JVM_ACC_SYNTHETIC | JVM_ACC_BRIDGE);
         Method* m = new_method(&bpool, &buffer, slot->name(), slot->signature(),
          flags, max_stack, slot->size_of_parameters(),
          ConstMethod::OVERPASS, CHECK);
        if (m != NULL) {
          overpasses.push(m);
        }
      }
    }
  }
#ifndef PRODUCT
  if (TraceDefaultMethods) {
    tty->print_cr("Created %d overpass methods", overpasses.length());
    tty->print_cr("Created %d default  methods", defaults.length());
  }
#endif // ndef PRODUCT
  if (overpasses.length() > 0) {
    switchover_constant_pool(&bpool, klass, &overpasses, CHECK);
    merge_in_new_methods(klass, &overpasses, CHECK);
  }
  if (defaults.length() > 0) {
    create_default_methods(klass, &defaults, CHECK);
  }
}
static void create_default_methods( InstanceKlass* klass,
    GrowableArray<Method*>* new_methods, TRAPS) {
  int new_size = new_methods->length();
  Array<Method*>* total_default_methods = MetadataFactory::new_array<Method*>(
      klass->class_loader_data(), new_size, NULL, CHECK);
  for (int index = 0; index < new_size; index++ ) {
    total_default_methods->at_put(index, new_methods->at(index));
  }
  Method::sort_methods(total_default_methods, false, false);
  klass->set_default_methods(total_default_methods);
}
static void sort_methods(GrowableArray<Method*>* methods) {
  bool sorted = true;
  for (int i = methods->length() - 1; i > 0; --i) {
    for (int j = 0; j < i; ++j) {
      Method* m1 = methods->at(j);
      Method* m2 = methods->at(j + 1);
      if ((uintptr_t)m1->name() > (uintptr_t)m2->name()) {
        methods->at_put(j, m2);
        methods->at_put(j + 1, m1);
        sorted = false;
      }
    }
    if (sorted) break;
    sorted = true;
  }
#ifdef ASSERT
  uintptr_t prev = 0;
  for (int i = 0; i < methods->length(); ++i) {
    Method* mh = methods->at(i);
    uintptr_t nv = (uintptr_t)mh->name();
    assert(nv >= prev, "Incorrect overpass method ordering");
    prev = nv;
  }
#endif
}
static void merge_in_new_methods(InstanceKlass* klass,
    GrowableArray<Method*>* new_methods, TRAPS) {
  enum { ANNOTATIONS, PARAMETERS, DEFAULTS, NUM_ARRAYS };
  Array<Method*>* original_methods = klass->methods();
  Array<int>* original_ordering = klass->method_ordering();
  Array<int>* merged_ordering = Universe::the_empty_int_array();
  int new_size = klass->methods()->length() + new_methods->length();
  Array<Method*>* merged_methods = MetadataFactory::new_array<Method*>(
      klass->class_loader_data(), new_size, NULL, CHECK);
  if (JvmtiExport::can_maintain_original_method_order() || DumpSharedSpaces) {
    merged_ordering = MetadataFactory::new_array<int>(
        klass->class_loader_data(), new_size, CHECK);
  }
  int method_order_index = klass->methods()->length();
  sort_methods(new_methods);
  int orig_idx = 0;
  int new_idx = 0;
  for (int i = 0; i < new_size; ++i) {
    Method* orig_method = NULL;
    Method* new_method = NULL;
    if (orig_idx < original_methods->length()) {
      orig_method = original_methods->at(orig_idx);
    }
    if (new_idx < new_methods->length()) {
      new_method = new_methods->at(new_idx);
    }
    if (orig_method != NULL &&
        (new_method == NULL || orig_method->name() < new_method->name())) {
      merged_methods->at_put(i, orig_method);
      original_methods->at_put(orig_idx, NULL);
      if (merged_ordering->length() > 0) {
        assert(original_ordering != NULL && original_ordering->length() > 0,
               "should have original order information for this method");
        merged_ordering->at_put(i, original_ordering->at(orig_idx));
      }
      ++orig_idx;
    } else {
      merged_methods->at_put(i, new_method);
      if (merged_ordering->length() > 0) {
        merged_ordering->at_put(i, method_order_index++);
      }
      ++new_idx;
    }
    merged_methods->at(i)->set_method_idnum(i);
    merged_methods->at(i)->set_orig_method_idnum(i);
  }
#ifdef ASSERT
  uintptr_t prev = 0;
  for (int i = 0; i < merged_methods->length(); ++i) {
    Method* mo = merged_methods->at(i);
    uintptr_t nv = (uintptr_t)mo->name();
    assert(nv >= prev, "Incorrect method ordering");
    prev = nv;
  }
#endif
  klass->set_methods(merged_methods);
  klass->set_initial_method_idnum(new_size);
  klass->set_method_ordering(merged_ordering);
  ClassLoaderData* cld = klass->class_loader_data();
  if (original_methods->length() > 0) {
    MetadataFactory::free_array(cld, original_methods);
  }
  if (original_ordering != NULL && original_ordering->length() > 0) {
    MetadataFactory::free_array(cld, original_ordering);
  }
}
C:\hotspot-69087d08d473\src\share\vm/classfile/defaultMethods.hpp
#ifndef SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
#define SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
#include "runtime/handles.hpp"
#include "utilities/growableArray.hpp"
#include "utilities/exceptions.hpp"
class InstanceKlass;
class Symbol;
class Method;
class DefaultMethods : AllStatic {
 public:
  static void generate_default_methods(
      InstanceKlass* klass, GrowableArray<Method*>* mirandas, TRAPS);
};
#endif // SHARE_VM_CLASSFILE_DEFAULTMETHODS_HPP
C:\hotspot-69087d08d473\src\share\vm/classfile/dictionary.cpp
#include "precompiled.hpp"
#include "classfile/dictionary.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/systemDictionaryShared.hpp"
#include "memory/iterator.hpp"
#include "oops/oop.inline.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "runtime/orderAccess.inline.hpp"
#include "utilities/hashtable.inline.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
DictionaryEntry*  Dictionary::_current_class_entry = NULL;
int               Dictionary::_current_class_index =    0;
size_t Dictionary::entry_size() {
  if (DumpSharedSpaces) {
    return SystemDictionaryShared::dictionary_entry_size();
  } else {
    return sizeof(DictionaryEntry);
  }
}
Dictionary::Dictionary(int table_size)
  : TwoOopHashtable<Klass*, mtClass>(table_size, (int)entry_size()) {
  _current_class_index = 0;
  _current_class_entry = NULL;
  _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
};
Dictionary::Dictionary(int table_size, HashtableBucket<mtClass>* t,
                       int number_of_entries)
  : TwoOopHashtable<Klass*, mtClass>(table_size, (int)entry_size(), t, number_of_entries) {
  _current_class_index = 0;
  _current_class_entry = NULL;
  _pd_cache_table = new ProtectionDomainCacheTable(defaultProtectionDomainCacheSize);
};
ProtectionDomainCacheEntry* Dictionary::cache_get(oop protection_domain) {
  return _pd_cache_table->get(protection_domain);
}
DictionaryEntry* Dictionary::new_entry(unsigned int hash, Klass* klass,
                                       ClassLoaderData* loader_data) {
  DictionaryEntry* entry = (DictionaryEntry*)Hashtable<Klass*, mtClass>::new_entry(hash, klass);
  entry->set_loader_data(loader_data);
  entry->set_pd_set(NULL);
  assert(klass->oop_is_instance(), "Must be");
  if (DumpSharedSpaces) {
    SystemDictionaryShared::init_shared_dictionary_entry(klass, entry);
  }
  return entry;
}
void Dictionary::free_entry(DictionaryEntry* entry) {
  while (entry->pd_set() != NULL) {
    ProtectionDomainEntry* to_delete = entry->pd_set();
    entry->set_pd_set(to_delete->next());
    delete to_delete;
  }
  Hashtable<Klass*, mtClass>::free_entry(entry);
}
bool DictionaryEntry::contains_protection_domain(oop protection_domain) const {
#ifdef ASSERT
  if (protection_domain == InstanceKlass::cast(klass())->protection_domain()) {
    bool in_pd_set = false;
    for (ProtectionDomainEntry* current = _pd_set;
                                current != NULL;
                                current = current->next()) {
      if (current->protection_domain() == protection_domain) {
        in_pd_set = true;
        break;
      }
    }
    if (in_pd_set) {
      assert(false, "A klass's protection domain should not show up "
                    "in its sys. dict. PD set");
    }
  }
#endif /* ASSERT */
  if (protection_domain == InstanceKlass::cast(klass())->protection_domain()) {
    return true;
  }
  for (ProtectionDomainEntry* current = _pd_set;
                              current != NULL;
                              current = current->next()) {
    if (current->protection_domain() == protection_domain) return true;
  }
  return false;
}
void DictionaryEntry::add_protection_domain(Dictionary* dict, oop protection_domain) {
  assert_locked_or_safepoint(SystemDictionary_lock);
  if (!contains_protection_domain(protection_domain)) {
    ProtectionDomainCacheEntry* entry = dict->cache_get(protection_domain);
    ProtectionDomainEntry* new_head =
                new ProtectionDomainEntry(entry, _pd_set);
    OrderAccess::release_store_ptr(&_pd_set, new_head);
  }
  if (TraceProtectionDomainVerification && WizardMode) {
    print();
  }
}
void Dictionary::do_unloading() {
  assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint");
  DictionaryEntry* probe = NULL;
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
      probe = *p;
      Klass* e = probe->klass();
      ClassLoaderData* loader_data = probe->loader_data();
      InstanceKlass* ik = InstanceKlass::cast(e);
      if (!is_strongly_reachable(loader_data, e)) {
        assert(!loader_data->is_the_null_class_loader_data(), "unloading entry with null class loader");
        if (loader_data->is_unloading()) {
          if (probe == _current_class_entry) {
            _current_class_entry = NULL;
          }
          free_entry(probe);
          continue;
        }
      }
      p = probe->next_addr();
    }
  }
}
void Dictionary::roots_oops_do(OopClosure* strong, OopClosure* weak) {
  if (strong == weak) {
    oops_do(strong);
    return;
  }
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry *probe = bucket(index);
                          probe != NULL;
                          probe = probe->next()) {
      Klass* e = probe->klass();
      ClassLoaderData* loader_data = probe->loader_data();
      if (is_strongly_reachable(loader_data, e)) {
        probe->set_strongly_reachable();
      }
    }
  }
  _pd_cache_table->roots_oops_do(strong, weak);
}
void Dictionary::remove_classes_in_error_state() {
  assert(DumpSharedSpaces, "supported only when dumping");
  DictionaryEntry* probe = NULL;
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry** p = bucket_addr(index); *p != NULL; ) {
      probe = *p;
      InstanceKlass* ik = InstanceKlass::cast(probe->klass());
      if (ik->is_in_error_state()) { // purge this entry
        if (probe == _current_class_entry) {
          _current_class_entry = NULL;
        }
        free_entry(probe);
        ResourceMark rm;
        tty->print_cr("Preload Warning: Removed error class: %s", ik->external_name());
        continue;
      }
      p = probe->next_addr();
    }
  }
}
void Dictionary::always_strong_oops_do(OopClosure* blk) {
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry *probe = bucket(index);
                          probe != NULL;
                          probe = probe->next()) {
      Klass* e = probe->klass();
      ClassLoaderData* loader_data = probe->loader_data();
      if (is_strongly_reachable(loader_data, e)) {
        probe->set_strongly_reachable();
      }
    }
  }
  _pd_cache_table->always_strong_oops_do(blk);
}
void Dictionary::always_strong_classes_do(KlassClosure* closure) {
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry* probe = bucket(index);
                          probe != NULL;
                          probe = probe->next()) {
      Klass* e = probe->klass();
      ClassLoaderData* loader_data = probe->loader_data();
      if (is_strongly_reachable(loader_data, e)) {
        closure->do_klass(e);
      }
    }
  }
}
void Dictionary::classes_do(void f(Klass*)) {
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry* probe = bucket(index);
                          probe != NULL;
                          probe = probe->next()) {
      Klass* k = probe->klass();
      if (probe->loader_data() == InstanceKlass::cast(k)->class_loader_data()) {
        f(k);
      }
    }
  }
}
void Dictionary::classes_do(void f(Klass*, TRAPS), TRAPS) {
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry* probe = bucket(index);
                          probe != NULL;
                          probe = probe->next()) {
      Klass* k = probe->klass();
      if (probe->loader_data() == InstanceKlass::cast(k)->class_loader_data()) {
        f(k, CHECK);
      }
    }
  }
}
void Dictionary::classes_do(void f(Klass*, ClassLoaderData*)) {
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry* probe = bucket(index);
                          probe != NULL;
                          probe = probe->next()) {
      Klass* k = probe->klass();
      f(k, probe->loader_data());
    }
  }
}
void Dictionary::oops_do(OopClosure* f) {
  _pd_cache_table->oops_do(f);
}
void Dictionary::methods_do(void f(Method*)) {
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry* probe = bucket(index);
                          probe != NULL;
                          probe = probe->next()) {
      Klass* k = probe->klass();
      if (probe->loader_data() == InstanceKlass::cast(k)->class_loader_data()) {
        InstanceKlass::cast(k)->methods_do(f);
      }
    }
  }
}
void Dictionary::unlink(BoolObjectClosure* is_alive) {
  _pd_cache_table->unlink(is_alive);
}
Klass* Dictionary::try_get_next_class() {
  while (true) {
    if (_current_class_entry != NULL) {
      Klass* k = _current_class_entry->klass();
      _current_class_entry = _current_class_entry->next();
      return k;
    }
    _current_class_index = (_current_class_index + 1) % table_size();
    _current_class_entry = bucket(_current_class_index);
  }
}
void Dictionary::add_klass(Symbol* class_name, ClassLoaderData* loader_data,
                           KlassHandle obj) {
  assert_locked_or_safepoint(SystemDictionary_lock);
  assert(obj() != NULL, "adding NULL obj");
  assert(obj()->name() == class_name, "sanity check on name");
  assert(loader_data != NULL, "Must be non-NULL");
  unsigned int hash = compute_hash(class_name, loader_data);
  int index = hash_to_index(hash);
  DictionaryEntry* entry = new_entry(hash, obj(), loader_data);
  add_entry(index, entry);
}
DictionaryEntry* Dictionary::get_entry(int index, unsigned int hash,
                                       Symbol* class_name,
                                       ClassLoaderData* loader_data) {
  debug_only(_lookup_count++);
  for (DictionaryEntry* entry = bucket(index);
                        entry != NULL;
                        entry = entry->next()) {
    if (entry->hash() == hash && entry->equals(class_name, loader_data)) {
      return entry;
    }
    debug_only(_lookup_length++);
  }
  return NULL;
}
Klass* Dictionary::find(int index, unsigned int hash, Symbol* name,
                          ClassLoaderData* loader_data, Handle protection_domain, TRAPS) {
  DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
  if (entry != NULL && entry->is_valid_protection_domain(protection_domain)) {
    return entry->klass();
  } else {
    return NULL;
  }
}
Klass* Dictionary::find_class(int index, unsigned int hash,
                                Symbol* name, ClassLoaderData* loader_data) {
  assert_locked_or_safepoint(SystemDictionary_lock);
  assert (index == index_for(name, loader_data), "incorrect index?");
  DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
  return (entry != NULL) ? entry->klass() : (Klass*)NULL;
}
Klass* Dictionary::find_shared_class(int index, unsigned int hash,
                                       Symbol* name) {
  assert (index == index_for(name, NULL), "incorrect index?");
  DictionaryEntry* entry = get_entry(index, hash, name, NULL);
  return (entry != NULL) ? entry->klass() : (Klass*)NULL;
}
void Dictionary::add_protection_domain(int index, unsigned int hash,
                                       instanceKlassHandle klass,
                                       ClassLoaderData* loader_data, Handle protection_domain,
                                       TRAPS) {
  Symbol*  klass_name = klass->name();
  DictionaryEntry* entry = get_entry(index, hash, klass_name, loader_data);
  assert(entry != NULL,"entry must be present, we just created it");
  assert(protection_domain() != NULL,
         "real protection domain should be present");
  entry->add_protection_domain(this, protection_domain());
  assert(entry->contains_protection_domain(protection_domain()),
         "now protection domain should be present");
}
bool Dictionary::is_valid_protection_domain(int index, unsigned int hash,
                                            Symbol* name,
                                            ClassLoaderData* loader_data,
                                            Handle protection_domain) {
  DictionaryEntry* entry = get_entry(index, hash, name, loader_data);
  return entry->is_valid_protection_domain(protection_domain);
}
void Dictionary::reorder_dictionary() {
  DictionaryEntry* master_list = NULL;
  for (int i = 0; i < table_size(); ++i) {
    DictionaryEntry* p = bucket(i);
    while (p != NULL) {
      DictionaryEntry* tmp;
      tmp = p->next();
      p->set_next(master_list);
      master_list = p;
      p = tmp;
    }
    set_entry(i, NULL);
  }
  while (master_list != NULL) {
    DictionaryEntry* p = master_list;
    master_list = master_list->next();
    p->set_next(NULL);
    Symbol* class_name = InstanceKlass::cast((Klass*)(p->klass()))->name();
    unsigned int hash = compute_hash(class_name, NULL);
    int index = hash_to_index(hash);
    p->set_hash(hash);
    p->set_loader_data(NULL);   // loader_data isn't copied to CDS
    p->set_next(bucket(index));
    set_entry(index, p);
  }
}
ProtectionDomainCacheTable::ProtectionDomainCacheTable(int table_size)
  : Hashtable<oop, mtClass>(table_size, sizeof(ProtectionDomainCacheEntry))
{
}
void ProtectionDomainCacheTable::unlink(BoolObjectClosure* is_alive) {
  assert(SafepointSynchronize::is_at_safepoint(), "must be");
  for (int i = 0; i < table_size(); ++i) {
    ProtectionDomainCacheEntry** p = bucket_addr(i);
    ProtectionDomainCacheEntry* entry = bucket(i);
    while (entry != NULL) {
      if (is_alive->do_object_b(entry->literal())) {
        p = entry->next_addr();
      } else {
        free_entry(entry);
      }
      entry = *p;
    }
  }
}
void ProtectionDomainCacheTable::oops_do(OopClosure* f) {
  for (int index = 0; index < table_size(); index++) {
    for (ProtectionDomainCacheEntry* probe = bucket(index);
                                     probe != NULL;
                                     probe = probe->next()) {
      probe->oops_do(f);
    }
  }
}
void ProtectionDomainCacheTable::roots_oops_do(OopClosure* strong, OopClosure* weak) {
  for (int index = 0; index < table_size(); index++) {
    for (ProtectionDomainCacheEntry* probe = bucket(index);
                                     probe != NULL;
                                     probe = probe->next()) {
      if (probe->is_strongly_reachable()) {
        probe->reset_strongly_reachable();
        probe->oops_do(strong);
      } else {
        if (weak != NULL) {
          probe->oops_do(weak);
        }
      }
    }
  }
}
uint ProtectionDomainCacheTable::bucket_size() {
  return sizeof(ProtectionDomainCacheEntry);
}
#ifndef PRODUCT
void ProtectionDomainCacheTable::print() {
  tty->print_cr("Protection domain cache table (table_size=%d, classes=%d)",
                table_size(), number_of_entries());
  for (int index = 0; index < table_size(); index++) {
    for (ProtectionDomainCacheEntry* probe = bucket(index);
                                     probe != NULL;
                                     probe = probe->next()) {
      probe->print();
    }
  }
}
void ProtectionDomainCacheEntry::print() {
  tty->print_cr("entry " PTR_FORMAT " value " PTR_FORMAT " strongly_reachable %d next " PTR_FORMAT,
                this, (void*)literal(), _strongly_reachable, next());
}
#endif
void ProtectionDomainCacheTable::verify() {
  int element_count = 0;
  for (int index = 0; index < table_size(); index++) {
    for (ProtectionDomainCacheEntry* probe = bucket(index);
                                     probe != NULL;
                                     probe = probe->next()) {
      probe->verify();
      element_count++;
    }
  }
  guarantee(number_of_entries() == element_count,
            "Verify of protection domain cache table failed");
  debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
}
void ProtectionDomainCacheEntry::verify() {
  guarantee(literal()->is_oop(), "must be an oop");
}
void ProtectionDomainCacheTable::always_strong_oops_do(OopClosure* f) {
  for (int index = 0; index < table_size(); index++) {
    for (ProtectionDomainCacheEntry* probe = bucket(index);
                                     probe != NULL;
                                     probe = probe->next()) {
      if (probe->is_strongly_reachable()) {
        probe->reset_strongly_reachable();
        probe->oops_do(f);
      }
    }
  }
}
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::get(oop protection_domain) {
  unsigned int hash = compute_hash(protection_domain);
  int index = hash_to_index(hash);
  ProtectionDomainCacheEntry* entry = find_entry(index, protection_domain);
  if (entry == NULL) {
    entry = add_entry(index, hash, protection_domain);
  }
  return entry;
}
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::find_entry(int index, oop protection_domain) {
  for (ProtectionDomainCacheEntry* e = bucket(index); e != NULL; e = e->next()) {
    if (e->protection_domain() == protection_domain) {
      return e;
    }
  }
  return NULL;
}
ProtectionDomainCacheEntry* ProtectionDomainCacheTable::add_entry(int index, unsigned int hash, oop protection_domain) {
  assert_locked_or_safepoint(SystemDictionary_lock);
  assert(index == index_for(protection_domain), "incorrect index?");
  assert(find_entry(index, protection_domain) == NULL, "no double entry");
  ProtectionDomainCacheEntry* p = new_entry(hash, protection_domain);
  Hashtable<oop, mtClass>::add_entry(index, p);
  return p;
}
void ProtectionDomainCacheTable::free(ProtectionDomainCacheEntry* to_delete) {
  unsigned int hash = compute_hash(to_delete->protection_domain());
  int index = hash_to_index(hash);
  ProtectionDomainCacheEntry** p = bucket_addr(index);
  ProtectionDomainCacheEntry* entry = bucket(index);
  while (true) {
    assert(entry != NULL, "sanity");
    if (entry == to_delete) {
      Hashtable<oop, mtClass>::free_entry(entry);
      break;
    } else {
      p = entry->next_addr();
      entry = *p;
    }
  }
}
SymbolPropertyTable::SymbolPropertyTable(int table_size)
  : Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry))
{
}
SymbolPropertyTable::SymbolPropertyTable(int table_size, HashtableBucket<mtSymbol>* t,
                                         int number_of_entries)
  : Hashtable<Symbol*, mtSymbol>(table_size, sizeof(SymbolPropertyEntry), t, number_of_entries)
{
}
SymbolPropertyEntry* SymbolPropertyTable::find_entry(int index, unsigned int hash,
                                                     Symbol* sym,
                                                     intptr_t sym_mode) {
  assert(index == index_for(sym, sym_mode), "incorrect index?");
  for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
    if (p->hash() == hash && p->symbol() == sym && p->symbol_mode() == sym_mode) {
      return p;
    }
  }
  return NULL;
}
SymbolPropertyEntry* SymbolPropertyTable::add_entry(int index, unsigned int hash,
                                                    Symbol* sym, intptr_t sym_mode) {
  assert_locked_or_safepoint(SystemDictionary_lock);
  assert(index == index_for(sym, sym_mode), "incorrect index?");
  assert(find_entry(index, hash, sym, sym_mode) == NULL, "no double entry");
  SymbolPropertyEntry* p = new_entry(hash, sym, sym_mode);
  Hashtable<Symbol*, mtSymbol>::add_entry(index, p);
  return p;
}
void SymbolPropertyTable::oops_do(OopClosure* f) {
  for (int index = 0; index < table_size(); index++) {
    for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
      if (p->method_type() != NULL) {
        f->do_oop(p->method_type_addr());
      }
    }
  }
}
void SymbolPropertyTable::methods_do(void f(Method*)) {
  for (int index = 0; index < table_size(); index++) {
    for (SymbolPropertyEntry* p = bucket(index); p != NULL; p = p->next()) {
      Method* prop = p->method();
      if (prop != NULL) {
        f((Method*)prop);
      }
    }
  }
}
void Dictionary::print(bool details) {
  ResourceMark rm;
  HandleMark   hm;
  if (details) {
    tty->print_cr("Java system dictionary (table_size=%d, classes=%d)",
                   table_size(), number_of_entries());
    tty->print_cr("^ indicates that initiating loader is different from "
                  "defining loader");
  }
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry* probe = bucket(index);
                          probe != NULL;
                          probe = probe->next()) {
      if (Verbose) tty->print("%4d: ", index);
      Klass* e = probe->klass();
      ClassLoaderData* loader_data =  probe->loader_data();
      bool is_defining_class =
         (loader_data == InstanceKlass::cast(e)->class_loader_data());
      tty->print("%s%s", ((!details) || is_defining_class) ? " " : "^",
                   e->external_name());
      if (details) {
        tty->print(", loader ");
        if (loader_data != NULL) {
          loader_data->print_value();
        } else {
          tty->print("NULL");
        }
      }
      tty->cr();
    }
  }
  if (details) {
    tty->cr();
    _pd_cache_table->print();
  }
  tty->cr();
}
void Dictionary::verify() {
  guarantee(number_of_entries() >= 0, "Verify of system dictionary failed");
  int element_count = 0;
  for (int index = 0; index < table_size(); index++) {
    for (DictionaryEntry* probe = bucket(index);
                          probe != NULL;
                          probe = probe->next()) {
      Klass* e = probe->klass();
      ClassLoaderData* loader_data = probe->loader_data();
      guarantee(e->oop_is_instance(),
                              "Verify of system dictionary failed");
      guarantee(loader_data != NULL || DumpSharedSpaces ||
                loader_data->class_loader() == NULL ||
                loader_data->class_loader()->is_instance(),
                "checking type of class_loader");
      e->verify();
      probe->verify_protection_domain_set();
      element_count++;
    }
  }
  guarantee(number_of_entries() == element_count,
            "Verify of system dictionary failed");
  debug_only(verify_lookup_length((double)number_of_entries() / table_size()));
  _pd_cache_table->verify();
}
C:\hotspot-69087d08d473\src\share\vm/classfile/dictionary.hpp
#ifndef SHARE_VM_CLASSFILE_DICTIONARY_HPP
#define SHARE_VM_CLASSFILE_DICTIONARY_HPP
#include "classfile/systemDictionary.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/oop.inline.hpp"
#include "utilities/hashtable.hpp"
class DictionaryEntry;
class PSPromotionManager;
class ProtectionDomainCacheTable;
class ProtectionDomainCacheEntry;
class BoolObjectClosure;
class Dictionary : public TwoOopHashtable<Klass*, mtClass> {
  friend class VMStructs;
private:
  static int                    _current_class_index;
  static DictionaryEntry*       _current_class_entry;
  ProtectionDomainCacheTable*   _pd_cache_table;
  DictionaryEntry* get_entry(int index, unsigned int hash,
                             Symbol* name, ClassLoaderData* loader_data);
protected:
  DictionaryEntry* bucket(int i) {
    return (DictionaryEntry*)Hashtable<Klass*, mtClass>::bucket(i);
  }
  DictionaryEntry** bucket_addr(int i) {
    return (DictionaryEntry**)Hashtable<Klass*, mtClass>::bucket_addr(i);
  }
  void add_entry(int index, DictionaryEntry* new_entry) {
    Hashtable<Klass*, mtClass>::add_entry(index, (HashtableEntry<Klass*, mtClass>*)new_entry);
  }
  static size_t entry_size();
public:
  Dictionary(int table_size);
  Dictionary(int table_size, HashtableBucket<mtClass>* t, int number_of_entries);
  DictionaryEntry* new_entry(unsigned int hash, Klass* klass, ClassLoaderData* loader_data);
  DictionaryEntry* new_entry();
  void free_entry(DictionaryEntry* entry);
  void add_klass(Symbol* class_name, ClassLoaderData* loader_data,KlassHandle obj);
  Klass* find_class(int index, unsigned int hash,
                      Symbol* name, ClassLoaderData* loader_data);
  Klass* find_shared_class(int index, unsigned int hash, Symbol* name);
  Klass* try_get_next_class();
  void oops_do(OopClosure* f);
  void always_strong_oops_do(OopClosure* blk);
  void roots_oops_do(OopClosure* strong, OopClosure* weak);
  void always_strong_classes_do(KlassClosure* closure);
  void classes_do(void f(Klass*));
  void classes_do(void f(Klass*, TRAPS), TRAPS);
  void classes_do(void f(Klass*, ClassLoaderData*));
  void methods_do(void f(Method*));
  void unlink(BoolObjectClosure* is_alive);
  void remove_classes_in_error_state();
  static bool is_strongly_reachable(ClassLoaderData* loader_data, Klass* klass) {
    assert (klass != NULL, "should have non-null klass");
    return (loader_data->is_the_null_class_loader_data() || !ClassUnloading);
  }
  void do_unloading();
  Klass* find(int index, unsigned int hash, Symbol* name,
                ClassLoaderData* loader_data, Handle protection_domain, TRAPS);
  bool is_valid_protection_domain(int index, unsigned int hash,
                                  Symbol* name, ClassLoaderData* loader_data,
                                  Handle protection_domain);
  void add_protection_domain(int index, unsigned int hash,
                             instanceKlassHandle klass, ClassLoaderData* loader_data,
                             Handle protection_domain, TRAPS);
  void reorder_dictionary();
  ProtectionDomainCacheEntry* cache_get(oop protection_domain);
  void print(bool details = true);
  void verify();
};
class ProtectionDomainCacheEntry : public HashtableEntry<oop, mtClass> {
  friend class VMStructs;
 private:
  bool _strongly_reachable;
 public:
  oop protection_domain() { return literal(); }
  void init() {
    _strongly_reachable = false;
  }
  ProtectionDomainCacheEntry* next() {
    return (ProtectionDomainCacheEntry*)HashtableEntry<oop, mtClass>::next();
  }
  ProtectionDomainCacheEntry** next_addr() {
    return (ProtectionDomainCacheEntry**)HashtableEntry<oop, mtClass>::next_addr();
  }
  void oops_do(OopClosure* f) {
    f->do_oop(literal_addr());
  }
  void set_strongly_reachable()   { _strongly_reachable = true; }
  bool is_strongly_reachable()    { return _strongly_reachable; }
  void reset_strongly_reachable() { _strongly_reachable = false; }
  void print() PRODUCT_RETURN;
  void verify();
};
class ProtectionDomainCacheTable : public Hashtable<oop, mtClass> {
  friend class VMStructs;
private:
  ProtectionDomainCacheEntry* bucket(int i) {
    return (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::bucket(i);
  }
  ProtectionDomainCacheEntry** bucket_addr(int i) {
    return (ProtectionDomainCacheEntry**) Hashtable<oop, mtClass>::bucket_addr(i);
  }
  ProtectionDomainCacheEntry* new_entry(unsigned int hash, oop protection_domain) {
    ProtectionDomainCacheEntry* entry = (ProtectionDomainCacheEntry*) Hashtable<oop, mtClass>::new_entry(hash, protection_domain);
    entry->init();
    return entry;
  }
  static unsigned int compute_hash(oop protection_domain) {
    return (unsigned int)(protection_domain->identity_hash());
  }
  int index_for(oop protection_domain) {
    return hash_to_index(compute_hash(protection_domain));
  }
  ProtectionDomainCacheEntry* add_entry(int index, unsigned int hash, oop protection_domain);
  ProtectionDomainCacheEntry* find_entry(int index, oop protection_domain);
public:
  ProtectionDomainCacheTable(int table_size);
  ProtectionDomainCacheEntry* get(oop protection_domain);
  void free(ProtectionDomainCacheEntry* entry);
  void unlink(BoolObjectClosure* cl);
  void oops_do(OopClosure* f);
  void always_strong_oops_do(OopClosure* f);
  void roots_oops_do(OopClosure* strong, OopClosure* weak);
  static uint bucket_size();
  void print() PRODUCT_RETURN;
  void verify();
};
class ProtectionDomainEntry :public CHeapObj<mtClass> {
  friend class VMStructs;
 public:
  ProtectionDomainEntry* _next;
  ProtectionDomainCacheEntry* _pd_cache;
  ProtectionDomainEntry(ProtectionDomainCacheEntry* pd_cache, ProtectionDomainEntry* next) {
    _pd_cache = pd_cache;
    _next     = next;
  }
  ProtectionDomainEntry* next() { return _next; }
  oop protection_domain() { return _pd_cache->protection_domain(); }
};
class DictionaryEntry : public HashtableEntry<Klass*, mtClass> {
  friend class VMStructs;
 private:
  ProtectionDomainEntry* _pd_set;
  ClassLoaderData*       _loader_data;
 public:
  bool contains_protection_domain(oop protection_domain) const;
  void add_protection_domain(Dictionary* dict, oop protection_domain);
  Klass* klass() const { return (Klass*)literal(); }
  Klass** klass_addr() { return (Klass**)literal_addr(); }
  DictionaryEntry* next() const {
    return (DictionaryEntry*)HashtableEntry<Klass*, mtClass>::next();
  }
  DictionaryEntry** next_addr() {
    return (DictionaryEntry**)HashtableEntry<Klass*, mtClass>::next_addr();
  }
  ClassLoaderData* loader_data() const { return _loader_data; }
  void set_loader_data(ClassLoaderData* loader_data) { _loader_data = loader_data; }
  ProtectionDomainEntry* pd_set() const { return _pd_set; }
  void set_pd_set(ProtectionDomainEntry* pd_set) { _pd_set = pd_set; }
  bool has_protection_domain() { return _pd_set != NULL; }
  bool is_valid_protection_domain(Handle protection_domain) {
    if (!ProtectionDomainVerification) return true;
    if (!SystemDictionary::has_checkPackageAccess()) return true;
    return protection_domain() == NULL
         ? true
         : contains_protection_domain(protection_domain());
  }
  void set_strongly_reachable() {
    for (ProtectionDomainEntry* current = _pd_set;
                                current != NULL;
                                current = current->_next) {
      current->_pd_cache->set_strongly_reachable();
    }
  }
  void verify_protection_domain_set() {
    for (ProtectionDomainEntry* current = _pd_set;
                                current != NULL;
                                current = current->_next) {
      current->_pd_cache->protection_domain()->verify();
    }
  }
  bool equals(Symbol* class_name, ClassLoaderData* loader_data) const {
    Klass* klass = (Klass*)literal();
    return (InstanceKlass::cast(klass)->name() == class_name &&
            _loader_data == loader_data);
  }
  void print() {
    int count = 0;
    for (ProtectionDomainEntry* current = _pd_set;
                                current != NULL;
                                current = current->_next) {
      count++;
    }
    tty->print_cr("pd set = #%d", count);
  }
};
class SymbolPropertyEntry : public HashtableEntry<Symbol*, mtSymbol> {
  friend class VMStructs;
 private:
  intptr_t _symbol_mode;  // secondary key
  Method*   _method;
  oop       _method_type;
 public:
  Symbol* symbol() const            { return literal(); }
  intptr_t symbol_mode() const      { return _symbol_mode; }
  void set_symbol_mode(intptr_t m)  { _symbol_mode = m; }
  Method*        method() const     { return _method; }
  void set_method(Method* p)        { _method = p; }
  oop      method_type() const      { return _method_type; }
  oop*     method_type_addr()       { return &_method_type; }
  void set_method_type(oop p)       { _method_type = p; }
  SymbolPropertyEntry* next() const {
    return (SymbolPropertyEntry*)HashtableEntry<Symbol*, mtSymbol>::next();
  }
  SymbolPropertyEntry** next_addr() {
    return (SymbolPropertyEntry**)HashtableEntry<Symbol*, mtSymbol>::next_addr();
  }
  void print_on(outputStream* st) const {
    symbol()->print_value_on(st);
    st->print("/mode=" INTX_FORMAT, symbol_mode());
    st->print(" -> ");
    bool printed = false;
    if (method() != NULL) {
      method()->print_value_on(st);
      printed = true;
    }
    if (method_type() != NULL) {
      if (printed)  st->print(" and ");
      st->print(INTPTR_FORMAT, p2i((void *)method_type()));
      printed = true;
    }
    st->print_cr(printed ? "" : "(empty)");
  }
};
class SymbolPropertyTable : public Hashtable<Symbol*, mtSymbol> {
  friend class VMStructs;
private:
  SymbolPropertyEntry* bucket(int i) {
    return (SymbolPropertyEntry*) Hashtable<Symbol*, mtSymbol>::bucket(i);
  }
  SymbolPropertyEntry** bucket_addr(int i) {
    return (SymbolPropertyEntry**) Hashtable<Symbol*, mtSymbol>::bucket_addr(i);
  }
  void add_entry(int index, SymbolPropertyEntry* new_entry) {
    ShouldNotReachHere();
  }
  void set_entry(int index, SymbolPropertyEntry* new_entry) {
    ShouldNotReachHere();
  }
  SymbolPropertyEntry* new_entry(unsigned int hash, Symbol* symbol, intptr_t symbol_mode) {
    SymbolPropertyEntry* entry = (SymbolPropertyEntry*) Hashtable<Symbol*, mtSymbol>::new_entry(hash, symbol);
    symbol->increment_refcount();
    entry->set_symbol_mode(symbol_mode);
    entry->set_method(NULL);
    entry->set_method_type(NULL);
    return entry;
  }
public:
  SymbolPropertyTable(int table_size);
  SymbolPropertyTable(int table_size, HashtableBucket<mtSymbol>* t, int number_of_entries);
  void free_entry(SymbolPropertyEntry* entry) {
    entry->literal()->decrement_refcount();
    Hashtable<Symbol*, mtSymbol>::free_entry(entry);
  }
  unsigned int compute_hash(Symbol* sym, intptr_t symbol_mode) {
    return Hashtable<Symbol*, mtSymbol>::compute_hash(sym) ^ symbol_mode;
  }
  int index_for(Symbol* name, intptr_t symbol_mode) {
    return hash_to_index(compute_hash(name, symbol_mode));
  }
  SymbolPropertyEntry* find_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode);
  SymbolPropertyEntry* add_entry(int index, unsigned int hash, Symbol* name, intptr_t name_mode);
  void oops_do(OopClosure* f);
  void methods_do(void f(Method*));
  void reorder_dictionary();
#ifndef PRODUCT
  void print();
#endif
  void verify();
};
#endif // SHARE_VM_CLASSFILE_DICTIONARY_HPP
C:\hotspot-69087d08d473\src\share\vm/classfile/javaAssertions.cpp
#include "precompiled.hpp"
#include "classfile/javaAssertions.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/systemDictionary.hpp"
#include "classfile/vmSymbols.hpp"
#include "memory/allocation.inline.hpp"
#include "memory/oopFactory.hpp"
#include "oops/oop.inline.hpp"
#include "runtime/handles.inline.hpp"
bool                            JavaAssertions::_userDefault = false;
bool                            JavaAssertions::_sysDefault = false;
JavaAssertions::OptionList*     JavaAssertions::_classes = 0;
JavaAssertions::OptionList*     JavaAssertions::_packages = 0;
JavaAssertions::OptionList::OptionList(const char* name, bool enabled,
  OptionList* next) {
  assert(name != 0, "need a name");
  _name = name;
  _enabled = enabled;
  _next = next;
}
int JavaAssertions::OptionList::count(OptionList* p) {
  int rc;
  for (rc = 0; p != 0; p = p->next(), ++rc) /* empty */;
  return rc;
}
void JavaAssertions::addOption(const char* name, bool enable) {
  assert(name != 0, "must have a name");
  int len = (int)strlen(name);
  char *name_copy = NEW_C_HEAP_ARRAY(char, len + 1, mtClass);
  strcpy(name_copy, name);
  OptionList** head = &_classes;
  if (len >= 3 && strcmp(name_copy + len - 3, "...") == 0) {
    len -= 3;
    name_copy[len] = '\0';
    head = &_packages;
  }
  for (int i = 0; i < len; ++i) {
    if (name_copy[i] == '.') name_copy[i] = '/';
  }
  if (TraceJavaAssertions) {
    tty->print_cr("JavaAssertions: adding %s %s=%d",
      head == &_classes ? "class" : "package",
      name_copy[0] != '\0' ? name_copy : "'default'",
      enable);
  }
}
oop JavaAssertions::createAssertionStatusDirectives(TRAPS) {
  Symbol* asd_sym = vmSymbols::java_lang_AssertionStatusDirectives();
  Klass* k = SystemDictionary::resolve_or_fail(asd_sym, true, CHECK_NULL);
  instanceKlassHandle asd_klass (THREAD, k);
  asd_klass->initialize(CHECK_NULL);
  Handle h = asd_klass->allocate_instance_handle(CHECK_NULL);
  int len;
  typeArrayOop t;
  len = OptionList::count(_packages);
  objArrayOop pn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL);
  objArrayHandle pkgNames (THREAD, pn);
  t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
  typeArrayHandle pkgEnabled(THREAD, t);
  fillJavaArrays(_packages, len, pkgNames, pkgEnabled, CHECK_NULL);
  len = OptionList::count(_classes);
  objArrayOop cn = oopFactory::new_objArray(SystemDictionary::String_klass(), len, CHECK_NULL);
  objArrayHandle classNames (THREAD, cn);
  t = oopFactory::new_typeArray(T_BOOLEAN, len, CHECK_NULL);
  typeArrayHandle classEnabled(THREAD, t);
  fillJavaArrays(_classes, len, classNames, classEnabled, CHECK_NULL);
  java_lang_AssertionStatusDirectives::set_packages(h(), pkgNames());
  java_lang_AssertionStatusDirectives::set_packageEnabled(h(), pkgEnabled());
  java_lang_AssertionStatusDirectives::set_classes(h(), classNames());
  java_lang_AssertionStatusDirectives::set_classEnabled(h(), classEnabled());
  java_lang_AssertionStatusDirectives::set_deflt(h(), userClassDefault());
  return h();
}
void JavaAssertions::fillJavaArrays(const OptionList* p, int len,
objArrayHandle names, typeArrayHandle enabled, TRAPS) {
  int index;
  for (index = len - 1; p != 0; p = p->next(), --index) {
    assert(index >= 0, "length does not match list");
    Handle s = java_lang_String::create_from_str(p->name(), CHECK);
    s = java_lang_String::char_converter(s, '/', '.', CHECK);
    names->obj_at_put(index, s());
    enabled->bool_at_put(index, p->enabled());
  }
  assert(index == -1, "length does not match list");
}
inline JavaAssertions::OptionList*
JavaAssertions::match_class(const char* classname) {
  for (OptionList* p = _classes; p != 0; p = p->next()) {
    if (strcmp(p->name(), classname) == 0) {
      return p;
    }
  }
  return 0;
}
JavaAssertions::OptionList*
JavaAssertions::match_package(const char* classname) {
  if (_packages == 0) return 0;
  size_t len = strlen(classname);
  for (/* empty */; len > 0 && classname[len] != '/'; --len) /* empty */;
  do {
    assert(len == 0 || classname[len] == '/', "not a package name");
    for (OptionList* p = _packages; p != 0; p = p->next()) {
      if (strncmp(p->name(), classname, len) == 0 && p->name()[len] == '\0') {
        return p;
      }
    }
    while (len > 0 && classname[--len] != '/') /* empty */;
  } while (len > 0);
  return 0;
}
inline void JavaAssertions::trace(const char* name,
const char* typefound, const char* namefound, bool enabled) {
  if (TraceJavaAssertions) {
    tty->print_cr("JavaAssertions:  search for %s found %s %s=%d",
      name, typefound, namefound[0] != '\0' ? namefound : "'default'", enabled);
  }
}
bool JavaAssertions::enabled(const char* classname, bool systemClass) {
  assert(classname != 0, "must have a classname");
  OptionList* p;
  if (p = match_class(classname)) {
    trace(classname, "class", p->name(), p->enabled());
    return p->enabled();
  }
  if (p = match_package(classname)) {
    trace(classname, "package", p->name(), p->enabled());
    return p->enabled();
  }
  bool result = systemClass ? systemClassDefault() : userClassDefault();
  trace(classname, systemClass ? "system" : "user", "default", result);
  return result;
}
C:\hotspot-69087d08d473\src\share\vm/classfile/javaAssertions.hpp
#ifndef SHARE_VM_CLASSFILE_JAVAASSERTIONS_HPP
#define SHARE_VM_CLASSFILE_JAVAASSERTIONS_HPP
#include "oops/objArrayOop.hpp"
#include "oops/typeArrayOop.hpp"
#include "utilities/exceptions.hpp"
#include "utilities/ostream.hpp"
class JavaAssertions: AllStatic {
public:
  static inline bool userClassDefault();
  static inline void setUserClassDefault(bool enabled);
  static inline bool systemClassDefault();
  static inline void setSystemClassDefault(bool enabled);
  static void addOption(const char* name, bool enable);
  static bool enabled(const char* classname, bool systemClass);
  static oop createAssertionStatusDirectives(TRAPS);
private:
  class OptionList;
  static void fillJavaArrays(const OptionList* p, int len, objArrayHandle names,
    typeArrayHandle status, TRAPS);
  static inline void trace(const char* name, const char* typefound,
    const char* namefound, bool enabled);
  static inline OptionList*     match_class(const char* classname);
  static OptionList*            match_package(const char* classname);
  static bool           _userDefault;   // User class default (-ea/-da).
  static bool           _sysDefault;    // System class default (-esa/-dsa).
  static OptionList*    _classes;       // Options for classes.
  static OptionList*    _packages;      // Options for package trees.
};
class JavaAssertions::OptionList: public CHeapObj<mtClass> {
public:
  inline OptionList(const char* name, bool enable, OptionList* next);
  inline const char*    name() const    { return _name; }
  inline bool           enabled() const { return _enabled; }
  inline OptionList*    next() const    { return _next; }
  static int count(OptionList* p);
private:
  const char*   _name;
  OptionList*   _next;
  bool          _enabled;
};
inline bool JavaAssertions::userClassDefault() {
  return _userDefault;
}
inline void JavaAssertions::setUserClassDefault(bool enabled) {
  if (TraceJavaAssertions)
    tty->print_cr("JavaAssertions::setUserClassDefault(%d)", enabled);
  _userDefault = enabled;
}
inline bool JavaAssertions::systemClassDefault() {
  return _sysDefault;
}
inline void JavaAssertions::setSystemClassDefault(bool enabled) {
  if (TraceJavaAssertions)
    tty->print_cr("JavaAssertions::setSystemClassDefault(%d)", enabled);
  _sysDefault = enabled;
}
#endif // SHARE_VM_CLASSFILE_JAVAASSERTIONS_HPP
C:\hotspot-69087d08d473\src\share\vm/classfile/javaClasses.cpp
#include "precompiled.hpp"
#include "classfile/altHashing.hpp"
#include "classfile/javaClasses.hpp"
#include "classfile/symbolTable.hpp"
#include "classfile/vmSymbols.hpp"
#include "code/debugInfo.hpp"
#include "code/pcDesc.hpp"
#include "compiler/compilerOracle.hpp"
#include "interpreter/interpreter.hpp"
#include "memory/oopFactory.hpp"
#include "memory/resourceArea.hpp"
#include "memory/universe.inline.hpp"
#include "oops/fieldStreams.hpp"
#include "oops/instanceKlass.hpp"
#include "oops/instanceMirrorKlass.hpp"
#include "oops/klass.hpp"
#include "oops/method.hpp"
#include "oops/symbol.hpp"
#include "oops/typeArrayOop.hpp"
#include "prims/jvmtiRedefineClassesTrace.hpp"
#include "runtime/fieldDescriptor.hpp"
#include "runtime/handles.inline.hpp"
#include "runtime/interfaceSupport.hpp"
#include "runtime/java.hpp"
#include "runtime/javaCalls.hpp"
#include "runtime/safepoint.hpp"
#include "runtime/thread.inline.hpp"
#include "runtime/vframe.hpp"
#include "utilities/preserveException.hpp"
PRAGMA_FORMAT_MUTE_WARNINGS_FOR_GCC
#define INJECTED_FIELD_COMPUTE_OFFSET(klass, name, signature, may_be_java)    \
  klass::_##name##_offset = JavaClasses::compute_injected_offset(JavaClasses::klass##_##name##_enum);
#define DECLARE_INJECTED_FIELD(klass, name, signature, may_be_java)           \
  { SystemDictionary::WK_KLASS_ENUM_NAME(klass), vmSymbols::VM_SYMBOL_ENUM_NAME(name##_name), vmSymbols::VM_SYMBOL_ENUM_NAME(signature), may_be_java },
InjectedField JavaClasses::_injected_fields[] = {
  ALL_INJECTED_FIELDS(DECLARE_INJECTED_FIELD)
};
int JavaClasses::compute_injected_offset(InjectedFieldID id) {
  return _injected_fields[id].compute_offset();
}
InjectedField* JavaClasses::get_injected(Symbol* class_name, int* field_count) {
  vmSymbols::SID sid = vmSymbols::find_sid(class_name);
  if (sid == vmSymbols::NO_SID) {
    return NULL;
  }
  int count = 0;
  int start = -1;
#define LOOKUP_INJECTED_FIELD(klass, name, signature, may_be_java) \
  if (sid == vmSymbols::VM_SYMBOL_ENUM_NAME(klass)) {              \
    count++;                                                       \
    if (start == -1) start = klass##_##name##_enum;                \
  }
  ALL_INJECTED_FIELDS(LOOKUP_INJECTED_FIELD);
#undef LOOKUP_INJECTED_FIELD
  if (start != -1) {
    return _injected_fields + start;
  }
  return NULL;
}
static bool find_field(InstanceKlass* ik,
                       Symbol* name_symbol, Symbol* signature_symbol,
                       fieldDescriptor* fd,
                       bool allow_super = false) {
  if (allow_super)
    return ik->find_field(name_symbol, signature_symbol, fd) != NULL;
  else
    return ik->find_local_field(name_symbol, signature_symbol, fd);
}
static void
compute_offset(int &dest_offset,
               Klass* klass_oop, Symbol* name_symbol, Symbol* signature_symbol,
               bool allow_super = false) {
  fieldDescriptor fd;
  InstanceKlass* ik = InstanceKlass::cast(klass_oop);
  if (!find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
    ResourceMark rm;
    tty->print_cr("Invalid layout of %s at %s", ik->external_name(), name_symbol->as_C_string());
#ifndef PRODUCT
    klass_oop->print();
    tty->print_cr("all fields:");
    for (AllFieldStream fs(InstanceKlass::cast(klass_oop)); !fs.done(); fs.next()) {
      tty->print_cr("  name: %s, sig: %s, flags: %08x", fs.name()->as_C_string(), fs.signature()->as_C_string(), fs.access_flags().as_int());
    }
#endif //PRODUCT
    vm_exit_during_initialization("Invalid layout of preloaded class: use -XX:+TraceClassLoading to see the origin of the problem class");
  }
  dest_offset = fd.offset();
}
static void
compute_optional_offset(int& dest_offset,
                        Klass* klass_oop, Symbol* name_symbol, Symbol* signature_symbol,
                        bool allow_super = false) {
  fieldDescriptor fd;
  InstanceKlass* ik = InstanceKlass::cast(klass_oop);
  if (find_field(ik, name_symbol, signature_symbol, &fd, allow_super)) {
    dest_offset = fd.offset();
  }
}
int java_lang_String::value_offset  = 0;
int java_lang_String::offset_offset = 0;
int java_lang_String::count_offset  = 0;
int java_lang_String::hash_offset   = 0;
bool java_lang_String::initialized  = false;
void java_lang_String::compute_offsets() {
  assert(!initialized, "offsets should be initialized only once");
  Klass* k = SystemDictionary::String_klass();
  compute_offset(value_offset,           k, vmSymbols::value_name(),  vmSymbols::char_array_signature());
  compute_optional_offset(offset_offset, k, vmSymbols::offset_name(), vmSymbols::int_signature());
  compute_optional_offset(count_offset,  k, vmSymbols::count_name(),  vmSymbols::int_signature());
  compute_optional_offset(hash_offset,   k, vmSymbols::hash_name(),   vmSymbols::int_signature());
  initialized = true;
}
Handle java_lang_String::basic_create(int length, TRAPS) {
  assert(initialized, "Must be initialized");
  oop obj;
  obj = InstanceKlass::cast(SystemDictionary::String_klass())->allocate_instance(CHECK_NH);
  Handle h_obj(THREAD, obj);
  typeArrayOop buffer;
    buffer = oopFactory::new_charArray(length, CHECK_NH);
  obj = h_obj();
  set_value(obj, buffer);
  assert(offset(obj) == 0, "initial String offset should be zero");
  set_count(obj, length);
  return h_obj;
}
Handle java_lang_String::create_from_unicode(jchar* unicode, int length, TRAPS) {
  Handle h_obj = basic_create(length, CHECK_NH);
  typeArrayOop buffer = value(h_obj());
  for (int index = 0; index < length; index++) {
    buffer->char_at_put(index, unicode[index]);
  }
  return h_obj;
}
oop java_lang_String::create_oop_from_unicode(jchar* unicode, int length, TRAPS) {
  Handle h_obj = create_from_unicode(unicode, length, CHECK_0);
  return h_obj();
}
Handle java_lang_String::create_from_str(const char* utf8_str, TRAPS) {
  if (utf8_str == NULL) {
    return Handle();
  }
  int length = UTF8::unicode_length(utf8_str);
  Handle h_obj = basic_create(length, CHECK_NH);
  if (length > 0) {
    UTF8::convert_to_unicode(utf8_str, value(h_obj())->char_at_addr(0), length);
  }
  return h_obj;
}
oop java_lang_String::create_oop_from_str(const char* utf8_str, TRAPS) {
  Handle h_obj = create_from_str(utf8_str, CHECK_0);
  return h_obj();
}
Handle java_lang_String::create_from_symbol(Symbol* symbol, TRAPS) {
  int length = UTF8::unicode_length((char*)symbol->bytes(), symbol->utf8_length());
  Handle h_obj = basic_create(length, CHECK_NH);
  if (length > 0) {
    UTF8::convert_to_unicode((char*)symbol->bytes(), value(h_obj())->char_at_addr(0), length);
  }
  return h_obj;
}
Handle java_lang_String::create_from_platform_dependent_str(const char* str, TRAPS) {
  assert(str != NULL, "bad arguments");
  typedef jstring (*to_java_string_fn_t)(JNIEnv*, const char *);
  static to_java_string_fn_t _to_java_string_fn = NULL;
  if (_to_java_string_fn == NULL) {
    void *lib_handle = os::native_java_library();
    _to_java_string_fn = CAST_TO_FN_PTR(to_java_string_fn_t, os::dll_lookup(lib_handle, "NewStringPlatform"));
    if (_to_java_string_fn == NULL) {
      fatal("NewStringPlatform missing");
    }
  }
  jstring js = NULL;
  { JavaThread* thread = (JavaThread*)THREAD;
    assert(thread->is_Java_thread(), "must be java thread");
    HandleMark hm(thread);
    ThreadToNativeFromVM ttn(thread);
    js = (_to_java_string_fn)(thread->jni_environment(), str);
  }
  return Handle(THREAD, JNIHandles::resolve(js));
}
char* java_lang_String::as_platform_dependent_str(Handle java_string, TRAPS) {
  typedef char* (*to_platform_string_fn_t)(JNIEnv*, jstring, bool*);
  static to_platform_string_fn_t _to_platform_string_fn = NULL;
  if (_to_platform_string_fn == NULL) {
    void *lib_handle = os::native_java_library();
    _to_platform_string_fn = CAST_TO_FN_PTR(to_platform_string_fn_t, os::dll_lookup(lib_handle, "GetStringPlatformChars"));
    if (_to_platform_string_fn == NULL) {
      fatal("GetStringPlatformChars missing");
    }
  }
  char *native_platform_string;
  { JavaThread* thread = (JavaThread*)THREAD;
    assert(thread->is_Java_thread(), "must be java thread");
    JNIEnv *env = thread->jni_environment();
    jstring js = (jstring) JNIHandles::make_local(env, java_string());
    bool is_copy;
    HandleMark hm(thread);
    ThreadToNativeFromVM ttn(thread);
    native_platform_string = (_to_platform_string_fn)(env, js, &is_copy);
    assert(is_copy == JNI_TRUE, "is_copy value changed");
    JNIHandles::destroy_local(js);
  }
  return native_platform_string;
}
Handle java_lang_String::char_converter(Handle java_string, jchar from_char, jchar to_char, TRAPS) {
  oop          obj    = java_string();
  typeArrayOop value  = java_lang_String::value(obj);
  int          offset = java_lang_String::offset(obj);
  int          length = java_lang_String::length(obj);
  int index; // Declared outside, used later
  for (index = 0; index < length; index++) {
    if (value->char_at(index + offset) == from_char) {
      break;
    }
  }
  if (index == length) {
    return java_string;
  }
  typeArrayHandle h_value(THREAD, value);
  Handle string = basic_create(length, CHECK_NH);
  typeArrayOop from_buffer = h_value();
  typeArrayOop to_buffer   = java_lang_String::value(string());
  for (index = 0; index < length; index++) {
    jchar c = from_buffer->char_at(index + offset);
    if (c == from_char) {
      c = to_char;
    }
    to_buffer->char_at_put(index, c);
  }
  return string;
}
jchar* java_lang_String::as_unicode_string(oop java_string, int& length, TRAPS) {
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
               length = java_lang_String::length(java_string);
  jchar* result = NEW_RESOURCE_ARRAY_RETURN_NULL(jchar, length);
  if (result != NULL) {
    for (int index = 0; index < length; index++) {
      result[index] = value->char_at(index + offset);
    }
  } else {
    THROW_MSG_0(vmSymbols::java_lang_OutOfMemoryError(), "could not allocate Unicode string");
  }
  return result;
}
unsigned int java_lang_String::hash_code(oop java_string) {
  int          length = java_lang_String::length(java_string);
  if (length == 0) return 0;
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
  return java_lang_String::hash_code(value->char_at_addr(offset), length);
}
char* java_lang_String::as_quoted_ascii(oop java_string) {
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
  int          length = java_lang_String::length(java_string);
  jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
  if (base == NULL) return NULL;
  int result_length = UNICODE::quoted_ascii_length(base, length) + 1;
  char* result = NEW_RESOURCE_ARRAY(char, result_length);
  UNICODE::as_quoted_ascii(base, length, result, result_length);
  assert(result_length >= length + 1, "must not be shorter");
  assert(result_length == (int)strlen(result) + 1, "must match");
  return result;
}
unsigned int java_lang_String::hash_string(oop java_string) {
  int          length = java_lang_String::length(java_string);
  if (length == 0) {
    return StringTable::hash_string(NULL, 0);
  }
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
  return StringTable::hash_string(value->char_at_addr(offset), length);
}
Symbol* java_lang_String::as_symbol(Handle java_string, TRAPS) {
  oop          obj    = java_string();
  typeArrayOop value  = java_lang_String::value(obj);
  int          offset = java_lang_String::offset(obj);
  int          length = java_lang_String::length(obj);
  jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
  Symbol* sym = SymbolTable::lookup_unicode(base, length, THREAD);
  return sym;
}
Symbol* java_lang_String::as_symbol_or_null(oop java_string) {
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
  int          length = java_lang_String::length(java_string);
  jchar* base = (length == 0) ? NULL : value->char_at_addr(offset);
  return SymbolTable::probe_unicode(base, length);
}
int java_lang_String::utf8_length(oop java_string) {
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
  int          length = java_lang_String::length(java_string);
  jchar* position = (length == 0) ? NULL : value->char_at_addr(offset);
  return UNICODE::utf8_length(position, length);
}
char* java_lang_String::as_utf8_string(oop java_string) {
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
  int          length = java_lang_String::length(java_string);
  jchar* position = (length == 0) ? NULL : value->char_at_addr(offset);
  return UNICODE::as_utf8(position, length);
}
char* java_lang_String::as_utf8_string(oop java_string, char* buf, int buflen) {
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
  int          length = java_lang_String::length(java_string);
  jchar* position = (length == 0) ? NULL : value->char_at_addr(offset);
  return UNICODE::as_utf8(position, length, buf, buflen);
}
char* java_lang_String::as_utf8_string(oop java_string, int start, int len) {
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
  int          length = java_lang_String::length(java_string);
  assert(start + len <= length, "just checking");
  jchar* position = value->char_at_addr(offset + start);
  return UNICODE::as_utf8(position, len);
}
bool java_lang_String::equals(oop java_string, jchar* chars, int len) {
  assert(java_string->klass() == SystemDictionary::String_klass(),
         "must be java_string");
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
  int          length = java_lang_String::length(java_string);
  if (length != len) {
    return false;
  }
  for (int i = 0; i < len; i++) {
    if (value->char_at(i + offset) != chars[i]) {
      return false;
    }
  }
  return true;
}
bool java_lang_String::equals(oop str1, oop str2) {
  assert(str1->klass() == SystemDictionary::String_klass(),
         "must be java String");
  assert(str2->klass() == SystemDictionary::String_klass(),
         "must be java String");
  typeArrayOop value1  = java_lang_String::value(str1);
  int          offset1 = java_lang_String::offset(str1);
  int          length1 = java_lang_String::length(str1);
  typeArrayOop value2  = java_lang_String::value(str2);
  int          offset2 = java_lang_String::offset(str2);
  int          length2 = java_lang_String::length(str2);
  if (length1 != length2) {
    return false;
  }
  for (int i = 0; i < length1; i++) {
    if (value1->char_at(i + offset1) != value2->char_at(i + offset2)) {
      return false;
    }
  }
  return true;
}
void java_lang_String::print(oop java_string, outputStream* st) {
  assert(java_string->klass() == SystemDictionary::String_klass(), "must be java_string");
  typeArrayOop value  = java_lang_String::value(java_string);
  int          offset = java_lang_String::offset(java_string);
  int          length = java_lang_String::length(java_string);
  int end = MIN2(length, 100);
  if (value == NULL) {
    st->print_cr("NULL");
  } else {
    st->print("\"");
    for (int index = 0; index < length; index++) {
      st->print("%c", value->char_at(index + offset));
    }
    st->print("\"");
  }
}
static void initialize_static_field(fieldDescriptor* fd, Handle mirror, TRAPS) {
  assert(mirror.not_null() && fd->is_static(), "just checking");
  if (fd->has_initial_value()) {
    BasicType t = fd->field_type();
    switch (t) {
      case T_BYTE:
        mirror()->byte_field_put(fd->offset(), fd->int_initial_value());
              break;
      case T_BOOLEAN:
        mirror()->bool_field_put(fd->offset(), fd->int_initial_value());
              break;
      case T_CHAR:
        mirror()->char_field_put(fd->offset(), fd->int_initial_value());
              break;
      case T_SHORT:
        mirror()->short_field_put(fd->offset(), fd->int_initial_value());
              break;
      case T_INT:
        mirror()->int_field_put(fd->offset(), fd->int_initial_value());
        break;
      case T_FLOAT:
        mirror()->float_field_put(fd->offset(), fd->float_initial_value());
        break;
      case T_DOUBLE:
        mirror()->double_field_put(fd->offset(), fd->double_initial_value());
        break;
      case T_LONG:
        mirror()->long_field_put(fd->offset(), fd->long_initial_value());
        break;
      case T_OBJECT:
        {
          #ifdef ASSERT
          TempNewSymbol sym = SymbolTable::new_symbol("Ljava/lang/String;", CHECK);
          assert(fd->signature() == sym, "just checking");
          #endif
          oop string = fd->string_initial_value(CHECK);
          mirror()->obj_field_put(fd->offset(), string);
        }
        break;
      default:
        THROW_MSG(vmSymbols::java_lang_ClassFormatError(),
                  "Illegal ConstantValue attribute in class file");
    }
  }
}
void java_lang_Class::fixup_mirror(KlassHandle k, TRAPS) {
  assert(InstanceMirrorKlass::offset_of_static_fields() != 0, "must have been computed already");
  if (!k->is_shared()) {
    if (k->oop_is_instance()) {
        for (JavaFieldStream fs(InstanceKlass::cast(k())); !fs.done(); fs.next()) {
        if (fs.access_flags().is_static()) {
          int real_offset = fs.offset() + InstanceMirrorKlass::offset_of_static_fields();
          fs.set_offset(real_offset);
        }
      }
    }
  }
  create_mirror(k, Handle(NULL), Handle(NULL), CHECK);
}
void java_lang_Class::initialize_mirror_fields(KlassHandle k,
                                               Handle mirror,
                                               Handle protection_domain,
                                               TRAPS) {
  typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK);
  set_init_lock(mirror(), r);
  set_protection_domain(mirror(), protection_domain());
  InstanceKlass::cast(k())->do_local_static_fields(&initialize_static_field, mirror, CHECK);
}
void java_lang_Class::create_mirror(KlassHandle k, Handle class_loader,
                                    Handle protection_domain, TRAPS) {
  assert(k->java_mirror() == NULL, "should only assign mirror once");
  int computed_modifiers = k->compute_modifier_flags(CHECK);
  k->set_modifier_flags(computed_modifiers);
  if (SystemDictionary::Class_klass_loaded()) {
    Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK);
    if (!k.is_null()) {
      java_lang_Class::set_klass(mirror(), k());
    }
    InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(mirror->klass());
    assert(oop_size(mirror()) == mk->instance_size(k), "should have been set");
    java_lang_Class::set_static_oop_field_count(mirror(), mk->compute_static_oop_field_count(mirror()));
    if (k->oop_is_array()) {
      Handle comp_mirror;
      if (k->oop_is_typeArray()) {
        BasicType type = TypeArrayKlass::cast(k())->element_type();
        comp_mirror = Universe::java_mirror(type);
      } else {
        assert(k->oop_is_objArray(), "Must be");
        Klass* element_klass = ObjArrayKlass::cast(k())->element_klass();
        assert(element_klass != NULL, "Must have an element klass");
        comp_mirror = element_klass->java_mirror();
      }
      assert(comp_mirror.not_null(), "must have a mirror");
      ArrayKlass::cast(k())->set_component_mirror(comp_mirror());
      set_array_klass(comp_mirror(), k());
    } else {
      assert(k->oop_is_instance(), "Must be");
      initialize_mirror_fields(k, mirror, protection_domain, THREAD);
      if (HAS_PENDING_EXCEPTION) {
        java_lang_Class::set_klass(mirror(), NULL);
        return;
      }
    }
    assert(class_loader() == k->class_loader(), "should be same");
    set_class_loader(mirror(), class_loader());
    if (!k.is_null()) {
      k->set_java_mirror(mirror());
    }
  } else {
    if (fixup_mirror_list() == NULL) {
      GrowableArray<Klass*>* list =
       new (ResourceObj::C_HEAP, mtClass) GrowableArray<Klass*>(40, true);
      set_fixup_mirror_list(list);
    }
    fixup_mirror_list()->push(k());
  }
}
int  java_lang_Class::oop_size(oop java_class) {
  assert(_oop_size_offset != 0, "must be set");
  return java_class->int_field(_oop_size_offset);
}
void java_lang_Class::set_oop_size(oop java_class, int size) {
  assert(_oop_size_offset != 0, "must be set");
  java_class->int_field_put(_oop_size_offset, size);
}
int  java_lang_Class::static_oop_field_count(oop java_class) {
  assert(_static_oop_field_count_offset != 0, "must be set");
  return java_class->int_field(_static_oop_field_count_offset);
}
void java_lang_Class::set_static_oop_field_count(oop java_class, int size) {
  assert(_static_oop_field_count_offset != 0, "must be set");
  java_class->int_field_put(_static_oop_field_count_offset, size);
}
oop java_lang_Class::protection_domain(oop java_class) {
  assert(_protection_domain_offset != 0, "must be set");
  return java_class->obj_field(_protection_domain_offset);
}
void java_lang_Class::set_protection_domain(oop java_class, oop pd) {
  assert(_protection_domain_offset != 0, "must be set");
  java_class->obj_field_put(_protection_domain_offset, pd);
}
oop java_lang_Class::init_lock(oop java_class) {
  assert(_init_lock_offset != 0, "must be set");
  return java_class->obj_field(_init_lock_offset);
}
void java_lang_Class::set_init_lock(oop java_class, oop init_lock) {
  assert(_init_lock_offset != 0, "must be set");
  java_class->obj_field_put(_init_lock_offset, init_lock);
}
objArrayOop java_lang_Class::signers(oop java_class) {
  assert(_signers_offset != 0, "must be set");
  return (objArrayOop)java_class->obj_field(_signers_offset);
}
void java_lang_Class::set_signers(oop java_class, objArrayOop signers) {
  assert(_signers_offset != 0, "must be set");
  java_class->obj_field_put(_signers_offset, (oop)signers);
}
void java_lang_Class::set_class_loader(oop java_class, oop loader) {
  if (_class_loader_offset != 0) {
    java_class->obj_field_put(_class_loader_offset, loader);
  }
}
oop java_lang_Class::class_loader(oop java_class) {
  assert(_class_loader_offset != 0, "must be set");
  return java_class->obj_field(_class_loader_offset);
}
oop java_lang_Class::create_basic_type_mirror(const char* basic_type_name, BasicType type, TRAPS) {
  oop java_class = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(NULL, CHECK_0);
  if (type != T_VOID) {
    Klass* aklass = Universe::typeArrayKlassObj(type);
    assert(aklass != NULL, "correct bootstrap");
    set_array_klass(java_class, aklass);
  }
#ifdef ASSERT
  InstanceMirrorKlass* mk = InstanceMirrorKlass::cast(SystemDictionary::Class_klass());
  assert(java_lang_Class::static_oop_field_count(java_class) == 0, "should have been zeroed by allocation");
#endif
  return java_class;
}
Klass* java_lang_Class::as_Klass(oop java_class) {
  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
  Klass* k = ((Klass*)java_class->metadata_field(_klass_offset));
  assert(k == NULL || k->is_klass(), "type check");
  return k;
}
void java_lang_Class::set_klass(oop java_class, Klass* klass) {
  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
  java_class->metadata_field_put(_klass_offset, klass);
}
void java_lang_Class::print_signature(oop java_class, outputStream* st) {
  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
  Symbol* name = NULL;
  bool is_instance = false;
  if (is_primitive(java_class)) {
    name = vmSymbols::type_signature(primitive_type(java_class));
  } else {
    Klass* k = as_Klass(java_class);
    is_instance = k->oop_is_instance();
    name = k->name();
  }
  if (name == NULL) {
    st->print("<null>");
    return;
  }
  if (is_instance)  st->print("L");
  st->write((char*) name->base(), (int) name->utf8_length());
  if (is_instance)  st->print(";");
}
Symbol* java_lang_Class::as_signature(oop java_class, bool intern_if_not_found, TRAPS) {
  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
  Symbol* name;
  if (is_primitive(java_class)) {
    name = vmSymbols::type_signature(primitive_type(java_class));
    name->increment_refcount();
  } else {
    Klass* k = as_Klass(java_class);
    if (!k->oop_is_instance()) {
      name = k->name();
      name->increment_refcount();
    } else {
      ResourceMark rm;
      const char* sigstr = k->signature_name();
      int         siglen = (int) strlen(sigstr);
      if (!intern_if_not_found) {
        name = SymbolTable::probe(sigstr, siglen);
      } else {
        name = SymbolTable::new_symbol(sigstr, siglen, THREAD);
      }
    }
  }
  return name;
}
const char* java_lang_Class::as_external_name(oop java_class) {
  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
  const char* name = NULL;
  if (is_primitive(java_class)) {
    name = type2name(primitive_type(java_class));
  } else {
    name = as_Klass(java_class)->external_name();
  }
  if (name == NULL) {
    name = "<null>";
  }
  return name;
}
Klass* java_lang_Class::array_klass(oop java_class) {
  Klass* k = ((Klass*)java_class->metadata_field(_array_klass_offset));
  assert(k == NULL || k->is_klass() && k->oop_is_array(), "should be array klass");
  return k;
}
void java_lang_Class::set_array_klass(oop java_class, Klass* klass) {
  assert(klass->is_klass() && klass->oop_is_array(), "should be array klass");
  java_class->metadata_field_put(_array_klass_offset, klass);
}
bool java_lang_Class::is_primitive(oop java_class) {
  bool is_primitive = (java_class->metadata_field(_klass_offset) == NULL);
#ifdef ASSERT
  if (is_primitive) {
    Klass* k = ((Klass*)java_class->metadata_field(_array_klass_offset));
    assert(k == NULL || is_java_primitive(ArrayKlass::cast(k)->element_type()),
        "Should be either the T_VOID primitive or a java primitive");
  }
#endif
  return is_primitive;
}
BasicType java_lang_Class::primitive_type(oop java_class) {
  assert(java_lang_Class::is_primitive(java_class), "just checking");
  Klass* ak = ((Klass*)java_class->metadata_field(_array_klass_offset));
  BasicType type = T_VOID;
  if (ak != NULL) {
    type = ArrayKlass::cast(ak)->element_type();
  } else {
    assert(java_class == Universe::void_mirror(), "only valid non-array primitive");
  }
  assert(Universe::java_mirror(type) == java_class, "must be consistent");
  return type;
}
BasicType java_lang_Class::as_BasicType(oop java_class, Klass** reference_klass) {
  assert(java_lang_Class::is_instance(java_class), "must be a Class object");
  if (is_primitive(java_class)) {
    if (reference_klass != NULL)
      (*reference_klass) = NULL;
    return primitive_type(java_class);
  } else {
    if (reference_klass != NULL)
      (*reference_klass) = as_Klass(java_class);
    return T_OBJECT;
  }
}
oop java_lang_Class::primitive_mirror(BasicType t) {
  oop mirror = Universe::java_mirror(t);
  assert(mirror != NULL && mirror->is_a(SystemDictionary::Class_klass()), "must be a Class");
  assert(java_lang_Class::is_primitive(mirror), "must be primitive");
  return mirror;
}
bool java_lang_Class::offsets_computed = false;
int  java_lang_Class::classRedefinedCount_offset = -1;
void java_lang_Class::compute_offsets() {
  assert(!offsets_computed, "offsets should be initialized only once");
  offsets_computed = true;
  Klass* klass_oop = SystemDictionary::Class_klass();
  compute_optional_offset(classRedefinedCount_offset,
                          klass_oop, vmSymbols::classRedefinedCount_name(), vmSymbols::int_signature());
  compute_optional_offset(_class_loader_offset,
                 klass_oop, vmSymbols::classLoader_name(),
                 vmSymbols::classloader_signature());
  CLASS_INJECTED_FIELDS(INJECTED_FIELD_COMPUTE_OFFSET);
}
int java_lang_Class::classRedefinedCount(oop the_class_mirror) {
  if (!JDK_Version::is_gte_jdk15x_version()
      || classRedefinedCount_offset == -1) {
    return -1;
  }
  return the_class_mirror->int_field(classRedefinedCount_offset);
}
void java_lang_Class::set_classRedefinedCount(oop the_class_mirror, int value) {
  if (!JDK_Version::is_gte_jdk15x_version()
      || classRedefinedCount_offset == -1) {
    return;
  }
  the_class_mirror->int_field_put(classRedefinedCount_offset, value);
}
int java_lang_Thread::_name_offset = 0;
int java_lang_Thread::_group_offset = 0;
int java_lang_Thread::_contextClassLoader_offset = 0;
int java_lang_Thread::_inheritedAccessControlContext_offset = 0;
int java_lang_Thread::_priority_offset = 0;
int java_lang_Thread::_eetop_offset = 0;
int java_lang_Thread::_daemon_offset = 0;
int java_lang_Thread::_stillborn_offset = 0;
int java_lang_Thread::_stackSize_offset = 0;
int java_lang_Thread::_tid_offset = 0;
int java_lang_Thread::_thread_status_offset = 0;
int java_lang_Thread::_park_blocker_offset = 0;
int java_lang_Thread::_park_event_offset = 0 ;
void java_lang_Thread::compute_offsets() {
  assert(_group_offset == 0, "offsets should be initialized only once");
  Klass* k = SystemDictionary::Thread_klass();
  compute_offset(_name_offset,      k, vmSymbols::name_name(),      vmSymbols::string_signature());
  compute_offset(_group_offset,     k, vmSymbols::group_name(),     vmSymbols::threadgroup_signature());
  compute_offset(_contextClassLoader_offset, k, vmSymbols::contextClassLoader_name(), vmSymbols::classloader_signature());
  compute_offset(_inheritedAccessControlContext_offset, k, vmSymbols::inheritedAccessControlContext_name(), vmSymbols::accesscontrolcontext_signature());
  compute_offset(_priority_offset,  k, vmSymbols::priority_name(),  vmSymbols::int_signature());
  compute_offset(_daemon_offset,    k, vmSymbols::daemon_name(),    vmSymbols::bool_signature());
  compute_offset(_eetop_offset,     k, vmSymbols::eetop_name(),     vmSymbols::long_signature());
  compute_offset(_stillborn_offset, k, vmSymbols::stillborn_name(), vmSymbols::bool_signature());
  compute_optional_offset(_stackSize_offset, k, vmSymbols::stackSize_name(), vmSymbols::long_signature());
  compute_optional_offset(_tid_offset, k, vmSymbols::thread_id_name(), vmSymbols::long_signature());
  compute_optional_offset(_thread_status_offset, k, vmSymbols::thread_status_name(), vmSymbols::int_signature());
  compute_optional_offset(_park_blocker_offset, k, vmSymbols::park_blocker_name(), vmSymbols::object_signature());
  compute_optional_offset(_park_event_offset, k, vmSymbols::park_event_name(),
 vmSymbols::long_signature());
}
JavaThread* java_lang_Thread::thread(oop java_thread) {
  return (JavaThread*)java_thread->address_field(_eetop_offset);
}
void java_lang_Thread::set_thread(oop java_thread, JavaThread* thread) {
  java_thread->address_field_put(_eetop_offset, (address)thread);
}
oop java_lang_Thread::name(oop java_thread) {
  return java_thread->obj_field(_name_offset);
}
void java_lang_Thread::set_name(oop java_thread, oop name) {
  java_thread->obj_field_put(_name_offset, name);
}
ThreadPriority java_lang_Thread::priority(oop java_thread) {
  return (ThreadPriority)java_thread->int_field(_priority_offset);
}
void java_lang_Thread::set_priority(oop java_thread, ThreadPriority priority) {
  java_thread->int_field_put(_priority_offset, priority);
}
oop java_lang_Thread::threadGroup(oop java_thread) {
  return java_thread->obj_field(_group_offset);
}
bool java_lang_Thread::is_stillborn(oop java_thread) {
  return java_thread->bool_field(_stillborn_offset) != 0;
}
void java_lang_Thread::set_stillborn(oop java_thread) {
  java_thread->bool_field_put(_stillborn_offset, true);
}
bool java_lang_Thread::is_alive(oop java_thread) {
  JavaThread* thr = java_lang_Thread::thread(java_thread);
  return (thr != NULL);
}
bool java_lang_Thread::is_daemon(oop java_thread) {
  return java_thread->bool_field(_daemon_offset) != 0;
}
void java_lang_Thread::set_daemon(oop java_thread) {
  java_thread->bool_field_put(_daemon_offset, true);
}
oop java_lang_Thread::context_class_loader(oop java_thread) {
  return java_thread->obj_field(_contextClassLoader_offset);
}
oop java_lang_Thread::inherited_access_control_context(oop java_thread) {
  return java_thread->obj_field(_inheritedAccessControlContext_offset);
}
jlong java_lang_Thread::stackSize(oop java_thread) {
  if (_stackSize_offset > 0) {
    assert(JDK_Version::is_gte_jdk14x_version(), "sanity check");
    return java_thread->long_field(_stackSize_offset);
  } else {
    return 0;
  }
}
void java_lang_Thread::set_thread_status(oop java_thread,
                                         java_lang_Thread::ThreadStatus status) {
  if (_thread_status_offset > 0) {
    java_thread->int_field_put(_thread_status_offset, status);
  }
}
java_lang_Thread::ThreadStatus java_lang_Thread::get_thread_status(oop java_thread) {
  assert(Threads_lock->owned_by_self() || Thread::current()->is_Watcher_thread() ||
         Thread::current()->is_VM_thread() ||
         JavaThread::current()->thread_state() == _thread_in_vm,
         "Java Thread is not running in vm");
  if (_thread_status_offset > 0) {
    return (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
  } else {
    JavaThread* thr = java_lang_Thread::thread(java_thread);
    if (thr == NULL) {
      return NEW;
    }
    return (java_lang_Thread::ThreadStatus)JVMTI_THREAD_STATE_ALIVE;
  }
}
jlong java_lang_Thread::thread_id(oop java_thread) {
  if (_tid_offset > 0) {
    return java_thread->long_field(_tid_offset);
  } else {
    return 0;
  }
}
oop java_lang_Thread::park_blocker(oop java_thread) {
  assert(JDK_Version::current().supports_thread_park_blocker() &&
         _park_blocker_offset != 0, "Must support parkBlocker field");
  if (_park_blocker_offset > 0) {
    return java_thread->obj_field(_park_blocker_offset);
  }
  return NULL;
}
jlong java_lang_Thread::park_event(oop java_thread) {
  if (_park_event_offset > 0) {
    return java_thread->long_field(_park_event_offset);
  }
  return 0;
}
bool java_lang_Thread::set_park_event(oop java_thread, jlong ptr) {
  if (_park_event_offset > 0) {
    java_thread->long_field_put(_park_event_offset, ptr);
    return true;
  }
  return false;
}
const char* java_lang_Thread::thread_status_name(oop java_thread) {
  assert(JDK_Version::is_gte_jdk15x_version() && _thread_status_offset != 0, "Must have thread status");
  ThreadStatus status = (java_lang_Thread::ThreadStatus)java_thread->int_field(_thread_status_offset);
  switch (status) {
    case NEW                      : return "NEW";
    case RUNNABLE                 : return "RUNNABLE";
    case SLEEPING                 : return "TIMED_WAITING (sleeping)";
    case IN_OBJECT_WAIT           : return "WAITING (on object monitor)";
    case IN_OBJECT_WAIT_TIMED     : return "TIMED_WAITING (on object monitor)";
    case PARKED                   : return "WAITING (parking)";
    case PARKED_TIMED             : return "TIMED_WAITING (parking)";
    case BLOCKED_ON_MONITOR_ENTER : return "BLOCKED (on object monitor)";
    case TERMINATED               : return "TERMINATED";
    default                       : return "UNKNOWN";
  };
}
int java_lang_ThreadGroup::_parent_offset = 0;
int java_lang_ThreadGroup::_name_offset = 0;
int java_lang_ThreadGroup::_threads_offset = 0;
int java_lang_ThreadGroup::_groups_offset = 0;
int java_lang_ThreadGroup::_maxPriority_offset = 0;
int java_lang_ThreadGroup::_destroyed_offset = 0;
int java_lang_ThreadGroup::_daemon_offset = 0;
int java_lang_ThreadGroup::_vmAllowSuspension_offset = 0;
int java_lang_ThreadGroup::_nthreads_offset = 0;
int java_lang_ThreadGroup::_ngroups_offset = 0;
oop  java_lang_ThreadGroup::parent(oop java_thread_group) {
  assert(java_thread_group->is_oop(), "thread group must be oop");
  return java_thread_group->obj_field(_parent_offset);
}
typeArrayOop java_lang_ThreadGroup::name(oop java_thread_group) {
  oop name = java_thread_group->obj_field(_name_offset);
  return name == NULL ? (typeArrayOop)NULL : java_lang_String::value(name);
}
int java_lang_ThreadGroup::nthreads(oop java_thread_group) {
  assert(java_thread_group->is_oop(), "thread group must be oop");
  return java_thread_group->int_field(_nthreads_offset);
}
objArrayOop java_lang_ThreadGroup::threads(oop java_thread_group) {
  oop threads = java_thread_group->obj_field(_threads_offset);
  assert(threads != NULL, "threadgroups should have threads");
  assert(threads->is_objArray(), "just checking"); // Todo: Add better type checking code
  return objArrayOop(threads);
}
int java_lang_ThreadGroup::ngroups(oop java_thread_group) {
  assert(java_thread_group->is_oop(), "thread group must be oop");
  return java_thread_group->int_field(_ngroups_offset);
}
objArrayOop java_lang_ThreadGroup::groups(oop java_thread_group) {
  oop groups = java_thread_group->obj_field(_groups_offset);
  assert(groups == NULL || groups->is_objArray(), "just checking"); // Todo: Add better type checking code
  return objArrayOop(groups);
}
ThreadPriority java_lang_ThreadGroup::maxPriority(oop java_thread_group) {
  assert(java_thread_group->is_oop(), "thread group must be oop");
  return (ThreadPriority) java_thread_group->int_field(_maxPriority_offset);
}
bool java_lang_ThreadGroup::is_destroyed(oop java_thread_group) {
  assert(java_thread_group->is_oop(), "thread group must be oop");
  return java_thread_group->bool_field(_destroyed_offset) != 0;
}
bool java_lang_ThreadGroup::is_daemon(oop java_thread_group) {
  assert(java_thread_group->is_oop(), "thread group must be oop");
  return java_thread_group->bool_field(_daemon_offset) != 0;
}
bool java_lang_ThreadGroup::is_vmAllowSuspension(oop java_thread_group) {
  assert(java_thread_group->is_oop(), "thread group must be oop");
  return java_thread_group->bool_field(_vmAllowSuspension_offset) != 0;
}
void java_lang_ThreadGroup::compute_offsets() {
  assert(_parent_offset == 0, "offsets should be initialized only once");
  Klass* k = SystemDictionary::ThreadGroup_klass();
  compute_offset(_parent_offset,      k, vmSymbols::parent_name(),      vmSymbols::threadgroup_signature());
  compute_offset(_name_offset,        k, vmSymbols::name_name(),        vmSymbols::string_signature());
  compute_offset(_threads_offset,     k, vmSymbols::threads_name(),     vmSymbols::thread_array_signature());
  compute_offset(_groups_offset,      k, vmSymbols::groups_name(),      vmSymbols::threadgroup_array_signature());
  compute_offset(_maxPriority_offset, k, vmSymbols::maxPriority_name(), vmSymbols::int_signature());
  compute_offset(_destroyed_offset,   k, vmSymbols::destroyed_name(),   vmSymbols::bool_signature());
  compute_offset(_daemon_offset,      k, vmSymbols::daemon_name(),      vmSymbols::bool_signature());
  compute_offset(_vmAllowSuspension_offset, k, vmSymbols::vmAllowSuspension_name(), vmSymbols::bool_signature());
  compute_offset(_nthreads_offset,    k, vmSymbols::nthreads_name(),    vmSymbols::int_signature());
  compute_offset(_ngroups_offset,     k, vmSymbols::ngroups_name(),     vmSymbols::int_signature());
}
oop java_lang_Throwable::unassigned_stacktrace() {
  InstanceKlass* ik = InstanceKlass::cast(SystemDictionary::Throwable_klass());
  address addr = ik->static_field_addr(static_unassigned_stacktrace_offset);
  if (UseCompressedOops) {
    return oopDesc::load_decode_heap_oop((narrowOop *)addr);
  } else {
    return oopDesc::load_decode_heap_oop((oop*)addr);
  }
}
oop java_lang_Throwable::backtrace(oop throwable) {
  return throwable->obj_field_acquire(backtrace_offset);
}
void java_lang_Throwable::set_backtrace(oop throwable, oop value) {
  throwable->release_obj_field_put(backtrace_offset, value);
}
oop java_lang_Throwable::message(oop throwable) {
  return throwable->obj_field(detailMessage_offset);
}
oop java_lang_Throwable::message(Handle throwable) {
  return throwable->obj_field(detailMessage_offset);
}
Symbol* java_lang_Throwable::detail_message(oop throwable) {
  PRESERVE_EXCEPTION_MARK;  // Keep original exception
  oop detailed_message = java_lang_Throwable::message(throwable);
  if (detailed_message != NULL) {
    return java_lang_String::as_symbol(detailed_message, THREAD);
  }
  return NULL;
}
void java_lang_Throwable::set_message(oop throwable, oop value) {
  throwable->obj_field_put(detailMessage_offset, value);
}
void java_lang_Throwable::set_stacktrace(oop throwable, oop st_element_array) {
  throwable->obj_field_put(stackTrace_offset, st_element_array);
}
void java_lang_Throwable::clear_stacktrace(oop throwable) {
  assert(JDK_Version::is_gte_jdk14x_version(), "should only be called in >= 1.4");
  set_stacktrace(throwable, NULL);
}
void java_lang_Throwable::print(oop throwable, outputStream* st) {
  ResourceMark rm;
  Klass* k = throwable->klass();
  assert(k != NULL, "just checking");
  st->print("%s", InstanceKlass::cast(k)->external_name());
  oop msg = message(throwable);
  if (msg != NULL) {
    st->print(": %s", java_lang_String::as_utf8_string(msg));
  }
}
void java_lang_Throwable::print(Handle throwable, outputStream* st) {
  ResourceMark rm;
  Klass* k = throwable->klass();
  assert(k != NULL, "just checking");
  st->print("%s", InstanceKlass::cast(k)->external_name());
  oop msg = message(throwable);
  if (msg != NULL) {
    st->print(": %s", java_lang_String::as_utf8_string(msg));
  }
}
const int MAX_VERSION = USHRT_MAX;
static inline int merge_bci_and_version(int bci, int version) {
  if (version > USHRT_MAX || version < 0) version = MAX_VERSION;
  assert((jushort)bci == bci, "bci should be short");
  return build_int_from_shorts(version, bci);
}
static inline int bci_at(unsigned int merged) {
  return extract_high_short_from_int(merged);
}
static inline int version_at(unsigned int merged) {
  return extract_low_short_from_int(merged);
}
static inline bool version_matches(Method* method, int version) {
  assert(version < MAX_VERSION, "version is too big");
  return method != NULL && (method->constants()->version() == version);
}
static inline int get_line_number(Method* method, int bci) {
  int line_number = 0;
  if (method->is_native()) {
    line_number = -2;
  } else {
    line_number = method->line_number_from_bci(bci);
    if (line_number == -1 && ShowHiddenFrames) {
      line_number = bci + 1000000;
    }
  }
  return line_number;
}
class BacktraceBuilder: public StackObj {
 private:
  Handle          _backtrace;
  objArrayOop     _head;
  typeArrayOop    _methods;
  typeArrayOop    _bcis;
  objArrayOop     _mirrors;
  typeArrayOop    _cprefs; // needed to insulate method name against redefinition
  int             _index;
  No_Safepoint_Verifier _nsv;
 public:
  enum {
    trace_methods_offset = java_lang_Throwable::trace_methods_offset,
    trace_bcis_offset    = java_lang_Throwable::trace_bcis_offset,
    trace_mirrors_offset = java_lang_Throwable::trace_mirrors_offset,
    trace_cprefs_offset  = java_lang_Throwable::trace_cprefs_offset,
    trace_next_offset    = java_lang_Throwable::trace_next_offset,
    trace_size           = java_lang_Throwable::trace_size,
    trace_chunk_size     = java_lang_Throwable::trace_chunk_size
  };
  static typeArrayOop get_methods(objArrayHandle chunk) {
    typeArrayOop methods = typeArrayOop(chunk->obj_at(trace_methods_offset));
    assert(methods != NULL, "method array should be initialized in backtrace");
    return methods;
  }
  static typeArrayOop get_bcis(objArrayHandle chunk) {
    typeArrayOop bcis = typeArrayOop(chunk->obj_at(trace_bcis_offset));
    assert(bcis != NULL, "bci array should be initialized in backtrace");
    return bcis;
  }
  static objArrayOop get_mirrors(objArrayHandle chunk) {
    objArrayOop mirrors = objArrayOop(chunk->obj_at(trace_mirrors_offset));
    assert(mirrors != NULL, "mirror array should be initialized in backtrace");
    return mirrors;
  }
  static typeArrayOop get_cprefs(objArrayHandle chunk) {
    typeArrayOop cprefs = typeArrayOop(chunk->obj_at(trace_cprefs_offset));
    assert(cprefs != NULL, "cprefs array should be initialized in backtrace");
    return cprefs;
  }
  BacktraceBuilder(TRAPS): _methods(NULL), _bcis(NULL), _head(NULL), _mirrors(NULL), _cprefs(NULL) {
    expand(CHECK);
    _backtrace = _head;
    _index = 0;
  }
  BacktraceBuilder(objArrayHandle backtrace) {
    _methods = get_methods(backtrace);
    _bcis = get_bcis(backtrace);
    _mirrors = get_mirrors(backtrace);
    _cprefs = get_cprefs(backtrace);
    assert(_methods->length() == _bcis->length() &&
           _methods->length() == _mirrors->length(),
           "method and source information arrays should match");
    _backtrace = _head = backtrace();
    _index = 0;
  }
  void expand(TRAPS) {
    objArrayHandle old_head(THREAD, _head);
    Pause_No_Safepoint_Verifier pnsv(&_nsv);
    objArrayOop head = oopFactory::new_objectArray(trace_size, CHECK);
    objArrayHandle new_head(THREAD, head);
    typeArrayOop methods = oopFactory::new_shortArray(trace_chunk_size, CHECK);
    typeArrayHandle new_methods(THREAD, methods);
    typeArrayOop bcis = oopFactory::new_intArray(trace_chunk_size, CHECK);
    typeArrayHandle new_bcis(THREAD, bcis);
    objArrayOop mirrors = oopFactory::new_objectArray(trace_chunk_size, CHECK);
    objArrayHandle new_mirrors(THREAD, mirrors);
    typeArrayOop cprefs = oopFactory::new_shortArray(trace_chunk_size, CHECK);
    typeArrayHandle new_cprefs(THREAD, cprefs);
    if (!old_head.is_null()) {
      old_head->obj_at_put(trace_next_offset, new_head());
    }
    new_head->obj_at_put(trace_methods_offset, new_methods());
    new_head->obj_at_put(trace_bcis_offset, new_bcis());
    new_head->obj_at_put(trace_mirrors_offset, new_mirrors());
    new_head->obj_at_put(trace_cprefs_offset, new_cprefs());
    _head    = new_head();
    _methods = new_methods();
    _bcis = new_bcis();
    _mirrors = new_mirrors();
    _cprefs  = new_cprefs();
    _index = 0;
  }
  oop backtrace() {
    return _backtrace();
  }
  inline void push(Method* method, int bci, TRAPS) {
    if (bci == SynchronizationEntryBCI) bci = 0;
    if (_index >= trace_chunk_size) {
      methodHandle mhandle(THREAD, method);
      expand(CHECK);
      method = mhandle();
    }
    _methods->ushort_at_put(_index, method->orig_method_idnum());
    _bcis->int_at_put(_index, merge_bci_and_version(bci, method->constants()->version()));
    _cprefs->ushort_at_put(_index, method->name_index());
    assert(method->method_holder()->java_mirror() != NULL, "never push null for mirror");
    _mirrors->obj_at_put(_index, method->method_holder()->java_mirror());
    _index++;
  }
};
char* java_lang_Throwable::print_stack_element_to_buffer(Handle mirror,
                                  int method_id, int version, int bci, int cpref) {
  InstanceKlass* holder = InstanceKlass::cast(java_lang_Class::as_Klass(mirror()));
  const char* klass_name  = holder->external_name();
  int buf_len = (int)strlen(klass_name);
  Method* method = holder->method_with_orig_idnum(method_id, version);
  Symbol* sym = (method != NULL) ? method->name() : holder->constants()->symbol_at(cpref);
  char* method_name = sym->as_C_string();
  buf_len += (int)strlen(method_name);
  holder = holder->get_klass_version(version);
  char* source_file_name = NULL;
  if (holder != NULL) {
    Symbol* source = holder->source_file_name();
    if (source != NULL) {
      source_file_name = source->as_C_string();
      buf_len += (int)strlen(source_file_name);
    }
  }
  char* buf = NEW_RESOURCE_ARRAY(char, buf_len + 64);
  sprintf(buf, "\tat %s.%s", klass_name, method_name);
  if (!version_matches(method, version)) {
    strcat(buf, "(Redefined)");
  } else {
    int line_number = get_line_number(method, bci);
    if (line_number == -2) {
      strcat(buf, "(Native Method)");
    } else {
      if (source_file_name != NULL && (line_number != -1)) {
        sprintf(buf + (int)strlen(buf), "(%s:%d)", source_file_name, line_number);
      } else if (source_file_name != NULL) {
        sprintf(buf + (int)strlen(buf), "(%s)", source_file_name);
      } else {
        sprintf(buf + (int)strlen(buf), "(Unknown Source)");
      }
      nmethod* nm = method->code();
      if (WizardMode && nm != NULL) {
        sprintf(buf + (int)strlen(buf), "(nmethod " INTPTR_FORMAT ")", (intptr_t)nm);
      }
    }
  }
  return buf;
}
void java_lang_Throwable::print_stack_element(outputStream *st, Handle mirror,
                                              int method_id, int version, int bci, int cpref) {
  ResourceMark rm;
  char* buf = print_stack_element_to_buffer(mirror, method_id, version, bci, cpref);
  st->print_cr("%s", buf);
}
void java_lang_Throwable::print_stack_element(outputStream *st, methodHandle method, int bci) {
  Handle mirror = method->method_holder()->java_mirror();
  int method_id = method->orig_method_idnum();
  int version = method->constants()->version();
  int cpref = method->name_index();
  print_stack_element(st, mirror, method_id, version, bci, cpref);
}
const char* java_lang_Throwable::no_stack_trace_message() {
  return "\t<<no stack trace available>>";
}
void java_lang_Throwable::print_stack_trace(oop throwable, outputStream* st) {
  Thread *THREAD = Thread::current();
  Handle h_throwable(THREAD, throwable);
  while (h_throwable.not_null()) {
    objArrayHandle result (THREAD, objArrayOop(backtrace(h_throwable())));
    if (result.is_null()) {
      st->print_cr("%s", no_stack_trace_message());
      return;
    }
    while (result.not_null()) {
      typeArrayHandle methods (THREAD, BacktraceBuilder::get_methods(result));
      typeArrayHandle bcis (THREAD, BacktraceBuilder::get_bcis(result));
      objArrayHandle mirrors (THREAD, BacktraceBuilder::get_mirrors(result));
      typeArrayHandle cprefs (THREAD, BacktraceBuilder::get_cprefs(result));
      int length = methods()->length();
      for (int index = 0; index < length; index++) {
        Handle mirror(THREAD, mirrors->obj_at(index));
        if (mirror.is_null()) goto handle_cause;
        int method = methods->ushort_at(index);
        int version = version_at(bcis->int_at(index));
        int bci = bci_at(bcis->int_at(index));
        int cpref = cprefs->ushort_at(index);
        print_stack_element(st, mirror, method, version, bci, cpref);
      }
      result = objArrayHandle(THREAD, objArrayOop(result->obj_at(trace_next_offset)));
    }
  handle_cause:
    {
      EXCEPTION_MARK;
      JavaValue cause(T_OBJECT);
      JavaCalls::call_virtual(&cause,
                              h_throwable,
                              KlassHandle(THREAD, h_throwable->klass()),
                              vmSymbols::getCause_name(),
                              vmSymbols::void_throwable_signature(),
                              THREAD);
      if (HAS_PENDING_EXCEPTION) {
        CLEAR_PENDING_EXCEPTION;
        h_throwable = Handle();
      } else {
        h_throwable = Handle(THREAD, (oop) cause.get_jobject());
        if (h_throwable.not_null()) {
          st->print("Caused by: ");
          print(h_throwable, st);
          st->cr();
        }
      }
    }
  }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值