In the last article, we studied the nature of objects through the source code compiled by Clang. In this article, we further analyze the class, or cut into the actual case.
The analysis of the class
We make a breakpoint when the object alloc, input the corresponding LLDB debugging instruction, and analyze the class by outputting the memory address. For details, please refer to the following
LLDB debugging command
X /nuf <addr> n Indicates the number of memory units to be displayed -------------------------- u indicates the length of an address unit. B indicates single byte. H indicates double bytes -------------------------- f indicates the display mode. The value can be: X displays variables in hexadecimal format d in decimal format U displays variables in decimal format unsigned integer o Displays variables in octal format T Displays variables in binary format A Displays variables in hexadecimal format I Instruction address format C Displays variables in character format F Displays variables in floating point formatCopy the code
Breakpoint debugging
When the breakpoint is at alloc, enter the LLDB instruction x/4gx p, and you can see the pointer address of the object output. The first address 0x011D800100008489 is the ISA pointer address of the object ATPerson. This paper takes x86_64 architecture as an example, 0x00007ffffffffff8ULL), and the result is 0x0000000100008488. The output result is ATPerson class through Po.
One more thought about the above output is that if we get the isa pointer to the class and&
onISA_MASK
And what was the result?
Based on the output above, we see that the result is stillATPerson
, is the same as before, but the memory address of the second time is inconsistent, the address of the first time is0x0000000100008488
And the second address is0x0000000100008460
, belong toATPerson
, but the address is not consistent, let’s write another function to verify:
Class class1 = [ATPerson Class]; void atTestClassNum(void) {Class Class [ATPerson Class]; Class class2 = [ATPerson alloc].class; Class class3 = object_getClass([ATPerson alloc]); Class class4 = [ATPerson alloc].class; NSLog(@"\n%p \n%p \n%p \n%p",class1,class2,class3,class4); Int main(int argc, const char * argv[]) {@autoreleasepool {atTestClassNum(); } return 0; }Copy the code
A printout
I get all of these0x100008488
That’s the same thing as the first time up, the second time upATPerson
What is it? According to the compiled executable (Products - > project name
), use MachOView tool to analyze the symbol table and findSymbol Table ~> Symbols
, search box inputclass
You can find a lot of information about classATPerson
The relevant position can be seen_OBJC_CLASS_$_ATPerson
And there’s another one on top_OBJC_METACLASS_$_ATPerson
That’s the concept of objective-C metaclasses, which are automatically compiled by the system.
Based on the above debugging analysis, we can draw a simple conclusion: object ISA ~> class ISA ~> metaclass; Let’s take a closer look at class formation in two directions.
First, ISA is out of position
From the above analysis we explored object -> class -> metaclass, so a question? Do metaclasses have ISA? Where does the isa of that metaclass point if it exists? We explore the following questions in two directions:
Custom class
Then the above ATPerson continues to analyze
Print the address of the metaclass ATPerson at 10x0000000100008460
, continue to execute x/4gx to get the metaclass isa as0x000000010036a0f0
.&
onISA_MASK
You get the root metaclass0x000000010036a0f0
That’s the second oneNSObject
, x/4gx and get isa(0x000000010036a0f0
),&
onISA_MASK
And then you get the same result in the third position as in the second positionNSObject
; So the line looks like this:
Object ISA ~> class ISA ~> metaclass ISA ~> root metaclass ISA ~> root metaclass.
NSObject class
Print the address of the NSObject root class is0x000000010036a140
Gets the ADDRESS of the ISA pointer to NSObject0x000000010036a0f0
The root metaclass address is the same as the root metaclass address. So the line is:The root class isa
~ >A metaclass isa
Based on the above two directions of exploration, we have summarized the following isa trend chart.
The ISA of the object finds the class, the ISA of the class finds the metaclass, the ISA of the metaclass finds the root metaclass, and the ISA of the root metaclass finds itself.
Second, the chain of inheritance
Analyze class inheritance with the following code, executed and printed in the main function
ATTeacher inherits ATPerson, and ATPerson inherits NSObject
Void atTestNSObject(void) {// NSObject instance object NSObject *object = [NSObject alloc]; // NSObject Class Class = object_getClass(object); // NSObject metaClass = object_getClass(Class); // NSObject rootMetaClass Class rootMetaClass = object_getClass(metaClass); // NSObject rootMetaClass Class rootRootMetaClass = object_getClass(rootMetaClass); NSLog (@ "\ n \ n % p % p instance objects class p metaClass \ n \ n % % p root metaClass \ n % p spikes metaClass", object, class, metaClass, rootMetaClass, rootRootMetaClass); // Class pMetaClass = object_getClass(atPerson.class); Class psuperClass = class_getSuperclass(pMetaClass); NSLog(@"%@ - %p",psuperClass,psuperClass); Class tMetaClass = object_getClass(atteacher.class); // ATTeacher -> ATPerson -> NSObject Class tsuperClass = class_getSuperclass(tMetaClass); NSLog(@"%@ - %p",tsuperClass,tsuperClass); // NSObject Root Class special case Class nsuperClass = class_getSuperclass(nsobjject); NSLog(@"%@ - %p",nsuperClass,nsuperClass); // root metaClass -> NSObject Class = class_getSuperclass(metaClass); NSLog(@"%@ - %p",rnsuperClass,rnsuperClass); } int main(int argc, const char * argv[]) { @autoreleasepool { atTestNSObject(); } return 0; }Copy the code
Run the output
The following conclusions can be drawn from the operation result data:
- NSObject’s metaclass, root metaclass, and root metaclass are the same
- The parent of the ATPerson metaclass is the NSObject metaclass (
0x7fff8079dfe0
) - The parent of the ATTeacher metaclass is the ATPerson metaclass
- The parent of the NSObject class is NULL
- The parent of the NSObject metaclass is the NSObject class (
0x7fff8079e008
)
Therefore, the following diagram can be obtained through inheritance analysis
conclusion
By analyzing objective-C classes from two different perspectives, isa orientation and inheritance chain to explore the class diagram, we combined the two situations into a diagram that is the class orientation diagram provided by Apple official documentation.
The isa of the class points to the metaclass, the ISA of the metaclass points to the root metaclass, and the ISA of the root metaclass points to itself. 2. From an inheritance perspective, subclasses point to the parent, and the parent points to the root class (NSObject). NSObject is nil; The subclass metaclass points to the parent metaclass, which points to the root metaclass, which points to the NSObject class.Copy the code