/* * Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. *
*/
// An InstanceKlass is the VM level representation of a Java class. // It contains all information needed for at class at execution runtime.
// InstanceKlass embedded field layout (after declared fields): // [EMBEDDED Java vtable ] size in words = vtable_len // [EMBEDDED nonstatic oop-map blocks] size in words = nonstatic_oop_map_size // The embedded nonstatic oop-map blocks are short pairs (offset, length) // indicating where oops are located in instances of this klass. // [EMBEDDED implementor of the interface] only exist for interface
// forward declaration for class -- see below for definition #if INCLUDE_JVMTI class BreakpointInfo; #endif class ClassFileParser; class ClassFileStream; class KlassDepChange; class DependencyContext; class fieldDescriptor; class jniIdMapBase; class JNIid; class JvmtiCachedClassFieldMap; class nmethodBucket; class OopMapCache; class InterpreterOopMap; class PackageEntry; class ModuleEntry;
// This is used in iterators below. class FieldClosure: public StackObj { public: virtualvoid do_field(fieldDescriptor* fd) = 0;
};
// Print fields. // If "obj" argument to constructor is NULL, prints static fields, otherwise prints non-static fields. class FieldPrinter: public FieldClosure {
oop _obj;
outputStream* _st; public:
FieldPrinter(outputStream* st, oop obj = NULL) : _obj(obj), _st(st) {} void do_field(fieldDescriptor* fd);
};
// Describes where oops are located in instances of this klass. class OopMapBlock { public: // Byte offset of the first oop mapped by this block. int offset() const { return _offset; } void set_offset(int offset) { _offset = offset; }
// Number of oops in this block.
uint count() const { return _count; } void set_count(uint count) { _count = count; }
public:
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. enum ClassState : u1 {
allocated, // allocated (but not yet linked)
loaded, // loaded and inserted in class hierarchy (but not linked yet)
being_linked, // currently running verifier and rewriter
linked, // successfully linked/verified (but not initialized yet)
being_initialized, // currently running class initializer
fully_initialized, // initialized (successful final state)
initialization_error // error happened during initialization
};
protected: // If you add a new field that points to any metaspace object, you // must add this field to InstanceKlass::metaspace_pointers_do().
// Annotations for this class
Annotations* _annotations; // Package this class is defined in
PackageEntry* _package_entry; // Array classes holding elements of this class.
ObjArrayKlass* volatile _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 NestMembers attribute. An array of shorts, where each is a // class info index for the class that is a nest member. This data // has not been validated.
Array<jushort>* _nest_members;
// Resolved nest-host klass: either true nest-host or self if we are not // nested, or an error occurred resolving or validating the nominated // nest-host. Can also be set directly by JDK API's that establish nest // relationships. // By always being set it makes nest-member access checks simpler.
InstanceKlass* _nest_host;
// The PermittedSubclasses attribute. An array of shorts, where each is a // class info index for the class that is a permitted subclass.
Array<jushort>* _permitted_subclasses;
// The contents of the Record attribute.
Array<RecordComponent*>* _record_components;
// 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 constchar* _source_debug_extension;
// 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 int _nonstatic_oop_map_size; // size in words of nonstatic oop map blocks int _itable_len; // length of Java itable (in words)
// The NestHost attribute. The class info index for the class // that is the nest-host of this class. This data has not been validated.
u2 _nest_host_index;
u2 _this_class_index; // constant pool entry
u2 _static_oop_field_count; // number of static oop fields in this klass
u2 _java_fields_count; // The number of declared Java fields
volatile u2 _idnum_allocated_count; // JNI/JVMTI: increments with the addition of methods, old ids don't change
// _is_marked_dependent can be set concurrently, thus cannot be part of the // _misc_status right now. bool _is_marked_dependent; // used for marking during flushing and deoptimization
ClassState _init_state; // state of class
u1 _reference_type; // reference type
// State is set while executing, eventually atomically to not disturb other state
InstanceKlassMiscStatus _misc_status;
Monitor* _init_monitor; // mutual exclusion to _init_state and _init_thread.
Thread* _init_thread; // Pointer to current thread doing initialization (to handle recursive initialization)
OopMapCache* volatile _oop_map_cache; // OopMapCache for all methods in the klass (allocated lazily)
JNIid* _jni_ids; // First JNI identifier for static fields in this class
jmethodID* volatile _methods_jmethod_ids; // jmethodIDs corresponding to method_idnum, or NULL if none
nmethodBucket* volatile _dep_context; // packed DependencyContext structure
uint64_t volatile _dep_context_last_cleaned;
nmethod* _osr_nmethods_head; // Head of list of on-stack replacement nmethods for this class #if INCLUDE_JVMTI
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; #endif
#if INCLUDE_JVMTI
JvmtiCachedClassFieldMap* _jvmti_cached_class_field_map; // JVMTI: used during heap iteration #endif
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; // Interfaces (InstanceKlass*s) this class declares locally to implement.
Array<InstanceKlass*>* _local_interfaces; // Interfaces (InstanceKlass*s) this class implements transitively.
Array<InstanceKlass*>* _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;
// 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 // interface. 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. //
private: // Called to verify that k is a member of this nest - does not look at k's nest-host, // nor does it resolve any CP entries or load any classes. bool has_nest_member(JavaThread* current, InstanceKlass* k) const;
public: // Call this only if you know that the nest host has been initialized.
InstanceKlass* nest_host_not_null() {
assert(_nest_host != NULL, "must be"); return _nest_host;
} // Used to construct informative IllegalAccessError messages at a higher level, // if there was an issue resolving or validating the nest host. // Returns NULL if there was no error. constchar* nest_host_error(); // Returns nest-host class, resolving and validating it if needed. // Returns NULL if resolution is not possible from the calling context.
InstanceKlass* nest_host(TRAPS); // Check if this klass is a nestmate of k - resolves this nest-host and k's bool has_nestmate_access_to(InstanceKlass* k, TRAPS);
// Called to verify that k is a permitted subclass of this class bool has_as_permitted_subclass(const InstanceKlass* k) const;
// package
PackageEntry* package() const { return _package_entry; }
ModuleEntry* module() const; bool in_unnamed_package() const { return (_package_entry == NULL); } void set_package(ClassLoaderData* loader_data, PackageEntry* pkg_entry, TRAPS); // If the package for the InstanceKlass is in the boot loader's package entry // table then sets the classpath_index field so that // get_system_package() will know to return a non-null value for the // package's location. And, so that the package will be added to the list of // packages returned by get_system_packages(). // For packages whose classes are loaded from the boot loader class path, the // classpath_index indicates which entry on the boot loader class path. void set_classpath_index(s2 path_index); bool is_same_class_package(const Klass* class2) const; bool is_same_class_package(oop other_class_loader, const Symbol* other_class_name) const;
// find an enclosing class
InstanceKlass* compute_enclosing_class(bool* inner_is_member, TRAPS) const;
// initialization (virtuals from Klass) bool should_be_initialized() const; // means that initialize should be called void initialize(TRAPS); void link_class(TRAPS); bool link_class_or_fail(TRAPS); // returns false on failure void rewrite_class(TRAPS); void link_methods(TRAPS);
Method* class_initializer() const;
// reference type
ReferenceType reference_type() const { return (ReferenceType)_reference_type; }
// this class cp index
u2 this_class_index() const { return _this_class_index; } void set_this_class_index(u2 index) { _this_class_index = index; }
// find local field, returns true if found bool find_local_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; // find field in direct superinterfaces, returns the interface in which the field is defined
Klass* find_interface_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; // find field according to JVM spec 5.4.3.2, returns the klass in which the field is defined
Klass* find_field(Symbol* name, Symbol* sig, fieldDescriptor* fd) const; // find instance or static fields according to JVM spec 5.4.3.2, returns the klass in which the field is defined
Klass* find_field(Symbol* name, Symbol* sig, bool is_static, fieldDescriptor* fd) const;
// find a non-static or static field given its offset within the class. bool contains_field_offset(int offset);
// find a local method (returns NULL if not found)
Method* find_local_method(const Symbol* name, const Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode) const;
// find a local method from given methods array (returns NULL if not found) static Method* find_local_method(const Array<Method*>* methods, const Symbol* name, const Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode);
// find a local method index in methods or default_methods (returns -1 if not found) staticint find_method_index(const Array<Method*>* methods, const Symbol* name, const Symbol* signature,
OverpassLookupMode overpass_mode,
StaticLookupMode static_mode,
PrivateLookupMode private_mode);
// lookup a method in all the interfaces that this class implements // (returns NULL if not found)
Method* lookup_method_in_all_interfaces(Symbol* name, Symbol* signature, DefaultsLookupMode defaults_mode) const;
// lookup a method in local defaults then in all interfaces // (returns NULL if not found)
Method* lookup_method_in_ordered_interfaces(Symbol* name, Symbol* signature) const;
// Find method indices by name. If a method with the specified name is // found the index to the first method is returned, and 'end' is filled in // with the index of first non-name-matching method. If no method is found // -1 is returned. int find_method_by_name(const Symbol* name, int* end) const; staticint find_method_by_name(const Array<Method*>* methods, const Symbol* name, int* end);
// constant pool
ConstantPool* constants() const { return _constants; } void set_constants(ConstantPool* c) { _constants = c; }
// minor and major version numbers of class file
u2 minor_version() const { return _constants->minor_version(); } void set_minor_version(u2 minor_version) { _constants->set_minor_version(minor_version); }
u2 major_version() const { return _constants->major_version(); } void set_major_version(u2 major_version) { _constants->set_major_version(major_version); }
#if INCLUDE_JVMTI // Redefinition locking. Class can only be redefined by one thread at a time. // The flag is in access_flags so that it can be set and reset using atomic // operations, and not be reset by other misc_flag settings. bool is_being_redefined() const { return _access_flags.is_being_redefined();
} void set_is_being_redefined(bool value) { if (value) {
_access_flags.set_is_being_redefined();
} else {
_access_flags.clear_is_being_redefined();
}
}
// RedefineClasses() support for previous versions: void add_previous_version(InstanceKlass* ik, int emcp_method_count); void purge_previous_version_list();
// JVMTI: Support for caching a class file before it is modified by an agent that can do retransformation void set_cached_class_file(JvmtiCachedClassFileData *data) {
_cached_class_file = data;
}
JvmtiCachedClassFileData * get_cached_class_file();
jint get_cached_class_file_len(); unsignedchar * get_cached_class_file_bytes();
// JVMTI: Support for caching of field indices, types, and offsets void set_jvmti_cached_class_field_map(JvmtiCachedClassFieldMap* descriptor) {
_jvmti_cached_class_field_map = descriptor;
}
JvmtiCachedClassFieldMap* jvmti_cached_class_field_map() const { return _jvmti_cached_class_field_map;
} #else// INCLUDE_JVMTI
// for adding methods, ConstMethod::UNSET_IDNUM means no more ids available inline u2 next_method_idnum(); void set_initial_method_idnum(u2 value) { _idnum_allocated_count = value; }
// additional member function to return a handle
instanceHandle allocate_instance_handle(TRAPS);
objArrayOop allocate_objArray(int n, int length, TRAPS); // Helper function static instanceOop register_finalizer(instanceOop i, TRAPS);
// Check whether reflection/jni/jvm code is allowed to instantiate this class; // if not, throw either an Error or an Exception. virtualvoid check_valid_for_instantiation(bool throwError, TRAPS);
#ifdef ASSERT // check whether this class or one of its superclasses was redefined bool has_redefined_this_or_super() const; #endif
// Access to the implementor of an interface.
InstanceKlass* implementor() const; void set_implementor(InstanceKlass* ik); int nof_implementors() const; void add_implementor(InstanceKlass* ik); // ik is a new class that implements this interface void init_implementor(); // initialize
// link this class into the implementors list of every interface it implements void process_interfaces();
// virtual operations from Klass
GrowableArray<Klass*>* compute_secondary_supers(int num_extra_slots,
Array<InstanceKlass*>* transitive_interfaces); bool can_be_primary_super_slow() const;
size_t oop_size(oop obj) const { return size_helper(); } // slow because it's a virtual call and used for verifying the layout_helper. // Using the layout_helper bits, we can call is_instance_klass without a virtual call.
DEBUG_ONLY(bool is_instance_klass_slow() const { returntrue; })
// Iterators void do_local_static_fields(FieldClosure* cl); void do_nonstatic_fields(FieldClosure* cl); // including inherited fields void do_local_static_fields(void f(fieldDescriptor*, Handle, TRAPS), Handle, TRAPS); void print_nonstatic_fields(FieldClosure* cl); // including inherited and injected fields
// Use this to return the size of an instance in heap words: int size_helper() const { return layout_helper_to_size_helper(layout_helper());
}
// This bit is initialized in classFileParser.cpp. // It is false under any of the following conditions: // - the class is abstract (including any interface) // - the class has a finalizer (if !RegisterFinalizersAtInit) // - the class size is larger than FastAllocateSizeLimit // - the class is java/lang/Class, which cannot be allocated directly bool can_be_fastpath_allocated() const { return !layout_helper_needs_slow_path(layout_helper());
}
// Java itable
klassItable itable() const; // return klassItable wrapper
Method* method_at_itable(InstanceKlass* holder, int index, TRAPS);
Method* method_at_itable_or_null(InstanceKlass* holder, int index, bool& itable_entry_found); int vtable_index_of_interface_method(Method* method);
public: // Explicit metaspace deallocation of fields // For RedefineClasses and class file parsing errors, we need to deallocate // instanceKlasses and the metadata they point to. void deallocate_contents(ClassLoaderData* loader_data); staticvoid deallocate_methods(ClassLoaderData* loader_data,
Array<Method*>* methods); voidstatic deallocate_interfaces(ClassLoaderData* loader_data, const Klass* super_klass,
Array<InstanceKlass*>* local_interfaces,
Array<InstanceKlass*>* transitive_interfaces); voidstatic deallocate_record_components(ClassLoaderData* loader_data,
Array<RecordComponent*>* record_component);
// The constant pool is on stack if any of the methods are executing or // referenced by handles. bool on_stack() const { return _constants->on_stack(); }
// callbacks for actions during class unloading staticvoid unload_class(InstanceKlass* ik);
// Oop fields (and metadata) iterators // // The InstanceKlass iterators also visits the Object's klass.
// Forward iteration public: // Iterate over all oop fields in the oop maps. template <typename T, class OopClosureType> inlinevoid oop_oop_iterate_oop_maps(oop obj, OopClosureType* closure);
// Iterate over all oop fields and metadata. template <typename T, class OopClosureType> inlinevoid oop_oop_iterate(oop obj, OopClosureType* closure);
// Iterate over all oop fields in one oop map. template <typename T, class OopClosureType> inlinevoid oop_oop_iterate_oop_map(OopMapBlock* map, oop obj, OopClosureType* closure);
// Reverse iteration // Iterate over all oop fields and metadata. template <typename T, class OopClosureType> inlinevoid oop_oop_iterate_reverse(oop obj, OopClosureType* closure);
private: // Iterate over all oop fields in the oop maps. template <typename T, class OopClosureType> inlinevoid oop_oop_iterate_oop_maps_reverse(oop obj, OopClosureType* closure);
// Iterate over all oop fields in one oop map. template <typename T, class OopClosureType> inlinevoid oop_oop_iterate_oop_map_reverse(OopMapBlock* map, oop obj, OopClosureType* closure);
// Bounded range iteration public: // Iterate over all oop fields in the oop maps. template <typename T, class OopClosureType> inlinevoid oop_oop_iterate_oop_maps_bounded(oop obj, OopClosureType* closure, MemRegion mr);
// Iterate over all oop fields and metadata. template <typename T, class OopClosureType> inlinevoid oop_oop_iterate_bounded(oop obj, OopClosureType* closure, MemRegion mr);
private: // Iterate over all oop fields in one oop map. template <typename T, class OopClosureType> inlinevoid oop_oop_iterate_oop_map_bounded(OopMapBlock* map, oop obj, OopClosureType* closure, MemRegion mr);
public:
u2 idnum_allocated_count() const { return _idnum_allocated_count; }
private: // initialization state void set_init_state(ClassState state); void set_rewritten() { _misc_status.set_rewritten(true); } void set_init_thread(Thread *thread) {
assert(thread == nullptr || _init_thread == nullptr, "Only one thread is allowed to own initialization");
_init_thread = thread;
}
// The RedefineClasses() API can cause new method idnums to be needed // which will cause the caches to grow. Safety requires different // cache management logic if the caches can grow instead of just // going from NULL to non-NULL. bool idnum_can_increment() const { return has_been_redefined(); } inline jmethodID* methods_jmethod_ids_acquire() const; inlinevoid release_set_methods_jmethod_ids(jmethodID* jmeths);
// Lock during initialization public: // Returns the array class for the n'th dimension virtual Klass* array_klass(int n, TRAPS); virtual Klass* array_klass_or_null(int n);
// Returns the array class with this class as element type virtual Klass* array_klass(TRAPS); virtual Klass* array_klass_or_null();
// for adding methods // UNSET_IDNUM return means no more ids available inline u2 InstanceKlass::next_method_idnum() { if (_idnum_allocated_count == ConstMethod::MAX_IDNUM) { return ConstMethod::UNSET_IDNUM; // no more ids available
} else { return _idnum_allocated_count++;
}
}
class PrintClassClosure : public KlassClosure { private:
outputStream* _st; bool _verbose; public:
PrintClassClosure(outputStream* st, bool verbose);
void do_klass(Klass* k);
};
/* JNIid class for jfieldIDs only */ class JNIid: public CHeapObj<mtClass> { friendclass VMStructs; private:
Klass* _holder;
JNIid* _next; int _offset; #ifdef ASSERT bool _is_static_field_id; #endif
// An iterator that's used to access the inner classes indices in the // InstanceKlass::_inner_classes array. class InnerClassesIterator : public StackObj { private:
Array<jushort>* _inner_classes; int _length; int _idx; public:
InnerClassesIterator(const InstanceKlass* k) {
_inner_classes = k->inner_classes(); if (k->inner_classes() != NULL) {
_length = _inner_classes->length(); // The inner class array's length should be the multiple of // inner_class_next_offset if it only contains the InnerClasses // attribute data, or it should be // n*inner_class_next_offset+enclosing_method_attribute_size // if it also contains the EnclosingMethod data.
assert((_length % InstanceKlass::inner_class_next_offset == 0 ||
_length % InstanceKlass::inner_class_next_offset == InstanceKlass::enclosing_method_attribute_size), "just checking"); // Remove the enclosing_method portion if exists. if (_length % InstanceKlass::inner_class_next_offset == InstanceKlass::enclosing_method_attribute_size) {
_length -= InstanceKlass::enclosing_method_attribute_size;
}
} else {
_length = 0;
}
_idx = 0;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.