preface
In the previous study, we already know that the ISA pointer of the class finds a class that is exactly the same as the class through the &mask mask, but the addresses of the two classes are different. Later, through exploration, we know that the class is actually automatically generated by the system, which is also a metaclass. So what is the meaning of the existence of metaclass? This is where the main discussion will focus.
WWDC about class dirty Meomory and Clean Memory
As shown in figure: The binary representation of a class includes the metaclass, the superclass, flags,methodCache, and of course the class itself. The class object itself contains Pointers to the metaclass, the superclass, the methodCache, and also Pointers to a piece of clean Memory, ro. This information cannot be modified.
The opposite is dirty Meomory. Rw is to dynamically modify the contents of a class at runtime. This part exists along with the program running, and when a class starts to be used, the system will automatically allocate this memory capacity for reading and writing.
First Subclass, Next Sibling Class: All classes are connected into a tree structure, allowing you to facilitate all classes used at runtime.
Methods, Properties, Protocols: Allows you to dynamically change Methods and Properties (classifications) at runtime.
Demangled Name: Since Swift and OC share this structure, only SWIFT will use this field and will only use it when asking for the OC Name.
The Methods, Properties, Protocols and Demangled names are rarely used in daily use, so Apple optimized this part to make room for more dirty addresses and created a separate structure for the extension (ext_T).
The problem of legacy
Question 1:
There are two classes, LGTearcher inherits LGPerson, but there is no LGTeacher found in firstSubclass when printing the LGPerson information.
Solution:
After calling lgteacher.class, you can print out.
The reason:
Class calls are lazy loads.
Question 2:
Class member variables are not printed
Analysis:
Member variables are read-only and are not in the properties method
Solution:
The implementation was found by searching the RO method.
The: ro() method is called
Supplementary Printing of the agreement
To summarize the fetching of data from a class:We get properties from the.properties() method, object methods from the ro() method, and.methods() method from the big function because it does not implement the print description method
The essential difference between member variables and attributes
By compiling the CPP file against clang, you can see that the underlying set and get methods have been generated for the properties.
Extension:
For special symbols, see ivar_getTypeEncoding to obtain typeEncoding, first attach the official document address: typeEncoding
V: return null (you can see that the method is set)
@ : id (you can see the current get method, returned by the value) 16/24: indicates the total number of bytes used
@ : Parameter id self
0: Starts from position 0
: : SEL
8: Start at position 8
16 is equal to 8 plus 8
24 is 16 plus 8
The structure of the class
The problem
In the compiled CPP file, we find that the properties are either the objc_setProperty method or the memory shift, which means they are implemented differently.
Think about:
Oc will find the corresponding set and get methods based on your property, but how to generate the corresponding set and get methods from the defined property? At the top level, set is an assignment, and get is a value. At the bottom level, both set and GET are based on CMD methods, but with different names, so they can be encapsulated uniformly. However, there is no direct communication from the upper layer to the bottom layer. In my personal understanding, a middle layer is needed to process the data of the upper layer well for the use of the lower layer, which is similar to unified processing with a general method. When the class is loaded, it can generate IVars and find the IMP based on the SEL of ivars. However, the IMP has not been implemented yet, so currently oc uses objc_setProperty redirection. Combined with some of the most open classification knowledge can know, now our assignment operation does not change this class, so objc_setProperty nature also won’t produce at run time, on the other hand, if at runtime to operating the system pressure is too large (objc source), and if you haven’t achieved, then to look up at runtime error prone, It’s not so easy to find out how. Therefore, we can find out the underlying implementation principle of LLVM by searching for it.
Approach:
Step 1: Once LLVM is opened, the method to generate it is found according to objc_setProperty
Step 2: Look from the bottom up, where did this method get called to create this Runtime objc_setProperty method? Global search getSetPropertyFn, look for GetPropertySetFunction method call, just do the middle jump, don’t worry about it, search for GetPropertySetFunction method. Now we know that this method was called somewhere else and that the global search for getSetPropertyFn is going to happen, but in which case it’s called, we don’t know what’s going on at the top, so all we need to know is the processing logic at the top.
The third step: Along the GetPropertySetFunction method, we can find the basis of the call judgment, such as native, GetSetProperty, etc., guess that different judgments may go through different property or member variable assignment process. Now you just need to find the basis for assigning the judgment.
Step 4: According to the PropertyImplStrategy to find its assignment and definition, you can see that when copy is determined to add methods, and it is the default, you can guess that the copy keyword will affect whether the GetSetProperty method will be called.
Methods of a class
Question 1:
In previous explorations, printouts of class methods were still missing.
Think about:
Methods are different from member variables. Methods are stored in the class to prevent the instantiation of objects from wasting memory by creating duplicate methods. Similarly, all class methods are stored in the metaclass to avoid wasting memory.
Methods a
After the LLDB print verification, there is no map.
Method 2
Print through API
Methods three
Rotten apple check
Question 2:
Class object methods can be found in the class, the class of the class method is a metaclass object method, a class of class method with the object remains the same name will not have a problem, so the print method of classes and metaclass list, the object of the class is no method metaclass, class of methods is to print out in class, why “method” in the metaclass can still be metaclass found?
To solve
Through the simple analysis of the underlying code, it is found that the process of getting a class method is to get an object method of the metaclass. Click in, the system has a judgment, if it is a metaclass, it will return directly, that is to say, the metaclass can directly view its own class method. Having said that, basically,At the bottom level there is no concept of classes or objects, it’s all object methodsIt just depends on where you get it from. If it’s a class, you can only get it from a metaclass. If it’s a metaclass, you can get it from itself.
Supplementary note
1. When obtaining bits data for strong rotation, pay attention to the shift of 32 bits; otherwise, there is a problem with the strongly rotated data. There is a problem with the count print. 2. When you print the address of the metaclass, it is often found that the address of the class isa is the same, but the OBJECT ISA is different from the class ISA. Isa internally stores class information + other information, reference counts, weak tables, etc. The latter are objects that do not exist for classes, so the ISA address of a class is the same as the address of a metaclass.
Afterword.
First time to write, hope to put forward valuable advice, mutual supervision, study together. Thank you! In addition, I have a bold idea, that is to put co someone by the throat ~~