preface
Isa isa pointer to struct objc_class. Finally, we also have a preliminary understanding of the class inheritance and bitmap provided by apple official. Today we’re going to take a deep dive into the underlying structure of the class and take a deep look at apple’s official ISA bitmap.
1.0 Memory Offset
Before exploring the underlying structure of classes, take a look at Pointers and offsets. A pointer is an address variable that also requires memory address storage. The offset is relative to the header address, which is the address of an object or variable in memory.
1.0.1 Ordinary Pointers
int main(int argc, const char * argv[]) {
@autoreleasepool {
int a = 10;
int b = 10;
int* c=&a;
int* d=&b;
NSLog(@"%d--%p--%p--%p",a,c,&a,&c);
NSLog(@"%d--%p--%p--%p",b,d,&b,&d);
}
return 0;
}
Copy the code
The output is as follows:
10--0x7ffeefbff1ec--0x7ffeefbff1ec--0x7ffeefbff1e0
10--0x7ffeefbff1e8--0x7ffeefbff1e8--0x7ffeefbff1d8
Copy the code
Analysis:
- The value of A is 10, and the address is
0x7ffeefbff1ec
That’s also the value of c, the value of B is 10, and the address is0x7ffeefbff1e8
It’s also the value of D, which means that even though the value is the same, memory is allocated to store the address of A and the address of B respectivelyDifference between
0x4 is four bytes, and the difference depends on the type of A,A is an int
, 4 bytes. - The value of c is 0x7FFeEFbff1ec, and the address is
0x7ffeefbff1e0
, the value of d is 0x7ffeefbff1e8 and the address is0x7ffeefbff1d8
, the difference between the address of C and the address of D 0x8 is 8 bytes, c is a pointer,Pointers are 8 bytes long
. - A, B, C, and D are all variables.
Variables are stored in the stack area
.The stack area
The address of theHigh address to low address
, a address 0x7ffeefbff1ecIs greater than
B’s address 0x7ffeefbff1e8.
1.0.2 Object Pointers
int main(int argc, const char * argv[]) {
@autoreleasepool {
LGPerson *p1 = [LGPerson alloc];
LGPerson *p2 = [LGPerson alloc];
NSLog(@"%@ -- %p",p1,&p1);
NSLog(@"%@ -- %p",p2,&p2);
}
return 0;
}
Copy the code
The output is as follows:
<LGPerson: 0x100626410> -- 0x7ffeefbff1e8
<LGPerson: 0x100625440> -- 0x7ffeefbff1e0
Copy the code
Analysis:
object
The memory isThe heap area
, the localvariable
The memory isThe stack area
.The heap area
The address isLow address to high address
.The stack area
The address isHigh address to low address
. Address of p1 pointer0x7ffeefbff1e8
Address greater than p2 pointer0x7ffeefbff1e0
.Pointer to the
It’s for the addressvariable
, this variable is inThe stack area
, that is, Pointers are stored in the stack area. The value of p1 0x100626410 is less than the value of P2 0x100625440 is the address of p2.object
Is stored inThe heap area
.
The illustration below
1.0.3 Array Pointers
int main(int argc, const char * argv[]) {
@autoreleasepool {
int c[4] = {1.2.3.4};
int *d = c;
NSLog(@"%p - %p - %p",&c,&c[0],&c[1]);
NSLog(@"%p - %p - %p",d,d+1,d+2);
for (int i = 0; i<4; i++) {
int value = *(d+i);
NSLog(@"%d",value); }}return 0;
}
Copy the code
The output is as follows:
0x7ffeefbff1e0 - 0x7ffeefbff1e0 - 0x7ffeefbff1e4
0x7ffeefbff1e0 - 0x7ffeefbff1e4 - 0x7ffeefbff1e8
1
2
3
4
Copy the code
Analysis is as follows:
An array of
Is an array elementThe first address
, i.e.,&c
and&c[0]
- The offset of each element in the array, based on the current element’s data type
- The address of the element in an array can be the first address +n* type size, which is in the array
The element type
Must be the same
Conclusion:
variable
The memory isThe stack area
.object
The memory isThe heap area
.Pointer to the
It’s an address storevariable
In theThe stack area
.The stack area
High address to low address, heap low address to high address.Memory address
That’s the memory elementThe first address
.Memory migration
According toFirst address + offset value
Method to obtain the address of the dependent variable.
2.0 ISA analysis
We analyze isa to get the value of shiftcls in ISA, that is, the value of the class pointer, to get the class object associated with ISA. We find that the ISA of an instance object is associated with a class object, and the ISA of a class object is associated with a class object, called a metaclass. Let’s look at this in detail.
2.0.1 Classes and metaclasses
Class class1 = [LGPerson class];
Class class2 = [LGPerson alloc].class;
Class class3 = object_getClass([LGPerson alloc]);
Class class4 = [LGPerson alloc].class;
NSLog(@"\n%p-\n%p-\n%p-\n%p",class1,class2,class3,class4);
Copy the code
Output:
0x100008360-
0x100008360-
0x100008360-
0x100008360
Copy the code
Analysis: No matter how many alloc times, the memory address of the class object is the same, indicating that there is only one memory in memory to store the class object.
LGPerson *p = [LGPerson alloc]
(lldb) x/4gx p
0x1007055f0: 0x011d800100008365 0x0000000000000000
0x100705600: 0x0000000000000000 0x0000000000000000
(lldb) p/x 0x011d800100008365 & 0x00007ffffffffff8ULL
(unsigned long long) $1 = 0x0000000100008360
(lldb) po 0x0000000100008360
LGPerson
(lldb) x/4gx 0x0000000100008360
0x100008360: 0x0000000100008338 0x00007fff80691008
0x100008370: 0x0000000101805860 0x0002802c00000003
(lldb) p/x 0x0000000100008338 & 0x00007ffffffffff8ULL
(unsigned long long) $3 = 0x0000000100008338
(lldb) po 0x0000000100008338
LGPerson
Copy the code
Analysis: object P isa associated class object LGPerson, address 0x0000000100008360, but 0x0000000100008338 address is also LGPerson? We know that there is only one memory in memory for this class object, so what is 0x0000000100008338? Apple officially calls it a metaclass, and the system generates it automatically.
What is the isa associated with this metaclass, and how many layers of objects are associated with it? Then the LLDB above continues to explore
(lldb) x/4gx p
0x1007055f0: 0x011d800100008365 0x0000000000000000
0x100705600: 0x0000000000000000 0x0000000000000000
(lldb) p/x 0x011d800100008365 & 0x00007ffffffffff8ULL
(unsigned long long) $1 = 0x0000000100008360
(lldb) po 0x0000000100008360
LGPerson
(lldb) x/4gx 0x0000000100008360
0x100008360: 0x0000000100008338 0x00007fff80691008
0x100008370: 0x0000000101805860 0x0002802c00000003
(lldb) p/x 0x0000000100008338 & 0x00007ffffffffff8ULL
(unsigned long long) $3 = 0x0000000100008338
(lldb) po 0x0000000100008338
LGPerson
(lldb) x/4gx 0x0000000100008338
0x100008338: 0x00007fff80690fe0 0x00007fff80690fe0
0x100008348: 0x000000010053a640 0x0002e03500000003
(lldb) p/x 0x00007fff80690fe0 & 0x00007ffffffffff8ULL
(unsigned long long) $5 = 0x00007fff80690fe0
(lldb) po 0x00007fff80690fe0
NSObject
(lldb) x/4gx 0x00007fff80690fe0
0x7fff80690fe0: 0x00007fff80690fe0 0x00007fff80691008
0x7fff80690ff0: 0x0000000101807b80 0x0003e03100000007
(lldb) p/x 0x00007fff80690fe0 & 0x00007ffffffffff8ULL
(unsigned long long) $7 = 0x00007fff80690fe0
Copy the code
Analysis: LGPerson object isa- >LGPerson class ISA ->LGPerson metaclass ISA ->NSObject root metaclass
Now that we’re pointing to NSObject, let’s look at the ISA bitmap of NSObject. NSObject* myobjc=[NSObject alloc] LLDB debug as follows
(lldb) x/4gx myobjc
0x103098400: 0x011dffff80691009 0x0000000000000000
0x103098410: 0x63756f54534e5b2d 0x7765695672614268
(lldb) p/x 0x011dffff80691009 & 0x00007ffffffffff8ULL
(unsigned long long) $1 = 0x00007fff80691008
(lldb) po 0x00007fff80691008
NSObject
(lldb) x/4gx 0x00007fff80691008
0x7fff80691008: 0x00007fff80690fe0 0x0000000000000000
0x7fff80691018: 0x000000010052a160 0x0001801000000003
(lldb) p/x 0x00007fff80690fe0 & 0x00007ffffffffff8ULL
(unsigned long long) $3 = 0x00007fff80690fe0
(lldb) po 0x00007fff80690fe0
NSObject
(lldb) x/4gx 0x00007fff80690fe0
0x7fff80690fe0: 0x00007fff80690fe0 0x00007fff80691008
0x7fff80690ff0: 0x0000000103007d90 0x0003e03100000007
(lldb) p/x 0x00007fff80690fe0 & 0x00007ffffffffff8ULL
(unsigned long long) $5 = 0x00007fff80690fe0
(lldb) po 0x00007fff80690fe0
NSObject
Copy the code
NSObject isa isa isa isa NSObject Isa isa NSObject isa isa NSObject metaclass itself is the root metaclass.
The above analysis is easier to understand in the previous diagram than LGPerson.
2.0.2 Class inheritance
We have analyzed the ISA relation of the class above, but is the ISA relation of the inherited class also like this, and how is the ISA relation of the inherited class parent? We’ll create a new object LGTeacher *t = [LGTeacher alloc]; LGTeacher inherits from LGPerson, LLDB to debug isa associations.
(lldb) x/4gx t
0x103836e70: 0x011d800100008315 0x0000000000000000
0x103836e80: 0x0000000000000000 0x0000000000000000
(lldb) p/x 0x011d800100008315 & 0x00007ffffffffff8ULL
(unsigned long long) $8 = 0x0000000100008310
(lldb) po 0x0000000100008310
LGTeacher
(lldb) x/4gx 0x0000000100008310
0x100008310: 0x00000001000082e8 0x0000000100008360
0x100008320: 0x00007fff20282aa0 0x0000802c00000000
(lldb) p/x 0x00000001000082e8 & 0x00007ffffffffff8ULL
(unsigned long long) $10 = 0x00000001000082e8
(lldb) po 0x00000001000082e8
LGTeacher
(lldb) x/4gx 0x00000001000082e8
0x1000082e8: 0x00007fff80690fe0 0x0000000100008338
0x1000082f8: 0x000000010061cf20 0x0002e03500000003
(lldb) p/x 0x00007fff80690fe0 & 0x00007ffffffffff8ULL
(unsigned long long) $12 = 0x00007fff80690fe0
(lldb) po 0x00007fff80690fe0
NSObject
Copy the code
Analysis: : LGTeacher object isa >LGTeacher class ISA >LGTeacher metaclass ISA >NSObject root metaclass. So see with LGTeacher’s ISA and LGPerson’s ISA is the same, LGTeacher and LGPerson have no other relationship?
Continue demo exploration:
/ / LGPerson metaclass
Class pMetaClass = object_getClass(LGPerson.class);
Class psuperClass = class_getSuperclass(pMetaClass);
NSLog(@"Metaclass: %@ - %p Parent metaclass: %@ - %p",pMetaClass,pMetaClass,psuperClass,psuperClass);
/ / LGTeacher metaclass
Class tMetaClass = object_getClass(LGTeacher.class);
Class tsuperClass = class_getSuperclass(tMetaClass);
NSLog(@"Metaclass: %@ - %p Parent metaclass: %@ - %p",tMetaClass,tMetaClass,tsuperClass,tsuperClass);
// NSObject root metaclass parent class
Class nsuperClass = class_getSuperclass(NSObject.class);
NSLog(@"%@ - %p",nsuperClass,nsuperClass);
Copy the code
The output is as follows:
Metaclass: LGPerson -0x100008338Metaclass parent: NSObject -0x7fff80690fe0Metaclass: LGTeacher -0x1000082e8Metaclass parent: LGPerson -0x100008338
(null) - 0x0
Copy the code
The parent address of the LGTeacher metaclass is 0x100008338, the address of the LGTeacher metaclass is 0x100008338, and the address of the LGTeacher metaclass is 0x100008338. The LGTeacher metaclass inherits from the LGPerson metaclass and the NSObject root metaclass inherits from nil.
The inheritance relationship ISA is shown below:
Compare apple’s official ISA with the above analysis, and it becomes clear:
Structure analysis of class 3.0
Isa isa isa isa Isa Isa Isa Isa Isa Isa Isa Isa Isa Isa Isa Isa Isa Isa Isa Isa Isa Isa Isa isa isa isa isa isa isa Objc4-818.2 objC_class = objC4-818.2
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
// Here are some methods to omit};Copy the code
struct objc_object {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
};
Copy the code
Objc_class inherits objc_Object, which has only one member variable isa. The member variables in objC_class are ISA, superclass, Cache, and bits. Superclass is a structure pointer to objc_class with 8 bytes.
Find the definition of cache_t:
typedef unsigned long uintptr_t;
#if __LP64__
typedef uint32_t mask_t; // x86_64 & arm64 asm are less efficient with 16-bits
#else
typedef uint16_t mask_t;
#endif
struct cache_t {
private:
explicit_atomic<uintptr_t> _bucketsAndMaybeMask; / / 8
union {
struct {
explicit_atomic<mask_t> _maybeMask; / / 4
#if __LP64__
uint16_t _flags; / / 2
#endif
uint16_t _occupied; / / 2
};
explicit_atomic<preopt_cache_t *> _originalPreoptCache; / / 8
};
// Here are some methods to omit
};
Copy the code
Analysis:
cache_t
Is a structure type with two member variables _bucketsAndMaybeMask and a union._bucketsAndMaybeMask
No operator is uintptr_tLong integers account for 8 bytes
.A consortium
There are two member variables in thereThe structure of the body
and_originalPreoptCache
The memory size of the union is determined by the maximum variable type in the member variable.
-_originalPreoptCache is a structure pointer of 8 bytes. The structure contains _maybeMask, _flags, _occupied. _maybeMask is the uint32_t of 4 bytes, _flags and _occupied are the Uint16_t of 2 bytes each, and the structure size is 8 bytes.
cache_t
The memory size of 8+8 or 8+4+2+2 is 16 bytes.
Objc_class summary
- The address of the first element in the structure is this
The first address of a structure
- Isa’s memory address is the first address of objc_class, which is 8 bytes
- The memory address of a superclass is the first address
+0x8
, 8 bytes - The memory address of the cache is the first address +
0x10
, 16 bytes - The memory address of bits is the first address +
0x20
3.1 –
Today we’re going to focus on what’s stored in bits, and notice that we’ve been analyzing classes, and bits are in classes. Bits is a class_data_bits_t struct. The source code is too long.
struct class_data_bits_t {
friend objc_class;// the friend keyword sets objc_class as a friend structure
// Values are the FAST_ flags above.
uintptr_t bits;Unsigned long integer 8 bytes
private:
// Omit some struct methods
public:
//data stores attributes, methods, protocols, etc
class_rw_t* data() const {
return (class_rw_t *)(bits & FAST_DATA_MASK);
}
// Store member variables
const class_ro_t *safe_ro() const {
class_rw_t *maybe_rw = data();
if (maybe_rw->flags & RW_REALIZED) {
// maybe_rw is rw
return maybe_rw->ro();
} else {
// maybe_rw is actually ro
return(class_ro_t *)maybe_rw; }}// Omit some struct methods
};
Copy the code
Analysis:
class_data_bits_t
There is only one long integer member variable in the structurebits
- The long integer variable bits has no desire to explore, but finds a point
class_rw_t
Structure pointer todata()
The programmer’s intuition about what data should store.
Take a look at the class_rw_T 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;
/ / to omit...
class_rw_ext_t *ext() const {
/ / to omit...
}
class_rw_ext_t *extAllocIfNeeded() {
/ / to omit...
}
class_rw_ext_t *deepCopy(const class_ro_t *ro) {
return extAlloc(ro, true);
}
// Member variables
const class_ro_t *ro() const {
/ / to omit...
}
void set_ro(const class_ro_t *ro) {
/ / to omit...
}
/ / method
const method_array_t methods() const {
/ / to omit...
}
const property_array_t properties() const {
/ / to omit...
}
const protocol_array_t protocols() const {
/ / to omit...
}
Copy the code
Analysis:
- The class_rw_t structure has familiar methods(), properties(),protocols()
3.2 Attribute Acquisition
Example verify that class_rw_t stores methods, attributes, and protocols. Create a demo like this and instantiate the LGPerson demo like this:
@protocol LGPersonDegete<NSObject>
-(void)testLGperson;
@end
@interface LGPerson : NSObject<LGPersonDegete>{
NSString *subject;
}
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *hobby;
- (void)sayNB;
+ (void)say666;
@end
Copy the code
LLDB debugging gets properties:
KCObjcBuild was compiled with optimization - stepping may behave oddly; variables may not be available.
(lldb) p/x LGPerson.class
(Class) $0 = 0x0000000100008380 LGPerson
(lldb) p/x 0x0000000100008380 + 0x20 // Note: the first address +0x20 offset is class_datA_bits_t address
(long) $1 = 0x00000001000083a0
(lldb) p (class_data_bits_t*)$1
(class_data_bits_t *) $2 = 0x00000001000083a0
(lldb) p $2->data() // Comment: get data
(class_rw_t *) $3 = 0x0000000100723c30
(lldb) p $3->properties() // Comment: get attributes in data
(const property_array_t) $4 = {
list_array_tt<property_t, property_list_t, RawPtr> = {
= {
list = {
ptr = 0x0000000100008260
}
arrayAndFlag = 4295000672
}
}
}
(lldb) p $4.list // Comment: Get the property list
(const RawPtr<property_list_t>) $5 = {
ptr = 0x0000000100008260
}
(lldb) p $5.ptr // Comment: Get the attribute list PTR
(property_list_t *const) $6 = 0x0000000100008260
(lldb) p *$6
(property_list_t) $7 = { // Comment: Get attribute list information
entsize_list_tt<property_t, property_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 16, count = 2)
}
(lldb) p $7.get(0) // Comment: the first attribute
(property_t) $8 = (name = "name", attributes = "T@\"NSString\",C,N,V_name")
(lldb) p $7.get(1) // Comment: second attribute
(property_t) $9 = (name = "hobby", attributes = "T@\"NSString\",C,N,V_hobby")
(lldb)
Copy the code
Analysis: Comments illustrate the LLDB debugging process. LGPerson->class_data_bits_t->data->properties->list->ptr->get
3.3 Method Acquisition
LLDB debugging is as follows:
(lldb) p $3->methods() // Comment: get method
(const method_array_t) $10 = {
list_array_tt<method_t, method_list_t, method_list_t_authed_ptr> = {
= {
list = {
ptr = 0x0000000100008160
}
arrayAndFlag = 4295000416
}
}
}
(lldb) p $10.list // Comment: Get a list of methods
(const method_list_t_authed_ptr<method_list_t>) $11 = {
ptr = 0x0000000100008160
}
(lldb) p $11.ptr // Comment: Get method list PTR
(method_list_t *const) $12 = 0x0000000100008160
(lldb) p *$12
(method_list_t) $13 = {
entsize_list_tt<method_t, method_list_t, 4294901763.method_t::pointer_modifier> = (entsizeAndFlags = 27, count = 6)
}
(lldb) p $13.get(0).big() // Comment: get the first method
(method_t::big) $15 = {
name = "sayNB"
types = 0x0000000100003f77 "v16@0:8"
imp = 0x0000000100003d40 (KCObjcBuild` - [LGPerson sayNB])} (LLDB) p $13. Get (1). The big () / / comment: Get the second method (method_t::big) $16 = {name = "hobby" types = 0x0000000100003F6f "@16@0:8" IMP = 0x0000000100003DB0 (KCObjcBuild`-[LGPerson hobby])
}
(lldb) p $13.get(2).big()
(method_t::big) $17 = {
name = "setHobby:"
types = 0x0000000100003f8b "v24@0:8@16"
imp = 0x0000000100003de0 (KCObjcBuild`-[LGPerson setHobby:]) } (lldb) p $13.get(3).big() (method_t::big) $18 = { name = "init" types = 0x0000000100003f6f "@16@0:8" imp = 0x0000000100003ce0 (KCObjcBuild`-[LGPerson init])
}
Copy the code
Analysis:
- Unlike getting properties(), getting methods is actually getting method_t, which has a big() method to get method.
- Comments mark the process of LLDB debugging.
LGPerson->class_data_bits_t->data->methods()->list->ptr->get(0).big()
. - Watch carefully LGPerson, I sayNB and say666 defines two methods, through LLDB debugging found LGPerson. Only sayNB class class () method without say666 () method, according to? SayNB is ()
Instance method it's in the class
, thenObject methods
say666()Where is it
? Watch my next blog for a detailed analysis.
3.4 Obtaining Protocols
(lldb) p/x LGPerson.class
(Class) $15 = 0x0000000100008898 LGPerson
(lldb) p/x 0x0000000100008898 + 0x20
(long) $16 = 0x00000001000088b8
(lldb) p/x (class_data_bits_t*)$16
(class_data_bits_t *) $17 = 0x00000001000088b8
(lldb) p $17->data()
(class_rw_t *) $18 = 0x0000000100707990
(lldb) p $18->protocols()
(const protocol_array_t) $19 = {
list_array_tt<unsigned long, protocol_list_t, RawPtr> = {
= {
list = {
ptr = 0x0000000100008348
}
arrayAndFlag = 4295000904
}
}
}
(lldb) p $19.list
(const RawPtr<protocol_list_t>) $20 = {
ptr = 0x0000000100008348
}
(lldb) p $20.ptr
(protocol_list_t *const) $21 = 0x0000000100008348
(lldb) p *$21
(protocol_list_t) $22 = (count = 1, list = protocol_ref_t [] @ 0x00007fa105c5eae8)
(lldb) p $22.list[0] Protocol_list_t = list[0];
(protocol_ref_t) $23 = 4295002352
(lldb) p (protocol_t*)$23 / / turn protocol_ref_t protocol_t strong
(protocol_t *) $24 = 0x00000001000088f0
(lldb) p $24
(protocol_t *) $24 = 0x00000001000088f0
(lldb) p *$24
(protocol_t) $25 = {
objc_object = {
isa = {
bits = 4298547400
cls = Protocol
= {
nonpointer = 0
has_assoc = 0
has_cxx_dtor = 0
shiftcls = 537318425
magic = 0
weakly_referenced = 0
unused = 0
has_sidetable_rc = 0
extra_rc = 0
}
}
}
mangledName = 0x0000000100003c3a "LGPersonDegete"
protocols = 0x0000000100008430
instanceMethods = 0x0000000100008448
classMethods = 0x0000000000000000
optionalInstanceMethods = 0x0000000000000000
optionalClassMethods = 0x0000000000000000
instanceProperties = 0x0000000000000000
size = 96
flags = 0
_extendedMethodTypes = 0x0000000100008468
_demangledName = 0x0000000000000000
_classProperties = 0x0000000000000000
}
(lldb)
Copy the code
Analysis:
- Protocol to obtain a complex need to structure the source code analysis, first to obtain
Structure protocol_list_t
Gets a member variable in the protocol_list_t structurelist[0
], the member variable is protocol_ref_t,Cast protocol_ref_t
forprotocol_t
, and return the protocol_t value - LGPerson – > class_data_bits_t – > data – > protocol () – > list – > PTR [0] – > – > list are strong protocol_t *
3.5 Obtaining member variables
Class_rw_t does get methods, attributes, and protocols, but does not. The subject variable in our demo does not get methods, attributes, and protocols. Where is it stored? There is a method to get ro() in class_rw_t, which LLDB explores.
(lldb) p/x LGPerson.class
(Class) $27 = 0x0000000100008898 LGPerson
(lldb) p/x 0x0000000100008898 + 0x20
(long) $28 = 0x00000001000088b8
(lldb) p (class_data_bits_t*)$28
(class_data_bits_t *) $29 = 0x00000001000088b8
(lldb) p $29->data()
(class_rw_t *) $30 = 0x0000000100707990
(lldb) p $30->ro()
(const class_ro_t *) $31 = 0x0000000100008250
(lldb) p *$31
(const class_ro_t) $32 = {
flags = 0
instanceStart = 8
instanceSize = 32
reserved = 0
= {
ivarLayout = 0x0000000000000000
nonMetaclass = nil
}
name = {
std::__1::atomic<const char *> = "LGPerson" {
Value = 0x0000000100003c31 "LGPerson"
}
}
baseMethodList = 0x0000000100008298
baseProtocols = 0x0000000100008348
ivars = 0x0000000100008360
weakIvarLayout = 0x0000000000000000
baseProperties = 0x00000001000083c8
_swiftMetadataInitializer_NEVER_USE = {}
}
(lldb) p $32.ivars
(const ivar_list_t *const) $33 = 0x0000000100008360
(lldb) p *$33
(const ivar_list_t) $34 = {
entsize_list_tt<ivar_t, ivar_list_t, 0, PointerModifierNop> = (entsizeAndFlags = 32, count = 3)
}
(lldb) p $34.get(0)
(ivar_t) $35 = {
offset = 0x00000001000087e0
name = 0x0000000100003caf "subject"
type = 0x0000000100003e0d "@\"NSString\""
alignment_raw = 3
size = 8
}
(lldb)
Copy the code
Analysis:
Member variables
subjectIn ro ()
In the- LGPerson->class_data_bits_t->data->ro()->ivars->get(0)
Conclusion:
isa
Is a point toobjc_class
theStructure pointer
.objc_class
inheritanceobjc_object
.- The objc_class structure has member variables
Isa, Superclass, Cache, bits
bits
It’s a class_data_bits_t struct, structPointer method data()
You can getProperty list, method list, member variable list, protocol list
And so on.Member variables
Pointer to the data() structurero()
In the