// Fill in information already parsed this_klass->set_should_verify_class(verify); jint lh = Klass::instance_layout_helper(info.instance_size, false); this_klass->set_layout_helper(lh);
if (has_final_method) { this_klass->set_has_final_method(); } this_klass->copy_method_ordering(method_ordering, CHECK_NULL); // The InstanceKlass::_methods_jmethod_ids cache // is managed on the assumption that the initial cache // size is equal to the number of methods in the class. If // that changes, then InstanceKlass::idnum_can_increment() // has to be changed accordingly. this_klass->set_initial_method_idnum(methods->length()); this_klass->set_name(cp->klass_name_at(_this_class_index)); if (is_anonymous()) // I am well known to myself cp->klass_at_put(_this_class_index, this_klass()); // eagerly resolve
if (!host_klass.is_null()) { assert (this_klass->is_anonymous(), "should be the same"); this_klass->set_host_klass(host_klass()); }
if (cached_class_file != NULL) { // JVMTI: we have an InstanceKlass now, tell it about the cached bytes this_klass->set_cached_class_file(cached_class_file); } // 创建镜像类和静态字段初始化 java_lang_Class::create_mirror(this_klass, class_loader, protection_domain, CHECK_(nullHandle)); } }
classInstanceKlass:public Klass { friendclassVMStructs; friendclassClassFileParser; friendclassCompileReplay;
protected: // Constructor InstanceKlass(int vtable_len, int itable_len, int static_field_size, int nonstatic_oop_map_size, ReferenceType rt, AccessFlags access_flags, bool is_anonymous); public: static InstanceKlass* allocate_instance_klass( ClassLoaderData* loader_data, int vtable_len, int itable_len, int static_field_size, int nonstatic_oop_map_size, ReferenceType rt, AccessFlags access_flags, Symbol* name, Klass* super_klass, bool is_anonymous, TRAPS);
InstanceKlass() { assert(DumpSharedSpaces || UseSharedSpaces, "only for CDS"); }
// See "The Java Virtual Machine Specification" section 2.16.2-5 for a detailed description // of the class loading & initialization procedure, and the use of the states. enumClassState { allocated, // allocated (but not yet linked) loaded, // loaded and inserted in class hierarchy (but not linked yet) linked, // successfully linked/verified (but not initialized yet) being_initialized, // currently running class initializer fully_initialized, // initialized (successfull final state) initialization_error // error happened during initialization };
protected: // Annotations for this class Annotations* _annotations; // Array classes holding elements of this class. Klass* _array_klasses; // Constant pool for this class. ConstantPool* _constants; // The InnerClasses attribute and EnclosingMethod attribute. The // _inner_classes is an array of shorts. If the class has InnerClasses // attribute, then the _inner_classes array begins with 4-tuples of shorts // [inner_class_info_index, outer_class_info_index, // inner_name_index, inner_class_access_flags] for the InnerClasses // attribute. If the EnclosingMethod attribute exists, it occupies the // last two shorts [class_index, method_index] of the array. If only // the InnerClasses attribute exists, the _inner_classes array length is // number_of_inner_classes * 4. If the class has both InnerClasses // and EnclosingMethod attributes the _inner_classes array length is // number_of_inner_classes * 4 + enclosing_method_attribute_size. Array<jushort>* _inner_classes;
// the source debug extension for this klass, NULL if not specified. // Specified as UTF-8 string without terminating zero byte in the classfile, // it is stored in the instanceklass as a NULL-terminated UTF-8 string char* _source_debug_extension; // Array name derived from this class which needs unreferencing // if this class is unloaded. Symbol* _array_name;
// Number of heapOopSize words used by non-static fields in this klass // (including inherited fields but after header_size()). int _nonstatic_field_size; int _static_field_size; // number words used by static fields (oop and non-oop) in this klass // Constant pool index to the utf8 entry of the Generic signature, // or 0 if none. u2 _generic_signature_index; // Constant pool index to the utf8 entry for the name of source file // containing this klass, 0 if not specified. u2 _source_file_name_index; u2 _static_oop_field_count;// number of static oop fields in this klass u2 _java_fields_count; // The number of declared Java fields int _nonstatic_oop_map_size;// size in words of nonstatic oop map blocks
// _is_marked_dependent can be set concurrently, thus cannot be part of the // _misc_flags. bool _is_marked_dependent; // used for marking during flushing and deoptimization bool _is_being_redefined; // used for locking redefinition bool _has_unloaded_dependent;
enum { _misc_rewritten = 1 << 0, // methods rewritten. _misc_has_nonstatic_fields = 1 << 1, // for sizing with UseCompressedOops _misc_should_verify_class = 1 << 2, // allow caching of preverification _misc_is_anonymous = 1 << 3, // has embedded _host_klass field _misc_is_contended = 1 << 4, // marked with contended annotation _misc_has_default_methods = 1 << 5, // class/superclass/implemented interfaces has default methods _misc_declares_default_methods = 1 << 6, // directly declares default methods (any access) _misc_has_been_redefined = 1 << 7// class has been redefined }; u2 _misc_flags; u2 _minor_version; // minor version number of class file u2 _major_version; // major version number of class file Thread* _init_thread; // Pointer to current thread doing initialization (to handle recursive initialization) int _vtable_len; // length of Java vtable (in words) int _itable_len; // length of Java itable (in words) OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily) MemberNameTable* _member_names; // Member names JNIid* _jni_ids; // First JNI identifier for static fields in this class jmethodID* _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none nmethodBucket* _dependencies; // list of dependent nmethods nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class BreakpointInfo* _breakpoints; // bpt lists, managed by Method* // Linked instanceKlasses of previous versions InstanceKlass* _previous_versions; // JVMTI fields can be moved to their own structure - see 6315920 // JVMTI: cached class file, before retransformable agent modified it in CFLH JvmtiCachedClassFileData* _cached_class_file;
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
// Class states are defined as ClassState (see above). // Place the _init_state here to utilize the unused 2-byte after // _idnum_allocated_count. u1 _init_state; // state of class u1 _reference_type; // reference type
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration
NOT_PRODUCT(int _verify_count;) // to avoid redundant verifies
// Method array. Array<Method*>* _methods; // Default Method Array, concrete methods inherited from interfaces Array<Method*>* _default_methods; // Interface (Klass*s) this class declares locally to implement. Array<Klass*>* _local_interfaces; // Interface (Klass*s) this class implements transitively. Array<Klass*>* _transitive_interfaces; // Int array containing the original order of method in the class file (for JVMTI). Array<int>* _method_ordering; // Int array containing the vtable_indices for default_methods // offset matches _default_methods offset Array<int>* _default_vtable_indices;
// Instance and static variable information, starts with 6-tuples of shorts // [access, name index, sig index, initval index, low_offset, high_offset] // for all fields, followed by the generic signature data at the end of // the array. Only fields with generic signature attributes have the generic // signature data set in the array. The fields array looks like following: // // f1: [access, name index, sig index, initial value index, low_offset, high_offset] // f2: [access, name index, sig index, initial value index, low_offset, high_offset] // ... // fn: [access, name index, sig index, initial value index, low_offset, high_offset] // [generic signature index] // [generic signature index] // ... Array<u2>* _fields;
/** 预留空间来存放 vtable(虚拟表), itable(接口表), 静态字段,引用的 map */ // embedded Java vtable follows here // embedded Java itables follows here // embedded static fields follows here // embedded nonstatic oop-map blocks follows here // embedded implementor of this interface follows here // The embedded implementor only exists if the current klass is an // iterface. The possible values of the implementor fall into following // three cases: // NULL: no implementor. // A Klass* that's not itself: one implementor. // Itself: more than one implementors. // embedded host klass follows here // The embedded host klass only exists in an anonymous class for // dynamic language support (JSR 292 enabled). The host class grants // its access privileges to this class also. The host class is either // named, or a previously loaded anonymous class. A non-anonymous class // or an anonymous class loaded through normal classloading does not // have this embedded field. //
... ... }
在上面解析 class 文件的源码中,我们看到了在调用 `allocate_instance_klass()` 创建一个 instanceKlass 之后,看到 `create_mirror()` 的函数,创建一个镜像类,接下来看看这个镜像类。
voidjava_lang_Class::create_mirror(KlassHandle k, Handle class_loader, Handle protection_domain, TRAPS){ assert(k->java_mirror() == NULL, "should only assign mirror once"); // Use this moment of initialization to cache modifier_flags also, // to support Class.getModifiers(). Instance classes recalculate // the cached flags after the class file is parsed, but before the // class is put into the system dictionary. int computed_modifiers = k->compute_modifier_flags(CHECK); k->set_modifier_flags(computed_modifiers); // Class_klass has to be loaded because it is used to allocate // the mirror. if (SystemDictionary::Class_klass_loaded()) { // Allocate mirror (java.lang.Class instance) Handle mirror = InstanceMirrorKlass::cast(SystemDictionary::Class_klass())->allocate_instance(k, CHECK);
// Setup indirection from mirror->klass 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");
// It might also have a component mirror. This mirror must already exist. 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");
// Two-way link between the array klass and its component 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) { // If any of the fields throws an exception like OOM remove the klass field // from the mirror so GC doesn't follow it after the klass has been deallocated. // This mirror looks like a primitive type, which logically it is because it // it represents no class. java_lang_Class::set_klass(mirror(), NULL); return; } }
// set the classLoader field in the java_lang_Class instance assert(class_loader() == k->class_loader(), "should be same"); set_class_loader(mirror(), class_loader());
// Setup indirection from klass->mirror last // after any exceptions can happen during allocations. 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()); } }
voidjava_lang_Class::initialize_mirror_fields(KlassHandle k, Handle mirror, Handle protection_domain, TRAPS){ // Allocate a simple java object for a lock. // This needs to be a java object because during class initialization // it can be held across a java call. typeArrayOop r = oopFactory::new_typeArray(T_INT, 0, CHECK); set_init_lock(mirror(), r);
// Set protection domain also set_protection_domain(mirror(), protection_domain());