namespace hiddenapi { class AccessContext;
} // namespace hiddenapi
namespace linker { class ImageWriter;
} // namespace linker
template<typename T> class ArraySlice; class ArtField; class ArtMethod; struct ClassOffsets; class DexFile; template<class T> class Handle; class ImTable; enum InvokeType : uint32_t; template <typename Iter> class IterationRange; template<typename T> class LengthPrefixedArray; enumclass PointerSize : uint32_t; class Signature; template<typename T> class StrideIterator; template<size_t kNumReferences> class PACKED(4) StackHandleScope; class Thread; class DexCacheVisitor; class RuntimeImageHelper;
namespace mirror {
class ClassExt; class ClassLoader; class Constructor; class DexCache; class Field; class IfTable; class Method; template <typename T> struct alignas(8) DexCachePair;
// C++ mirror of java.lang.Class class EXPORT MANAGED Class final : public Object { // Most member functions are not declared const, even if they logically are const, since they // require Java object accesses, and read barriers may modify the object. public:
MIRROR_CLASS("Ljava/lang/Class;");
// 'reference_instance_offsets_' may contain up to 31 reference offsets. If // more bits are required, then we set the most-significant bit and store the // number of 32-bit bitmap entries required in the remaining bits. All the // required bitmap entries are stored after static fields (at the end of the class). static constexpr uint32_t kVisitReferencesSlowpathShift = 31; static constexpr uint32_t kVisitReferencesSlowpathMask = 1u << kVisitReferencesSlowpathShift;
// Shift primitive type by kPrimitiveTypeSizeShiftShift to get the component type size shift // Used for computing array size as follows: // array_bytes = header_size + (elements << (primitive_type >> kPrimitiveTypeSizeShiftShift)) static constexpr uint32_t kPrimitiveTypeSizeShiftShift = 16; static constexpr uint32_t kPrimitiveTypeMask = (1u << kPrimitiveTypeSizeShiftShift) - 1;
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, bool kWithSynchronizationBarrier = true>
ClassStatus GetStatus() REQUIRES_SHARED(Locks::mutator_lock_) { // Reading the field without barrier is used exclusively for IsVisiblyInitialized().
int32_t field_value = kWithSynchronizationBarrier
? GetField32Volatile<kVerifyFlags>(StatusOffset())
: GetField32<kVerifyFlags>(StatusOffset()); // Avoid including "subtype_check_bits_and_status.h" to get the field. // The ClassStatus is always in the 4 most-significant bits of status_. return enum_cast<ClassStatus>(static_cast<uint32_t>(field_value) >> (32 - 4));
}
// This is static because 'this' may be moved by GC. staticvoid SetStatus(Handle<Class> h_this, ClassStatus new_status, Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// Used for structural redefinition to directly set the class-status while // holding a strong mutator-lock. void SetStatusLocked(ClassStatus new_status) REQUIRES(Locks::mutator_lock_);
// Returns true if the class has been retired. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsRetired() REQUIRES_SHARED(Locks::mutator_lock_) { return GetStatus<kVerifyFlags>() == ClassStatus::kRetired;
}
// Returns true if the class has failed to link. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsErroneousUnresolved() REQUIRES_SHARED(Locks::mutator_lock_) { return GetStatus<kVerifyFlags>() == ClassStatus::kErrorUnresolved;
}
// Returns true if the class has failed to initialize. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsErroneousResolved() REQUIRES_SHARED(Locks::mutator_lock_) { return GetStatus<kVerifyFlags>() == ClassStatus::kErrorResolved;
}
// Returns true if the class status indicets that the class has failed to link or initialize. staticbool IsErroneous(ClassStatus status) { return status == ClassStatus::kErrorUnresolved || status == ClassStatus::kErrorResolved;
}
// Returns true if the class has failed to link or initialize. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsErroneous() REQUIRES_SHARED(Locks::mutator_lock_) { return IsErroneous(GetStatus<kVerifyFlags>());
}
// Returns true if the class has been loaded. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsIdxLoaded() REQUIRES_SHARED(Locks::mutator_lock_) { return GetStatus<kVerifyFlags>() >= ClassStatus::kIdx;
}
// Returns true if the class has been loaded. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsLoaded() REQUIRES_SHARED(Locks::mutator_lock_) { return GetStatus<kVerifyFlags>() >= ClassStatus::kLoaded;
}
// Returns true if the class has been linked. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsResolved() REQUIRES_SHARED(Locks::mutator_lock_) {
ClassStatus status = GetStatus<kVerifyFlags>(); return status >= ClassStatus::kResolved || status == ClassStatus::kErrorResolved;
}
// Returns true if the class should be verified at runtime. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool ShouldVerifyAtRuntime() REQUIRES_SHARED(Locks::mutator_lock_) { return GetStatus<kVerifyFlags>() == ClassStatus::kRetryVerificationAtRuntime;
}
// Returns true if the class has been verified at compile time, but should be // executed with access checks. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsVerifiedNeedsAccessChecks() REQUIRES_SHARED(Locks::mutator_lock_) { return GetStatus<kVerifyFlags>() == ClassStatus::kVerifiedNeedsAccessChecks;
}
// Returns true if the class has been verified. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsVerified() REQUIRES_SHARED(Locks::mutator_lock_) { return GetStatus<kVerifyFlags>() >= ClassStatus::kVerified;
}
// Returns true if the class is initializing. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsInitializing() REQUIRES_SHARED(Locks::mutator_lock_) { return GetStatus<kVerifyFlags>() >= ClassStatus::kInitializing;
}
// Returns true if the class is initialized. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsInitialized() REQUIRES_SHARED(Locks::mutator_lock_) { return GetStatus<kVerifyFlags>() >= ClassStatus::kInitialized;
}
// Returns true if the class is visibly initialized. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsVisiblyInitialized() REQUIRES_SHARED(Locks::mutator_lock_) { // Note: Avoiding the synchronization barrier for the visibly initialized check.
ClassStatus status = GetStatus<kVerifyFlags, /*kWithSynchronizationBarrier=*/ false>();
// We need to prevent the compiler from reordering loads that depend // on the class being visibly initialized before the status load above. asmvolatile ("" : : : "memory");
return status == ClassStatus::kVisiblyInitialized;
}
// Returns true if this class is ever accessed through a C++ mirror. bool IsMirrored() REQUIRES_SHARED(Locks::mutator_lock_);
// Adds new_flags and clears clear_flags from the existing set of class_flags void AddRemoveClassFlags(uint32_t new_flags, uint32_t clear_flags = 0)
REQUIRES_SHARED(Locks::mutator_lock_);
// Set access flags during linking, these cannot be rolled back by a Transaction. void SetAccessFlagsDuringLinking(uint32_t new_access_flags) REQUIRES_SHARED(Locks::mutator_lock_);
// Set access flags, recording the change if running inside a Transaction. void SetAccessFlags(uint32_t new_access_flags) REQUIRES_SHARED(Locks::mutator_lock_);
// Returns true if the class is an enum.
ALWAYS_INLINE bool IsEnum() REQUIRES_SHARED(Locks::mutator_lock_) { return (GetAccessFlags() & kAccEnum) != 0;
}
// Returns true if the class is an interface. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE bool IsInterface() REQUIRES_SHARED(Locks::mutator_lock_) { return (GetAccessFlags<kVerifyFlags>() & kAccInterface) != 0;
}
// Returns true if the class is declared public.
ALWAYS_INLINE bool IsPublic() REQUIRES_SHARED(Locks::mutator_lock_) { return (GetAccessFlags() & kAccPublic) != 0;
}
// Returns true if the class is declared final.
ALWAYS_INLINE bool IsFinal() REQUIRES_SHARED(Locks::mutator_lock_) { return (GetAccessFlags() & kAccFinal) != 0;
}
// Returns true if the class is abstract. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
ALWAYS_INLINE bool IsAbstract() REQUIRES_SHARED(Locks::mutator_lock_) { return (GetAccessFlags<kVerifyFlags>() & kAccAbstract) != 0;
}
// Returns true if the class is an annotation.
ALWAYS_INLINE bool IsAnnotation() REQUIRES_SHARED(Locks::mutator_lock_) { return (GetAccessFlags() & kAccAnnotation) != 0;
}
// Returns true if the class is synthetic.
ALWAYS_INLINE bool IsSynthetic() REQUIRES_SHARED(Locks::mutator_lock_) { return (GetAccessFlags() & kAccSynthetic) != 0;
}
// Can references of this type be assigned to by things of another type? For non-array types // this is a matter of whether sub-classes may exist - which they can't if the type is final. // For array classes, where all the classes are final due to there being no sub-classes, an // Object[] may be assigned to by a String[] but a String[] may not be assigned to by other // types as the component is final. bool CannotBeAssignedFromOtherTypes() REQUIRES_SHARED(Locks::mutator_lock_);
// Returns true if this class is the placeholder and should retire and // be replaced with a class with the right size for embedded imt/vtable. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsTemp() REQUIRES_SHARED(Locks::mutator_lock_) {
ClassStatus s = GetStatus<kVerifyFlags>(); return s < ClassStatus::kResolving &&
s != ClassStatus::kErrorResolved &&
ShouldHaveEmbeddedVTable<kVerifyFlags>();
}
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
ObjPtr<String> GetName() REQUIRES_SHARED(Locks::mutator_lock_); // Returns the cached name. void SetName(ObjPtr<String> name) REQUIRES_SHARED(Locks::mutator_lock_); // Sets the cached name. // Computes the name, then sets the cached value. static ObjPtr<String> ComputeName(Handle<Class> h_this) REQUIRES_SHARED(Locks::mutator_lock_)
REQUIRES(!Roles::uninterruptible_);
template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsProxyClass() REQUIRES_SHARED(Locks::mutator_lock_) { // Read access flags without using getter as whether something is a proxy can be check in // any loaded state // TODO: switch to a check if the super class is java.lang.reflect.Proxy?
uint32_t access_flags = GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, access_flags_)); return (access_flags & kAccClassIsProxy) != 0;
}
// Returns true if the class is a primitive type. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags> bool IsPrimitive() REQUIRES_SHARED(Locks::mutator_lock_) { return GetPrimitiveType<kVerifyFlags>() != Primitive::kPrimNot;
}
// Enum used to control whether we try to add a finalizer-reference for object alloc or not. enumclass AddFinalizer { // Don't create a finalizer reference regardless of what the class-flags say.
kNoAddFinalizer, // Use the class-flags to figure out if we should make a finalizer reference.
kUseClassTag,
};
// Creates a raw object instance but does not invoke the default constructor. // kCheckAddFinalizer controls whether we use a DCHECK to check that we create a // finalizer-reference if needed. This should only be disabled when doing structural class // redefinition. template <bool kIsInstrumented = true,
AddFinalizer kAddFinalizer = AddFinalizer::kUseClassTag, bool kCheckAddFinalizer = true>
ALWAYS_INLINE ObjPtr<Object> Alloc(Thread* self, gc::AllocatorType allocator_type)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// Adjust class-size during linking in case an overflow bitmap for reference // offsets is required. static size_t AdjustClassSizeForReferenceOffsetBitmapDuringLinking(ObjPtr<Class> klass,
size_t class_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Compute how many bytes would be used a class with the given elements. static uint32_t ComputeClassSize(bool has_embedded_vtable,
uint32_t num_vtable_entries,
uint32_t num_8bit_static_fields,
uint32_t num_16bit_static_fields,
uint32_t num_32bit_static_fields,
uint32_t num_64bit_static_fields,
uint32_t num_ref_static_fields,
uint32_t num_ref_bitmap_entries,
PointerSize pointer_size);
// The size of java.lang.Class.class. static uint32_t ClassClassSize(PointerSize pointer_size) { // The number of vtable entries in java.lang.Class.
uint32_t vtable_entries = Object::kVTableLength + 85; return ComputeClassSize(true, vtable_entries, 0, 0, 4, 1, 0, 0, pointer_size);
}
// The size of a java.lang.Class representing a primitive such as int.class. static uint32_t PrimitiveClassSize(PointerSize pointer_size) { return ComputeClassSize(false, 0, 0, 0, 0, 0, 0, 0, pointer_size);
}
void SetObjectSizeWithoutChecks(uint32_t new_object_size)
REQUIRES_SHARED(Locks::mutator_lock_) { // Not called within a transaction. return SetField32<false, false, kVerifyNone>(
OFFSET_OF_OBJECT_MEMBER(Class, object_size_), new_object_size);
}
// Returns true if this class is in the same packages as that class. bool IsInSamePackage(ObjPtr<Class> that) REQUIRES_SHARED(Locks::mutator_lock_);
// Returns true if a class member should be discoverable with reflection given // the criteria. Some reflection calls only return public members // (public_only == true), some members should be hidden from non-boot class path // callers (hiddenapi_context). template<typename T>
ALWAYS_INLINE staticbool IsDiscoverable(bool public_only, const hiddenapi::AccessContext& access_context,
T* member)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns true if this class can access that class. bool CanAccess(ObjPtr<Class> that) REQUIRES_SHARED(Locks::mutator_lock_);
// Can this class access a member in the provided class with the provided member access flags? // Note that access to the class isn't checked in case the declaring class is protected and the // method has been exposed by a public sub-class bool CanAccessMember(ObjPtr<Class> access_to, uint32_t member_flags)
REQUIRES_SHARED(Locks::mutator_lock_);
// Can this class access a resolved field? // Note that access to field's class is checked and this may require looking up the class // referenced by the FieldId in the DexFile in case the declaring class is inaccessible. bool CanAccessResolvedField(ObjPtr<Class> access_to,
ArtField* field,
ObjPtr<DexCache> dex_cache,
uint32_t field_idx)
REQUIRES_SHARED(Locks::mutator_lock_); bool CheckResolvedFieldAccess(ObjPtr<Class> access_to,
ArtField* field,
ObjPtr<DexCache> dex_cache,
uint32_t field_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
// Can src be assigned to this class? For example, String can be assigned to Object (by an // upcast), however, an Object cannot be assigned to a String as a potentially exception throwing // downcast would be necessary. Similarly for interfaces, a class that implements (or an interface // that extends) another can be assigned to its parent, but not vice-versa. All Classes may assign // to themselves. Classes for primitive types may not assign to each other.
ALWAYS_INLINE bool IsAssignableFrom(ObjPtr<Class> src) REQUIRES_SHARED(Locks::mutator_lock_);
// Check if this class implements a given interface. bool Implements(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
// Checks if 'klass' is a redefined version of this. bool IsObsoleteVersionOf(ObjPtr<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
// Get first common super class. It will never return null. // `This` and `klass` must be classes.
ObjPtr<Class> GetCommonSuperClass(Handle<Class> klass) REQUIRES_SHARED(Locks::mutator_lock_);
// Also updates the dex_cache_strings_ variable from new_dex_cache. void SetDexCache(ObjPtr<DexCache> new_dex_cache) REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the number of non-inherited virtual methods (sum of declared and copied methods).
ALWAYS_INLINE uint32_t NumVirtualMethods() REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the number of copied virtual methods.
ALWAYS_INLINE uint32_t NumCopiedVirtualMethods() REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the number of declared virtual methods.
ALWAYS_INLINE uint32_t NumDeclaredVirtualMethods() REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the number of declared methods.
ALWAYS_INLINE uint32_t NumDeclaredMethods() REQUIRES_SHARED(Locks::mutator_lock_);
template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier> void VerifyOverflowReferenceBitmap() REQUIRES_SHARED(Locks::mutator_lock_); // If the bitmap in `reference_instance_offsets_` was found to be insufficient // in CreateReferenceInstanceOffsets(), then populate the overflow bitmap, // which is at the end of class object. void PopulateReferenceOffsetBitmap() REQUIRES_SHARED(Locks::mutator_lock_);
// Given a method implemented by this class but potentially from a super class, return the // specific implementation method for this class.
ArtMethod* FindVirtualMethodForVirtual(ArtMethod* method, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Given a method implemented by this class' super class, return the specific implementation // method for this class.
ArtMethod* FindVirtualMethodForSuper(ArtMethod* method, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Given a method from some implementor of this interface, return the specific implementation // method for this class.
ArtMethod* FindVirtualMethodForInterfaceSuper(ArtMethod* method, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Given a method implemented by this class, but potentially from a // super class or interface, return the specific implementation // method for this class.
ArtMethod* FindVirtualMethodForInterface(ArtMethod* method, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_) ALWAYS_INLINE;
// Find a method with the given name and signature in an interface class. // // Search for the method declared in the class, then search for a method declared in any // superinterface, then search the superclass java.lang.Object (implicitly declared methods // in an interface without superinterfaces, see JLS 9.2, can be inherited, see JLS 9.4.1). // TODO: Implement search for a unique maximally-specific non-abstract superinterface method.
// Return the first public SDK method from the list of interfaces implemented by // this class.
ArtMethod* FindAccessibleInterfaceMethod(ArtMethod* implementation_method,
PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Find a method with the given name and signature in a non-interface class. // // Search for the method in the class, following the JLS rules which conflict with the RI // in some cases. The JLS says that inherited methods are searched (JLS 15.12.2.1) and // these can come from a superclass or a superinterface (JLS 8.4.8). We perform the // following search: // 1. Search the methods declared directly in the class. If we find a method with the // given name and signature, return that method. // 2. Search the methods declared in superclasses until we find a method with the given // signature or complete the search in java.lang.Object. If we find a method with the // given name and signature, check if it's been inherited by the class where we're // performing the lookup (qualifying type). If it's inherited, return it. Otherwise, // just remember the method and its declaring class and proceed to step 3. // 3. Search "copied" methods (containing methods inherited from interfaces) in the class // and its superclass chain. If we found a method in step 2 (which was not inherited, // otherwise we would not be performing step 3), end the search when we reach its // declaring class, otherwise search the entire superclass chain. If we find a method // with the given name and signature, return that method. // 4. Return the method found in step 2 if any (not inherited), or null. // // It's the responsibility of the caller to throw exceptions if the returned method (or null) // does not satisfy the request. Special consideration should be given to the case where this // function returns a method that's not inherited (found in step 2, returned in step 4).
// Get fields of the class.
LengthPrefixedArray<ArtField>* GetFieldsPtr() REQUIRES_SHARED(Locks::mutator_lock_);
LengthPrefixedArray<ArtField>* GetFieldsPtrUnchecked() REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the number of instance fields containing reference types. Does not count fields in any // super classes. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
uint32_t NumReferenceInstanceFields() REQUIRES_SHARED(Locks::mutator_lock_) {
DCHECK(IsResolved<kVerifyFlags>()); return GetField32<kVerifyFlags>(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_));
}
void SetNumReferenceInstanceFields(uint32_t new_num) REQUIRES_SHARED(Locks::mutator_lock_) { // Not called within a transaction.
SetField32<false>(OFFSET_OF_OBJECT_MEMBER(Class, num_reference_instance_fields_), new_num);
}
// Get the offset of the first reference instance field. Other reference instance fields follow. template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags,
ReadBarrierOption kReadBarrierOption = kWithReadBarrier>
MemberOffset GetFirstReferenceInstanceFieldOffset()
REQUIRES_SHARED(Locks::mutator_lock_);
void SetNumReferenceStaticFields(uint32_t new_num) REQUIRES_SHARED(Locks::mutator_lock_) { // Not called within a transaction.
SetField32<false>(NumReferenceStaticFieldsOffset(), new_num);
}
// Get the offset of the first reference static field. Other reference static fields follow. template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
MemberOffset GetFirstReferenceStaticFieldOffset(PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Get the offset of the first reference static field. Other reference static fields follow.
MemberOffset GetFirstReferenceStaticFieldOffsetDuringLinking(PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Find a static or instance field using the JLS resolution order
ArtField* FindField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
// Finds the given instance field in this class or a superclass.
ArtField* FindInstanceField(std::string_view name, std::string_view type)
REQUIRES_SHARED(Locks::mutator_lock_);
// Finds the given instance field in this class or a superclass, only searches classes that // have the same dex cache.
ArtField* FindInstanceField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
// Finds the given static field in this class or a superclass.
ArtField* FindStaticField(std::string_view name, std::string_view type)
REQUIRES_SHARED(Locks::mutator_lock_);
// Finds the given static field in this class or superclass, only searches classes that // have the same dex cache.
ArtField* FindStaticField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns the ExtData for this class, allocating one if necessary. This should be the only way // to force ext_data_ to be set. No functions are available for changing an already set ext_data_ // since doing so is not allowed. static ObjPtr<ClassExt> EnsureExtDataPresent(Handle<Class> h_this, Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// Visit native roots visits roots which are keyed off the native pointers such as ArtFields and // ArtMethods. template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier, bool kVisitProxyMethod = true, class Visitor> void VisitNativeRoots(Visitor& visitor, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier, class Visitor> void VisitObsoleteClass(Visitor& visitor) REQUIRES_SHARED(Locks::mutator_lock_);
// Visit ArtMethods directly owned by this class. template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier, class Visitor> void VisitMethods(Visitor visitor, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Visit ArtFields directly owned by this class. template<ReadBarrierOption kReadBarrierOption = kWithReadBarrier, class Visitor> void VisitFields(Visitor visitor) REQUIRES_SHARED(Locks::mutator_lock_);
// Get one of the primitive classes. static ObjPtr<mirror::Class> GetPrimitiveClass(ObjPtr<mirror::String> name)
REQUIRES_SHARED(Locks::mutator_lock_);
// Clear the kAccMustCountLocks flag on each method, for class redefinition. void ClearMustCountLocksFlagOnAllMethods(PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_); // Clear the kAccCompileDontBother flag on each method, for class redefinition. void ClearDontCompileFlagOnAllMethods(PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Clear the kAccSkipAccessChecks flag on each method, for class redefinition. void ClearSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_); // When class is verified, set the kAccSkipAccessChecks flag on each method. void SetSkipAccessChecksFlagOnAllMethods(PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Get the descriptor of the class as `std::string_view`. The class must be directly // backed by a `DexFile` - it must not be primitive, array or proxy class.
std::string_view GetDescriptorView() REQUIRES_SHARED(Locks::mutator_lock_);
// Get the descriptor of a primitive class as `std::string_view`.
std::string_view GetPrimitiveDescriptorView() REQUIRES_SHARED(Locks::mutator_lock_);
// Get the descriptor of the class. In a few cases a std::string is required, rather than // always create one the storage argument is populated and its internal c_str() returned. We do // this to avoid memory allocation in the common case. constchar* GetDescriptor(std::string* storage) REQUIRES_SHARED(Locks::mutator_lock_);
// Look up cached descriptor hash, or recompute if that hasn't yet been initialized. // May update the cache, but that is not guaranteed.
uint32_t DescriptorHash() REQUIRES_SHARED(Locks::mutator_lock_);
// Should be called by initializing thread once other initialization is completed, since it may // reuse initialization state. Unconditionally clears the initializing thread id. void CacheDescriptorHash(uint32_t hash) REQUIRES_SHARED(Locks::mutator_lock_);
// Same as above, but computes the hash itself. void CacheDescriptorHash() REQUIRES_SHARED(Locks::mutator_lock_);
// Get the direct interface at index `idx` if resolved, otherwise return null. // If the caller expects the interface to be resolved, for example for a resolved `klass`, // that assumption should be checked by `DCHECK(result != nullptr)`.
ObjPtr<Class> GetDirectInterface(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_);
// Resolve and get the direct interface of the `klass` at index `idx`. // Returns null with a pending exception if the resolution fails. static ObjPtr<Class> ResolveDirectInterface(Thread* self, Handle<Class> klass, uint32_t idx)
REQUIRES_SHARED(Locks::mutator_lock_);
// Asserts we are initialized or initializing in the given thread. void AssertInitializedOrInitializingInThread(Thread* self)
REQUIRES_SHARED(Locks::mutator_lock_);
// For proxy class only.
ObjPtr<ObjectArray<Class>> GetProxyInterfaces() REQUIRES_SHARED(Locks::mutator_lock_);
// For proxy class only.
ObjPtr<ObjectArray<ObjectArray<Class>>> GetProxyThrows() REQUIRES_SHARED(Locks::mutator_lock_);
// May cause thread suspension due to EqualParameters.
ArtMethod* GetDeclaredConstructor(Thread* self,
Handle<ObjectArray<Class>> args,
PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Used to initialize a class in the allocation code path to ensure it is guarded by a StoreStore // fence. class InitializeClassVisitor { public: explicit InitializeClassVisitor(uint32_t class_size) : class_size_(class_size) {
}
// Returns true if the class loader is null, ie the class loader is the boot strap class loader. bool IsBootStrapClassLoaded() REQUIRES_SHARED(Locks::mutator_lock_);
static std::string PrettyDescriptor(ObjPtr<mirror::Class> klass)
REQUIRES_SHARED(Locks::mutator_lock_);
std::string PrettyDescriptor()
REQUIRES_SHARED(Locks::mutator_lock_); // Returns a human-readable form of the name of the given class. // Given String.class, the output would be "java.lang.Class<java.lang.String>". static std::string PrettyClass(ObjPtr<mirror::Class> c)
REQUIRES_SHARED(Locks::mutator_lock_);
std::string PrettyClass()
REQUIRES_SHARED(Locks::mutator_lock_); // Returns a human-readable form of the name of the given class with its class loader. static std::string PrettyClassAndClassLoader(ObjPtr<mirror::Class> c)
REQUIRES_SHARED(Locks::mutator_lock_);
std::string PrettyClassAndClassLoader()
REQUIRES_SHARED(Locks::mutator_lock_);
// Fix up all of the native pointers in the class by running them through the visitor. Only sets // the corresponding entry in dest if visitor(obj) != obj to prevent dirty memory. Dest should be // initialized to a copy of *this to prevent issues. Does not visit the ArtMethod and ArtField // roots. template <VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags, typename Visitor> void FixupNativePointers(Class* dest, PointerSize pointer_size, const Visitor& visitor)
REQUIRES_SHARED(Locks::mutator_lock_);
// Get or create the various jni id arrays in a lock-less thread safe manner. staticbool EnsureMethodIds(Handle<Class> h_this)
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<Object> GetMethodIds() REQUIRES_SHARED(Locks::mutator_lock_); staticbool EnsureStaticFieldIds(Handle<Class> h_this)
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<Object> GetStaticFieldIds() REQUIRES_SHARED(Locks::mutator_lock_); staticbool EnsureInstanceFieldIds(Handle<Class> h_this)
REQUIRES_SHARED(Locks::mutator_lock_);
ObjPtr<Object> GetInstanceFieldIds() REQUIRES_SHARED(Locks::mutator_lock_);
// Calculate the index in the fields_ or methods_ arrays a method is located at. This // is to be used with the above Get{,OrCreate}...Ids functions.
size_t GetStaticFieldIdOffset(ArtField* field)
REQUIRES_SHARED(Locks::mutator_lock_);
size_t GetInstanceFieldIdOffset(ArtField* field)
REQUIRES_SHARED(Locks::mutator_lock_);
size_t GetMethodIdOffset(ArtMethod* method, PointerSize pointer_size)
REQUIRES_SHARED(Locks::mutator_lock_);
// Returns whether the class should be visible to an app. // Notorious example is java.lang.ClassValue, which was added in Android U and proguarding tools // used that as justification to remove computeValue method implementation. Such an app running // on U+ will fail with AbstractMethodError as computeValue is not implemented. // See b/259501764. bool CheckIsVisibleWithTargetSdk(Thread* self) REQUIRES_SHARED(Locks::mutator_lock_);
// Ensure the class does not store the thread id of the initializing thread, so that its // contents are deterministic, and we can safely write it out. // Used e.g. to ensure determinism when writing an image. `class_for_descr` is used only to // compute the class descriptor, since `this` may not be in the Java heap, and // ComputeClassDescriptor() assumes that. void FixThreadId(Class* class_for_descr) REQUIRES_SHARED(Locks::mutator_lock_);
// Helper to set the status without any validity cheks. void SetStatusInternal(ClassStatus new_status)
REQUIRES_SHARED(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
// Compute the descriptor hash without relying on the cached value.
uint32_t ComputeDescriptorHash() REQUIRES_SHARED(Locks::mutator_lock_);
// 'Class' Object Fields // Order governed by java field ordering. See art::ClassLinker::LinkFieldsHelper::LinkFields.
// Defining class loader, or null for the "bootstrap" system loader.
HeapReference<ClassLoader> class_loader_;
// For array classes, the component class object for instanceof/checkcast // (for String[][][], this will be String[][]). null for non-array classes.
HeapReference<Class> component_type_;
// DexCache of resolved constant pool entries (will be null for classes generated by the // runtime such as arrays and primitive classes).
HeapReference<DexCache> dex_cache_;
// Extraneous class data that is not always needed. This field is allocated lazily and may // only be set with 'this' locked. This is synchronized on 'this'. // TODO(allight) We should probably synchronize it on something external or handle allocation in // some other (safe) way to prevent possible deadlocks.
HeapReference<ClassExt> ext_data_;
// The interface table (iftable_) contains pairs of a interface class and an array of the // interface methods. There is one pair per interface supported by this class. That means one // pair for each interface we support directly, indirectly via superclass, or indirectly via a // superinterface. This will be null if neither we nor our superclass implement any interfaces. // // Why we need this: given "class Foo implements Face", declare "Face faceObj = new Foo()". // Invoke faceObj.blah(), where "blah" is part of the Face interface. We can't easily use a // single vtable. // // For every interface a concrete class implements, we create an array of the concrete vtable_ // methods for the methods in the interface.
HeapReference<IfTable> iftable_;
// Descriptor for the class such as "java.lang.Class" or "[C". Lazily initialized by ComputeName
HeapReference<String> name_;
// The superclass, or null if this is java.lang.Object or a primitive type. // // Note that interfaces have java.lang.Object as their // superclass. This doesn't match the expectations in JNI // GetSuperClass or java.lang.Class.getSuperClass() which need to // check for interfaces and return null.
HeapReference<Class> super_class_;
// Virtual method table (vtable), for use by "invoke-virtual". The vtable from the superclass is // copied in, and virtual methods from our class either replace those from the super or are // appended. For abstract classes, methods may be created in the vtable that aren't in // virtual_ methods_ for miranda methods.
HeapReference<PointerArray> vtable_;
// instance and static fields // // These describe the layout of the contents of an Object. // Note that only the fields directly declared by this class are // listed in `fields_`; fields declared by a superclass are listed in // the superclass's `Class.fields_`. // // ArtFields are allocated as a length prefixed ArtField array, and not an array of pointers to // ArtFields.
uint64_t fields_;
// Pointer to an ArtMethod length-prefixed array. All the methods where this class is the place // where they are logically defined. This includes all private, static, final and virtual methods // as well as inherited default methods and miranda methods. // // The slice methods_ [0, virtual_methods_offset_) are the direct (static, private, init) methods // declared by this class. // // The slice methods_ [virtual_methods_offset_, copied_methods_offset_) are the virtual methods // declared by this class. // // The slice methods_ [copied_methods_offset_, |methods_|) are the methods that are copied from // interfaces such as miranda or default methods. These are copied for resolution purposes as this // class is where they are (logically) declared as far as the virtual dispatch is concerned. // // Note that this field is used by the native debugger as the unique identifier for the type.
uint64_t methods_;
// Access flags; low 16 bits are defined by VM spec.
uint32_t access_flags_;
// Class flags to help speed up visiting object references. See class_flags.h // for various possible flags.
uint32_t class_flags_;
// Total size of the Class instance; used when allocating storage on gc heap. // See also object_size_.
uint32_t class_size_;
// The number of high bits in a tid that are guaranteed to be zero. This should be at most // 32 - ceil(log2(PID_MAX_LIMIT)), where PID_MAX_LIMIT is defined as in the kernel's thread.h. // This is a slightly dubious assumption, already made by some other packages. // We're careful about CHECK()ing this. static constexpr uint32_t kTidExtraBits = 10; static constexpr uint32_t kTidUnusedBitsMask = ~((1 << (32 - kTidExtraBits)) - 1);
// Tid used to check for recursive <clinit> invocation during initialization, and briefly for // circular class hierarchy check in DefineClass. When not used to store the tid, it may be // used to contain the bitwise complement of the class descriptor hash, provided the high // kTidExtraBits of the hash are not all one. Thus the high bits can be used to distinguish the // two cases. We store the complement of the hash code, instead of the hash code itself, since // Java String's hashCode(), which is replicated here, has high zero bits for very short // strings. The thread id is typically accessed while holding the monitor on the class. The // hash code is accessed without synchronization.
std::atomic<uint32_t> clinit_thread_id_or_hash_;
static_assert(sizeof(pid_t) == sizeof(int32_t), "java.lang.Class.clinitThreadId size check");
// ClassDef index in dex file, -1 if no class definition such as an array. // TODO: really 16bits
int32_t dex_class_def_idx_;
// Type index in dex file. // TODO: really 16bits
int32_t dex_type_idx_;
// Number of instance fields that are object refs. Does not count object refs // in any super classes.
uint32_t num_reference_instance_fields_;
// Number of static fields that are object refs,
uint32_t num_reference_static_fields_;
// Total object size; used when allocating storage on gc heap. // (For interfaces and abstract classes this will be zero.) // See also class_size_.
uint32_t object_size_;
// Aligned object size for allocation fast path. The value is max uint32_t if the object is // uninitialized or finalizable. Not currently used for variable sized objects.
uint32_t object_size_alloc_fast_path_;
// The lower 16 bits contains a Primitive::Type value. The upper 16 // bits contains the size shift of the primitive type.
uint32_t primitive_type_;
// Bitmap of offsets of instance fields.
uint32_t reference_instance_offsets_;
// See the real definition in subtype_check_bits_and_status.h // typeof(status_) is actually SubtypeCheckBitsAndStatus.
uint32_t status_;
// The following data exist in real class objects. // Embedded Vtable length, for class object that's instantiable, fixed size. // uint32_t vtable_length_; // Embedded Imtable pointer, for class object that's not an interface, fixed size. // ImTableEntry embedded_imtable_; // Embedded Vtable, for class object that's not an interface, variable size. // VTableEntry embedded_vtable_[0]; // Static fields, variable size. // uint32_t fields_[0]; // Embedded bitmap of offsets of instance fields, for classes that need more than 31 // reference-offset bits. 'reference_instance_offsets_' stores the number of // 32-bit entries that hold the entire bitmap. We compute the offset of first // entry by subtracting this number from class_size_. // uint32_t reference_bitmap_[0];
ART_FRIEND_TEST(DexCacheTest, TestResolvedFieldAccess); // For ResolvedFieldAccessTest friendstruct art::ClassOffsets; // for verifying offset information friendclass Object; // For VisitReferences friendclass linker::ImageWriter; // For SetStatusInternal friendclass art::RuntimeImageHelper; // For SetStatusInternal
DISALLOW_IMPLICIT_CONSTRUCTORS(Class);
};
} // namespace mirror
} // namespace art
#endif// ART_RUNTIME_MIRROR_CLASS_H_
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.21 Sekunden
(vorverarbeitet am 2026-06-29)
¤
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.