- In previous articles, we explored the nature of objects:
- Alloc flow analysis of OC object principle
- OC objects have internal alignment
- The nature of objects in the OC object principle
- After understanding the nature of objects, do you have questions like:
- What is the nature of a class?
- What is the structure of a class?
- Where are the properties and methods we use stored?
- With these questions in mind, let’s explore the nature of the next class.
The structure of the class
- Let’s start with the underlying implementation of the following code:
@interface LGPerson : NSObject
@property (nonatomic) NSString *name;
@end
@implementation LGPerson
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
LGPerson *p = [LGPerson alloc];
NSLog(@"p:%@", p);
}
return 0;
}
Copy the code
- use
clang
Compile:clang -rewrite-objc main.m -o main.cpp
// ...
struct objc_class;
typedef struct objc_class *Class;
// ...
struct NSObject_IMPL {
Class isa;
};
// ...
typedef struct objc_object LGPerson;
struct LGPerson_IMPL {
struct NSObject_IMPL NSObject_IVARS;
NSString *_name;
};
// ...
Copy the code
- As you can see from the compiled results :(code irrelevant to this analysis has been omitted)
LGPerson
Classes are actuallystruct objc_object
typeLGPerson
The concrete implementation ofLGPerson_IMPL
The first member isNSObject_IMPL
In theisa
isa
Is of typeClass
.Class
Is of typestruct objc_class
objc_class
It’s just a declaration, not a definition, so we can look at itobjc
Is there a definition in the source code
objc
The source codeobjc_class
Definition:
struct objc_class : objc_object {
/ /...
// Class ISA;
Class superclass;
cache_t cache; // formerly cache pointer and vtable
class_data_bits_t bits; // class_rw_t * plus custom rr/alloc flags
// ...
}
struct objc_object {
isa_t isa;
}
Copy the code
- from
objc
You can see the source code,objc_class
Inherited fromobjc_object
, the first member variable isisa
- In the previous article we examined the object’s
isa
Point to a class, so what does a class’s ISA point to?
Class of isa
- Take a look at the isa reference of the class using the following code
@interface LGPerson : NSObject
@end
@implementation LGPerson
@end
int main(int argc, const char * argv[]) {
@autoreleasepool {
LGPerson *p = [LGPerson alloc];
}
return 0;
}
Copy the code
LLDB
printisa
Information:x/4gx
: Prints data stored in memoryp/x
: Output in hexadecimal format0x00007ffffffffff8
Is:ISA_MASK
The value of the&
The purpose of this value is to fetchNONPOINTER_ISA
In theisa
value
- As you can see from the print above
- Instance variable of
isa
Pointing to the classLGPerson
LGPerson
Of the classisa
Point to anotherLGPerson
Class (these twoLGPerson
Classes are not the same because they have different addresses, actually the secondLGPerson
Classes are metaclasses.- print
LGPerson
The memory address of the class, known by this validation, of the objectisa
Pointing to class, of classisa
Pointing to the metaclass
- Instance variable of
Type of relationship
- The basic concept
- The root class: in
OC
Almost all classes in theNSObject
Class,NSObject
The class is the root class, and the parent of the root class isnil
- Metaclass: in our peacetime development will use class method and instance method, but there is no such distinction in the implementation of the underlying, in fact, are through the instance method to find, in order to distinguish these two methods, the concept of the introduction of metaclass, and then the instance method stored in the class, class method stored in the metaclass. Of the class
isa
Point to metaclass. - Root metaclass: is the root class
NSObject
theisa
Point to the class
- The root class: in
- The diagram
- Conclusion:
isa
To:- Instance variable of
isa
Point to the corresponding class - Of the class
isa
Point to the corresponding metaclass - metaclass
isa
Point to the root metaclass - A metaclass
isa
Point to their own
- Instance variable of
- Class inheritance:
- Of the class
superclass
Points to the parent class - Of the parent class
superclass
Point to the root class - The root class
superclass
Point to thenil
- Of the class
- Metaclass inheritance:
- metaclass
superclass
A metaclass that points to the parent of the corresponding class - Of the metaclass of the parent class
superclass
Point to the root metaclass - A metaclass
superclass
Point to the root class - The root class
superclass
Point to thenil
- metaclass
Addendum: translation value is stored in the structure
- For example:
struct LGStruct {
int a; // Offset: 0, accounting for 4 bytes
char b; // Offset: 4, accounting for 1 byte
int c; // Offset: 8, accounting for 4 bytes
long d; // Offset: 16, 8 bytes (the starting position of the member variable is an integer multiple of the memory occupied by the current member variable)
};
int main(int argc, const char * argv[]) {
@autoreleasepool {
struct LGStruct s;
s.a = 10;
s.b = 'a';
s.c = 30;
s.d = 40;
}
return 0;
}
Copy the code
- Retrieves the value of a member variable:
- First determine the structure variable address
- Determines the offset position of the member variable
- Calculates the memory address of a member variable: structure variable address + the offset position of the variable
- Converts the computed address to a pointer type of the variable’s corresponding type (e.g
a
isint
Type, converts the computed address toint *
Type, the purpose of this turn is to extractint
Type value)
Class of storage
- From the previous analysis, we have a general understanding of the relationships between classes and the structure of the class, but we are not clear about how the class is stored in memory.
- Where are properties stored?
- Where are member variables stored?
- Where are methods stored?
- So let’s go through
LLDB
Combined with the source code of the way to analyze the next class in memory storage
The bits analysis of the class
- The following debugging analysis is needed
objc
Source code project, this article debugging source code address:Gitee.com/jrcode/ios_… LGPerson
Definition:
@interface LGPerson : NSObject {
NSString *subject;
}
@property (nonatomic.copy) NSString *name;
- (void)sayHello;
+ (void)say666;
@end
@implementation LGPerson
- (void)sayHello {}
+ (void)say666 {}
@end
Copy the code
- As you can see from the above class structure, there are four main member variables in the class:
Class ISA;
: isa pointerClass superclass;
: the parent classcache_t cache;
: Cache relatedclass_data_bits_t bits;
- As you can see from the class member variables, the data in the class should be stored in
bits
In, the following key analysisbits
- First of all to see
cache_t
Definition:
struct cache_t {
explicit_atomic<uintptr_t> _bucketsAndMaybeMask;
union {
struct {
explicit_atomic<mask_t> _maybeMask; // uint32_t
#if __LP64__
uint16_t _flags; / / 2 bytes
#endif
uint16_t _occupied; / / 2 bytes
};
explicit_atomic<preopt_cache_t *> _originalPreoptCache;
};
// Static variables and methods are memory free
}
Copy the code
- from
cache_t
The definition of can be seen as:- The first member variable
_bucketsAndMaybeMask
foruintptr_t
Type, which is actuallyunsigned long
The type,8
byte - The second member variable is union (union members share the same block of memory)
- The first member of the consortium is the structure, which occupies the largest proportion
8
byte - The second member of the union is of type pointer, accounting for
8
byte - Therefore, the memory size of the union is the memory size of the maximum member, i.e
8
byte
- The first member of the consortium is the structure, which occupies the largest proportion
- So,
cache_t
Memory is16
byte
- The first member variable
bits
Data acquisition:- It can be obtained by the method of storing translation value in the structure introduced earlier
bits
The value of the - In obtaining
bits
You need to determine the value ofbits
The offset - The first two member variables
ISA
andsuperclass
Are allClass
Type, andClass
forstructobjc_class *
Type, 8 bytes - The third member variable
cache
forcache_t
The type,16
byte - So, member variables
bits
The offset address of is32
Bytes (address + can be stored in the structure body0x20
Calculated)
- It can be obtained by the method of storing translation value in the structure introduced earlier
class_data_bits_t
Definition:
struct class_data_bits_t {
friend objc_class;
// Values are the FAST_ flags above.
uintptr_t bits;
// ...
class_rw_t* data() const {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
// ...
};
Copy the code
- from
class_data_bits_t
The definition of can be seen throughdata()
Get the data and the result isclass_rw_t
type class_rw_t
Definition:
struct class_rw_t {
// Be warned that Symbolication knows the layout of this structure.
uint32_t flags;
uint16_t witness;
#if SUPPORT_INDEXED_ISA
uint16_t index;
#endif
explicit_atomic<uintptr_t> ro_or_rw_ext;
Class firstSubclass;
Class nextSiblingClass;
// ...
const class_ro_t *ro() const {
auto v = get_ro_or_rwe();
if (slowpath(v.is<class_rw_ext_t *>())) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->ro;
}
return v.get<const class_ro_t *>(&ro_or_rw_ext);
}
// ...
const method_array_t methods() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->methods;
} else {
return method_array_t{v.get<constclass_ro_t *>(&ro_or_rw_ext)->baseMethods()}; }}const property_array_t properties() const {
auto v = get_ro_or_rwe();
if (v.is<class_rw_ext_t *>()) {
return v.get<class_rw_ext_t *>(&ro_or_rw_ext)->properties;
} else {
return property_array_t{v.get<constclass_ro_t *>(&ro_or_rw_ext)->baseProperties}; }}// ...
};
Copy the code
- from
class_rw_t
The definition of “can be seen in several important ways:methods()
properties()
ro()
- The following through
LLDB
So let’s just debug and verify that this is where we think it’s going to be
Read class_rw_t data
- To get
LGPerson
The memory address of the class - Obtained by internal translation of the structure
bits
value - To obtain
bits
Stored in theclass_rw_t
Type data address - To view
class_rw_t
The specific data stored in
Store of properties (property_t)
p $2->properties()
: Gets the attribute informationproperty_array_t
Type data, inherited fromlist_array_tt
:
template <typename Element, typename List, template<typename> class Ptr>
class list_array_tt {
// ...
union {
Ptr<List> list;
uintptr_t arrayAndFlag;
};
// ...
};
Copy the code
p $8.list.ptr
: getproperty_array_t
Stored in theproperty_list_t
data- From the above
list_array_tt
The definition of theta can be seen herelist
forList
Type data, which is passed inproperty_list_t
Type data
- From the above
- To view
property_list_t
Storing data,property_list_t
Inherited fromentsize_list_tt
:- I’ve defined one here
get
Method, callget
It will end up callinggetOrEnd
, the returned data type isElement
Element
The type is passed inproperty_t
type
- I’ve defined one here
template <typename Element, typename List, uint32_t FlagMask, typename PointerModifier = PointerModifierNop>
struct entsize_list_tt {
uint32_t entsizeAndFlags;
uint32_t count;
// ...
Element& getOrEnd(uint32_t i) const {
ASSERT(i <= count);
return *PointerModifier::modify(*this, (Element *)((uint8_t *)this + sizeof(*this) + i*entsize()));
}
Element& get(uint32_t i) const {
ASSERT(i < count);
return getOrEnd(i);
}
// ...
};
Copy the code
- through
get
Methods to obtainproperty_t
Type data:
struct property_t {
const char *name;
const char *attributes;
};
Copy the code
Storage of object methods (method_t)
p $2->methods()
: Gets method information and returnsmethod_array_t
Type data, inherited fromlist_array_tt
p $12.list.ptr
: getmethod_array_t
Stored in themethod_list_t
data- To view
method_list_t
Storing data,method_list_t
Inherited fromentsize_list_tt
:Element
The type is passed inmethod_t
type
- through
get
Methods to obtainmethod_t
Type data, printed here{}
You can take a lookmethod_t
Definition:- As you can see by definition,
method_t
Need to pass throughbig()
Take out the data
- As you can see by definition,
struct method_t {
// ...
struct big {
SEL name;
const char *types;
MethodListIMP imp;
};
// ...
big &big() const{ ASSERT(! isSmall());return* (struct big *)this;
}
// ...
};
Copy the code
- Print respectively
sayHello
And attributesname
The correspondinggetter
andsetter
Methods information
Member variable storage (iVAR_t)
p $2->ro()
: getro
Information, returnclass_ro_t
Type data,class_ro_t
Definition:- This structure contains
ivar_list_t
Type of a member variableivars
ivars
To store the member variable data we defined
- This structure contains
struct class_ro_t {
uint32_t flags;
uint32_t instanceStart;
uint32_t instanceSize;
#ifdef __LP64__
uint32_t reserved;
#endif
union {
const uint8_t * ivarLayout;
Class nonMetaclass;
};
explicit_atomic<const char *> name;
// With ptrauth, this is signed if it points to a small list, but
// may be unsigned if it points to a big list.
void *baseMethodList;
protocol_list_t * baseProtocols;
const ivar_list_t * ivars;
const uint8_t * weakIvarLayout;
property_list_t *baseProperties;
// ...
};
Copy the code
p $19->ivars
: Gets information about member variables and returnsivar_list_t
Type data- To view
ivar_list_t
Storing data,ivar_list_t
Inherited fromentsize_list_tt
:Element
The type is passed inivar_t
type
- through
get
Methods to obtainivar_t
Type data:
struct ivar_t {
int32_t *offset;
const char *name;
const char *type;
// alignment is sometimes -1; use alignment() instead
uint32_t alignment_raw;
uint32_t size;
// ...
};
Copy the code
Storage of class methods (method_t)
- Class methods are stored in metaclasses
- through
x/4gx LGPerson.class
: seeLGPerson
Class memory structure - through
ISA_MASK
Gets the value of theLGPerson
Of the classisa
, that is, to findLGPerson
Class corresponding to the metaclass - Through the address of the metaclass, memory translation to get the metaclass
bits
Memory address - through
data()
To obtainbits
Data stored in
- through
methods()
Of the metaclassbits
Method list data stored in p $12.list.ptr
: getmethod_array_t
Stored in themethod_list_t
data- To view
method_list_t
Storing data,method_list_t
Inherited fromentsize_list_tt
:Element
The type is passed inmethod_t
type
- through
get
Methods andbig()
To obtainmethod_t
Type data, outputsay666
Method information, that is, class methods, is stored in metaclasses