A peek into the underlying implementation of iOS — the nature of OC objects (I) — Digging gold

A peek into the underlying implementation of iOS — the nature of OC objects (II) — Digging gold

Look at the underlying implementation of iOS –OC object classification: instance, class, META -calss object ISA and Superclass – nuggets

A peek into the underlying implementation of iOS — the essence of KVO/KVC — nuggets

Summary of iOS underlying principles – Using Runtime source code to analyze the low-level implementation of categories

.

Question: How much memory does an NSObject take up?

int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc]init];
        /// How much memory do obj objects take up?}}return 0;

Copy the code

The essence of Objective-C

Most of the objective-C code we write, the underlying implementation is c /C++ code.

So objective-C object orientation is implemented based on C/C++ data structures.

Question to consider: Objective-C objects, classes are mainly based on C\C++ based on what data structure?

/ / / > Student class
@interface Student: NSObject{
 @public
    int _no;
    int _age;
}
@end
@implementation Student

@end

int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc]init];
        /// How much memory do obj objects take up?}}return 0;
Copy the code

If objective-C objects are converted to C/C++ code, they are actually converted to C/C++ bodies.

So how do we convert OC code to C/C++ code?

  1. The terminal enters the program directory:

  2. Input command line

    Xcrun-sdk iphoneOS clang-arch arm64-rewrite-objc OC source file -o CPP file eg: xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cppCopy the code
  3. It then generates a main-arm64.cpp file which is our C/C++ implementation.

  4. If you need to link to other frameworks, use the -framework argument. For example – framework UIKit

  5. Search for NSObject_IMPL in generate main-arm64.cpp

    • NSObject_IMPL: NSObject Implementation
    • NSObject is actually in memory
///> NSObject_IMPL
struct NSObject_IMPL {
    Class isa; /// isa
};
Copy the code

The underlying implementation structure diagram for NSObject

The figure above actually has an ISA pointer in NSObject, and the ISA pointer takes up 8 bytes on a 64-bit system, and 4 bytes on a 32-bit system, which is currently the 64-bit system, so in our NSObject the ISA pointer takes up 8 bytes. The internal implementation of CLass isa isa structure.

  /// class is a pointer to a structure
  typedef struct objc_class *Class 
  
Copy the code
/// Create and allocate storage space
NSObject *obj = [[NSObject alloc]init];
Copy the code

Let’s say we allocate a block of storage for our NSObject object, and let’s say the next eight bytes, and within those eight bytes we just put the ISA pointer, and let’s say our ISA address is 0x100400110, and that ISA address is the address of the structure. So the address of obj is 0x100400110.

Memory occupied by NSObject

#import <malloc/malloc.h>
#import <OBJC/runtime.h>
///> main
int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc]init];
        ///> Get the size of the instance object of the NSObject class
        NSLog(@"%zd", class_getInstanceSize([NSObject class]));
        ///> get the size of the obj pointer to memory
        NSLog(@"%zd", malloc_size((__bridge const void *)obj));        
        
        
        /** The output is 8 16 */ 
    }
    return 0;
}
Copy the code
  • First we use the Runtime class_getInstanceSize() method to check the size of the instance object of the NSObject class

    • The incoming class
    • Note: for Instance Instance, return a class Instance size that occupies 8 memory space
  • Then we use the malloc_size method to check that the obj pointer to memory is 16;

    • Pass in a pointer to obj (error message and say bridge is ok (__bridge const void *))

Malloc_size = 16 malloc_size = 16 malloc_size = 16 malloc_size = 16 malloc_size = 16 malloc_size = 16 malloc_size = 16

  • How much memory does an NSObject take up?
    • The system allocates 16 bytes to the NSObject object (obtained by the malloc_size function)
    • But the NSObject object uses only 8 bytes of space internally (available in 64-bit environments via the class_getInstanceSize function)

Custom memory used by NSObject

#import <malloc/malloc.h>
#import <OBJC/runtime.h>
/ / / > Student class
@interface Student: NSObject{
    @public
    int _no;
    int _age;
}

///> The actual underlying structure structure
//struct Student_IMPL{
// Class isa,
// int _no,
// int _age;
/ /}
@end

@implementation Student
@end

///> main
int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc]init];
        Student *stu = [[Student alloc]init];
        stu->_no = 4;
        stu->_age = 5;
        NSLog(@"no:%d, age:%d",stu->_no, stu->_age);
        NSLog(@"%zd", class_getInstanceSize([Student class]));
        NSLog(@"%zd", malloc_size((__bridge const void *)stu));        
        
        /** No :4, age:5 16 16 */ 
    }
    return 0;
}
Copy the code
  • When we customize an NSObject we actually have three underlying member variables, isa pointer takes 8 bytes, _no takes 4 bytes and _age really takes 4 bytes, so we end up with 16,16

Consider: if my Student has three member variables, how many bytes will it take?

What is the output of class_getInstanceSize([Student class])?

Malloc_size ((__bridge const void *) what is the output of stu?

#import <malloc/malloc.h>
#import <OBJC/runtime.h>
/ / / > Student class
@interface Student: NSObject{
    @public
    int _no;
    int _age;
    int _gender;
}

///> The actual underlying structure structure
//struct Student_IMPL{
// Class isa,
// int _no,
// int _age;
// int _gender;

/ /}
@end

@implementation Student
@end

///> main
int main(int argc, char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc]init];
        Student *stu = [[Student alloc]init];
        stu->_no = 4;
        stu->_age = 5;
        stu->_gender = 0;
        NSLog(@"%zd", class_getInstanceSize([Student class]));
        NSLog(@"%zd", malloc_size((__bridge const void *)stu));        
        
        24 32 */ is displayed 
    }
    return 0;
}
Copy the code
  • The heaviest output is:
    • Class_getInstanceSize: 24
    • Malloc_size: 32

Isa: occupies 8 bytes, _no: occupies 4 bytes, _age: occupies 4 bytes, _gender: occupies 4 bytes. Why 24?

Why 24 and 32 ???? A peek into the underlying implementation of iOS — the nature of OC objects (II) — Digging gold


  • The article is summarized from MJ teacher’s bottom video.