preface

We have gained a clearer understanding of ISA by exploring the underlying principles of iOS 04: EXPLORING the underlying Principles of ISA. This article will continue to explore the position of ISA.

What is a metaclass

First we define a Person, and then we debug with a breakpoint on the NSLog. (The following debugging is in the macOS environment if not specified)

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        
        Person *person = [Person alloc];
        NSLog(@"Hello, World!  %@",person);
    }
    return 0;
}
Copy the code
  • To enable LLDB debugging, perform the following steps
  • 1. Print in hexadecimal formatperson4 segments of memory:
(lldb) x/4gx person
0x1006c25a0: 0x001d8001000021c9 0x0000000000000000
0x1006c25b0: 0x75736956534e5b2d 0x6369506261546c61
Copy the code
  • 2. Add person’sisaandISA_MASKAnd operation, and print class information
#   define ISA_MASK        0x00007ffffffffff8ULL
Copy the code
(lldb) p/x 0x001d8001000021c9 & 0x00007ffffffffff8ULL
(unsigned long long) $2 = 0x00000001000021c8
(lldb) po 0x00000001000021c8
Person
Copy the code

From the exploration in the previous article, it is clear that the and operation in this step already fetches the class information for Person

  • 3, We print the memory status of Person:
(lldb) x/4gx 0x00000001000021c8 
0x1000021c8: 0x00000001000021a0 0x0000000100334140
0x1000021d8: 0x000000010032e410 0x0000801000000000
Copy the code
  • 4, will bePersontheisaISA_MASKAnd, and print the class information at this time:
(lldb) p/x 0x00000001000021a0 & 0x00007ffffffffff8ULL
(unsigned long long) $2 = 0x00000001000021a0
(lldb) po 0x00000001000021a0
Person
Copy the code

  • Through the above debugging process, we have a question: Why is the class information in p/x 0x001D8001000021C9&0x00007ffffffffff8ull and p/x 0x00000001000021A0&0x00007ffffffff8ull both printed as Person?

  • 0x001D8001000021C9 is the ISA pointer address of the Person object, and the ampersand results in the creation of person’s class person

  • 0x00000001000021A0 is the ISA pointer address of the class indicated by the class information obtained in ISA, that is, the ISA pointer address of the class of Person. In Apple, we refer to the class of Person as metaclass

So, the root reason why both prints are Person is because of metaclasses.

### description of metaclasses

  • The definition and creation of metaclasses are done automatically by the compiler

  • Metaclasses are classes of class objects, and all class methods, protocols, and so on belong to metaclasses.

  • 5, We continue to repeat the above steps:

(lldb) x/4gx 0x00000001000021a0 
0x1000021a0: 0x00000001003340f0 0x00000001003340f0
0x1000021b0: 0x000000010071fb80 0x0003e03100000007
(lldb) p/x 0x00000001003340f0 & 0x00007ffffffffff8ULL
(unsigned long long) $5 = 0x00000001003340f0
(lldb) po 0x00000001003340f0
NSObject
Copy the code

The printed class information is NSObject.

  • 6, continue to print the memory of NSObject:
(lldb) x/4gx 0x00000001003340f0 
0x1003340f0: 0x00000001003340f0 0x0000000100334140
0x100334100: 0x000000010062a050 0x0004e03100000007
Copy the code

The ISA 0x00000001003340F0 pointer address is now the same as the NSObject pointer address.

From the above exploration, we can draw a conclusion:

  • objectisaPoint to theclass(also called class object).
  • classisaPoint to theThe metaclass.
  • The metaclassisaPoint to theA metaclass, namely NSObject.
  • A metaclassisaPoint to theIts own.
  • Object –> class –> metaclass –> NSobject, NSobject points to itself.

How many copies of NSobject are there in the system?

As you can see from the exploration above, the last root metaclass is NSObject, is this NSObject the same as NSObject in our system? Here we verify it in two ways:

  • 1, LLDB command verification:
  • We proceed to the above verification, print systemThe first address of NSObject– > printNSObject Memory condition— >Isa and operation.

As can be seen from the figure, the last step aboveNSObjectOf the classThe metaclassIs alsoNSObject, and aboveThe root metaclass in Person(NSObject)The metaclass, it isThe sameSo we can get oneconclusion: memoryOnly one copy of the root metaclass existsNSObject,The metaclass of the root metaclassIs pointing to itoneself.

  • 2. Pass the code verification:
//MARK:-- Analyze the memory number of class objects
void testClassNum(){
    Class class1 = [Person class];
    Class class2 = [Person alloc].class;
    Class class3 = object_getClass([Person alloc]);
    NSLog(@"\n%p-\n%p-\n%p-", class1, class2, class3);
}
Copy the code

As you can see from the print, printedIt's all the same address, soThere is only one copy of NSObject in memory.

Isa bitmap

Solid lines aresuper_classPointer, dotted line isisaPointer. ###isa points to:

  • 1, The isa of an Instance of Subclass refers to the class.

  • Class isa refers to a Meta class.

  • 3, Meta class isa pointing to Root metal class

The ISA of the Root metal class points to itself, forming a closed loop, where the Root metaclass is NSObject

### Superclass:

  • 1.subClassInherited fromsuperClass
  • 2,superClassInherited fromRootClass, where the root class refers toNSObject
  • 3,The root classInherits from nil, so the root class NSObject can be understood asOrigin of all things

Metaclass inheritance:

  • 1.SubClass metaclass (Metal SubClass)Inherited fromSuperClass (metal SuperClass)
  • 2,SuperClass (metal SuperClass)Inherited fromRoot metal Class
  • 3, rootRoot Metal ClassInheritance inRoot classIn which case the root class is NSObject

The above content is the isa exploration process, this finally clear ISA pointer and class is how to associate, also clear ISA go bitmap process, ISA, I understand you!