Objc – init analysis
A number of methods are called respectively:
environ_init()
: Reads environment variables that affect the runtime. You can also print environment variable help if desired.tls_init()
: bindings for thread keys – such as destructors for per-thread datastatic_init()
: Runs the C ++ static constructor. Libc calls _objc_init () before DYLD calls our static constructor, so we have to do it ourselveslock_init()
: no rewrite, using C++ featuresexception_init()
Initialize libobJC’s exception handling systemcache_init()
: Initializes the cache conditionruntime_init()
: the runtime runtime environment initialization, it mainly: unattachedCategories, allocatedClasses later analysis_imp_implementationWithBlock_init
: Enables the callback mechanism. Normally that doesn’t do anything, because all the initializations, right
Is lazy, but for some processes we can’t wait to load trampolines dylib.
environ_init(); Read environment variables that affect the runtime. You can also print environment variable help if desired.
-
- Enter the
void environ_init(void)
The source code to view
- Enter the
void environ_init(void)
{...// This code is a copy of the following code, while removing the judgment. After the operation.
for (size_t i = 0; i < sizeof(Settings)/sizeof(Settings[0]); i++) {
const option_t *opt = &Settings[i];
_objc_inform("%s: %s", opt->env, opt->help);
_objc_inform("%s is set", opt->env); }...// Print OBJC_HELP and OBJC_PRINT_OPTIONS output.
if (PrintHelp || PrintOptions) {
if (PrintHelp) {
_objc_inform("Objective-C runtime debugging. Set variable=YES to enable.");
_objc_inform("OBJC_HELP: describe available environment variables");
if (PrintOptions) {
_objc_inform("OBJC_HELP is set");
}
_objc_inform("OBJC_PRINT_OPTIONS: list which options are set");
}
if (PrintOptions) {
_objc_inform("OBJC_PRINT_OPTIONS is set");
}
for (size_t i = 0; i < sizeof(Settings)/sizeof(Settings[0]); i++) {
const option_t *opt = &Settings[i];
if (PrintHelp) _objc_inform("%s: %s", opt->env, opt->help);
if (PrintOptions && *opt->var) _objc_inform("%s is set", opt->env); }}... }Copy the code
- There will be a lot of data printing, and there will be this OBJC_DISABLE_NONPOINTER_ISA is set
- OBJC_DISABLE_NONPOINTER_ISA is set This is the first value of isA-union.
- Test the difference between this setting and not setting it
- 1. Create an object and set a breakpoint
- 2. X /4gx p Displays the memory address of the object, and outputs 4 segments in the form of 8 bytes
- 3. P /t 0x011D8001000082D1 Displays the first ADDRESS of the ISA of the p object in base 2
- Modifying environment Variables
- Print run
- No OBJC_DISABLE_NONPOINTER_ISA is set prints at the end of P’s ISA, indicating that the ISA – isa pure ISA and is no longer a union
- So let’s test this JC_PRINT_LOAD_METHODS, check it.
- The load method wastes performance.
- Print out which classes call the load method.
- You can optimize this class.
- Now it turns out that a lot of things can be done with this environment variable setting. Now I want to know what other variable Settings are, but sometimes I don’t know what they are.
- 1. Open the terminal
- 2. First instruction
export OBJC_HELP=1
- 3. Second instruction
/Applications/Safari.app/Contents/MacOS/Safari
- Enter and there will be a lot of print environment variable Settings and comments
Objective-C runtime debugging. Set variable=YES to enable.
objc[1591]: OBJC_HELP: describe available environment variables
objc[1591]: OBJC_PRINT_OPTIONS: list which options are set
objc[1591]: OBJC_PRINT_IMAGES: log image and library names as they are loaded
objc[1591]: OBJC_PRINT_IMAGE_TIMES: measure duration of image loading steps
objc[1591]: OBJC_PRINT_LOAD_METHODS: log calls to class and category +load methods
objc[1591]: OBJC_PRINT_INITIALIZE_METHODS: log calls to class +initialize methods
objc[1591]: OBJC_PRINT_RESOLVED_METHODS: log methods created by +resolveClassMethod: and +resolveInstanceMethod:
objc[1591]: OBJC_PRINT_CLASS_SETUP: log progress of class and category setup
objc[1591]: OBJC_PRINT_PROTOCOL_SETUP: log progress of protocol setup
objc[1591]: OBJC_PRINT_IVAR_SETUP: log processing of non-fragile ivars
objc[1591]: OBJC_PRINT_VTABLE_SETUP: log processing of class vtables
objc[1591]: OBJC_PRINT_VTABLE_IMAGES: print vtable images showing overridden methods
objc[1591]: OBJC_PRINT_CACHE_SETUP: log processing of method caches
objc[1591]: OBJC_PRINT_FUTURE_CLASSES: log use of future classes for toll-free bridging
objc[1591]: OBJC_PRINT_PREOPTIMIZATION: log preoptimization courtesy of dyld shared cache
objc[1591]: OBJC_PRINT_CXX_CTORS: log calls to C++ ctors and dtors for instance variables
objc[1591]: OBJC_PRINT_EXCEPTIONS: log exception handling
objc[1591]: OBJC_PRINT_EXCEPTION_THROW: log backtrace of every objc_exception_throw()
objc[1591]: OBJC_PRINT_ALT_HANDLERS: log processing of exception alt handlers
objc[1591]: OBJC_PRINT_REPLACED_METHODS: log methods replaced by category implementations
objc[1591]: OBJC_PRINT_DEPRECATION_WARNINGS: warn about calls to deprecated runtime functions
objc[1591]: OBJC_PRINT_POOL_HIGHWATER: log high-water marks for autorelease pools
objc[1591]: OBJC_PRINT_CUSTOM_CORE: log classes with custom core methods
objc[1591]: OBJC_PRINT_CUSTOM_RR: log classes with custom retain/release methods
objc[1591]: OBJC_PRINT_CUSTOM_AWZ: log classes with custom allocWithZone methods
objc[1591]: OBJC_PRINT_RAW_ISA: log classes that require raw pointer isa fields
objc[1591]: OBJC_DEBUG_UNLOAD: warn about poorly-behaving bundles when unloaded
objc[1591]: OBJC_DEBUG_FRAGILE_SUPERCLASSES: warn about subclasses that may have been broken by subsequent changes to superclasses
objc[1591]: OBJC_DEBUG_NIL_SYNC: warn about @synchronized(nil), which does no synchronization
objc[1591]: OBJC_DEBUG_NONFRAGILE_IVARS: capriciously rearrange non-fragile ivars
objc[1591]: OBJC_DEBUG_ALT_HANDLERS: record more info about bad alt handler use
objc[1591]: OBJC_DEBUG_MISSING_POOLS: warn about autorelease with no pool in place, which may be a leak
objc[1591]: OBJC_DEBUG_POOL_ALLOCATION: halt when autorelease pools are popped out of order, and allow heap debuggers to track autorelease pools
objc[1591]: OBJC_DEBUG_DUPLICATE_CLASSES: halt when multiple classes with the same name are present
objc[1591]: OBJC_DEBUG_DONT_CRASH: halt the process by exiting instead of crashing
objc[1591]: OBJC_DEBUG_POOL_DEPTH: log fault when at least a set number of autorelease pages has been allocated
objc[1591]: OBJC_DEBUG_SCRIBBLE_CACHES: scribble the IMPs in freed method caches
objc[1591]: OBJC_DISABLE_VTABLES: disable vtable dispatch
objc[1591]: OBJC_DISABLE_PREOPTIMIZATION: disable preoptimization courtesy of dyld shared cache
objc[1591]: OBJC_DISABLE_TAGGED_POINTERS: disable tagged pointer optimization of NSNumber et al.
objc[1591]: OBJC_DISABLE_TAG_OBFUSCATION: disable obfuscation of tagged pointers
objc[1591]: OBJC_DISABLE_NONPOINTER_ISA: disable non-pointer isa fields
objc[1591]: OBJC_DISABLE_INITIALIZE_FORK_SAFETY: disable safety checks for +initialize after fork
objc[1591]: OBJC_DISABLE_FAULTS: disable os faults
objc[1591]: OBJC_DISABLE_PREOPTIMIZED_CACHES: disable preoptimized caches
objc[1591]: OBJC_DISABLE_AUTORELEASE_COALESCING: disable coalescing of autorelease pool pointers
objc[1591]: OBJC_DISABLE_AUTORELEASE_COALESCING_LRU: disable coalescing of autorelease pool pointers using look back N strategy
Copy the code
The variable name | introduce | note |
---|---|---|
OBJC_PRINT_OPTIONS | list which options are set | Prints OBJC’s set options |
OBJC_PRINT_IMAGES | log image and library names as they are loaded | The loaded image information is displayed |
OBJC_PRINT_LOAD_METHODS | log calls to class and category +load methods | Prints calls to the + (void)load methods of Class and Category |
OBJC_PRINT_INITIALIZE_METHODS | log calls to class +initialize methods | Print the call information for Class + (void)initialize |
OBJC_PRINT_RESOLVED_METHODS | log methods created by +resolveClassMethod and +resolveInstanceMethod: | Print class methods generated by +resolveClassMethod: or +resolveInstanceMethod: |
OBJC_PRINT_CLASS_SETUP | log progress of class and category setup | Print the Class and Category Settings |
OBJC_PRINT_PROTOCOL_SETUP | log progress of protocol setup | Prints the Protocol setting process |
OBJC_PRINT_IVAR_SETUP | log processing of non-fragile ivars | The Ivar setup process is displayed |
OBJC_PRINT_VTABLE_SETUP | log processing of class vtables | Print the vtable setting process |
OBJC_PRINT_VTABLE_IMAGES | print vtable images showing overridden methods | Print the method of overwriting vtable |
OBJC_PRINT_CACHE_SETUP | log processing of method caches | Print the procedure for setting up the method cache |
OBJC_PRINT_FUTURE_CLASSES | log use of future classes for toll-free bridging | Print classes that will be used for seamless conversion from CFType to NSObject (such as CFArrayRef to NSArray *) |
OBJC_PRINT_GC | log some GC operations | Print some garbage collection operations |
OBJC_PRINT_PREOPTIMIZATION | log preoptimization courtesy of dyld shared cache | Print the greeting before dyLD shared cache optimization |
OBJC_PRINT_CXX_CTORS | log calls to C++ ctors and dtors for instance variables | Print the construction and destructor calls of C++ objects in class instances |
OBJC_PRINT_EXCEPTIONS | log exception handling | Printing exception Processing |
OBJC_PRINT_EXCEPTION_THROW | log backtrace of every objc_exception_throw() | Prints Backtrace for all exceptions thrown |
OBJC_PRINT_ALT_HANDLERS | log processing of exception alt handlers | Abnormal processing of Alt operations |
OBJC_PRINT_REPLACED_METHODS | log methods replaced by category implementations | Print the method to be replaced by Category |
OBJC_PRINT_DEPRECATION_WARNINGS | warn about calls to deprecated runtime functions | Prints all obsolete method calls |
OBJC_PRINT_POOL_HIGHWATER | log high-water marks for autorelease pools | Prints autoreleasepool high watermark warnings |
OBJC_PRINT_CUSTOM_RR | log classes with un-optimized custom retain/release methods | Prints a class with a custom retain/release method that is not optimized |
OBJC_PRINT_CUSTOM_AWZ | log classes with un-optimized custom allocWithZone methods | Prints a class with a custom allocWithZone method that is not optimized |
OBJC_PRINT_RAW_ISA | log classes that require raw pointer isa fields | Print the classes that need access to the original ISA pointer |
OBJC_DEBUG_UNLOAD | warn about poorly-behaving bundles when unloaded | Prints a warning when uninstalling misbehaving bundles |
OBJC_DEBUG_FRAGILE_SUPERCLASSES | warn about subclasses that may have been broken by subsequent changes to superclasses | Prints a warning when a subclass may be broken by changes to its parent class |
OBJC_DEBUG_FINALIZERS | warn about classes that implement -dealloc but not -finalize | Warning implements -dealloc but not -Finalize classes |
OBJC_DEBUG_NIL_SYNC | warn about @synchronized(nil), which does no synchronization | Warning of @synchronized(nil) calls that do not lock |
OBJC_DEBUG_NONFRAGILE_IVARS | capriciously rearrange non-fragile ivars | Prints the behavior of suddenly rearranging non-fragile ivars |
OBJC_DEBUG_ALT_HANDLERS | record more info about bad alt handler use | Record more Alt operation errors |
OBJC_DEBUG_MISSING_POOLS | warn about autorelease with no pool in place, which may be a leak | Warning: Using autoRelease without a pool may leak memory |
OBJC_DEBUG_DUPLICATE_CLASSES | halt when multiple classes with the same name are present | Stop when a class duplication occurs |
OBJC_USE_INTERNAL_ZONE | allocate runtime data in a dedicated malloc zone | Allocate runtime data in a dedicated MALloc area |
OBJC_DISABLE_GC | force GC OFF, even if the executable wants it on | Forcibly turn off automatic garbage collection, even if the executable requires garbage collection |
OBJC_DISABLE_VTABLES | disable vtable dispatch | Disable VTable distribution |
OBJC_DISABLE_PREOPTIMIZATION | disable preoptimization courtesy of dyld shared cache | Disable the greeting before dyLD shared cache optimization |
OBJC_DISABLE_TAGGED_POINTERS | disable tagged pointer optimization of NSNumber et al. | Disable tagged Pointer optimization for NSNumber |
OBJC_DISABLE_NONPOINTER_ISA | disable non-pointer isa fields | Disable access to the non-pointer ISA field |
- The above instructions are used for debugging (understand)
tls_init(); Bindings for thread keys, such as destructors for each thread’s data
- Such as the per-thread destructor (not explained here)
static_init();
- Run the C++ static destructor. Before DYLD calls our static constructor,
linc
Will be called_objc_init()
So we have to do it ourselves
/*********************************************************************** * static_init * Run C++ static constructor functions. * libc calls _objc_init() before dyld would call our static constructors, * static_init * run c++ static constructors. * Libc calls _objc_init() before dyld calls the static constructor, * so we have to do it ourselves. Dyldy will automatically call our library's global static functions, such as: __attribute__((constructor)) static void libSystem_initializer static_init() We call dyly's static methods in our library ourselves after _objc_init(). * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
static void static_init(a)
{
size_t count;
auto inits = getLibobjcInitializers(&_mh_dylib_header, &count);
for (size_t i = 0; i < count; i++) {
inits[i]();
}
auto offsets = getLibobjcInitializerOffsets(&_mh_dylib_header, &count);
for (size_t i = 0; i < count; i++) {
UnsignedInitializer init(offsets[i]);
init();
}
}
Copy the code
- A global static function was actively called, i.e
__attribute__((constructor)) void objcFunc(a){
printf("Coming: %s \n",__func__);
}
Copy the code
The function written this way will be called actively, and then
__attribute__((constructor))
static void
libSystem_initializer(int argc,
const char* argv[],
const char* envp[],
const char* apple[],
const struct ProgramVars* vars){}Copy the code
-
I call this method on my own initiative.
-
_dyLD_OBJC_notify_register (&map_images, load_images, unmap_image); Ensure that all global static functions are called before the function is called.
runtime_init();
- The runtime runtime environment initialization, it mainly: unattachedCategories, allocatedClasses later analysis
- Initialize two tables
unattachedCategories
.allocatedClasses
exception_init(); Initialize the exception handling system for lib_objc
- Exception listening initialization (ignored for now)
/*********************************************************************** * exception_init * Initialize libobjc's Exception handling system. * Called by map_images(). * Exception_init Initializes libobJC's exception handling system. * called by map_images(). * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
void exception_init(void)
{
old_terminate = std::set_terminate(&_objc_terminate);
}
Copy the code
Cache_init () Initializes the cache condition
_imp_implementationWithBlock_init: Enables the callback mechanism. Usually this doesn’t do much, because all initialization is lazy, but for some processes we can’t wait to load trampolines dylib
points
- Focus on
_dyld_objc_notify_register(&map_images, load_images, unmap_image); Analysis of the
map_images()
dyld
willimage
This function is called when the image file is loaded into memory.load_images()
dyld
Initialize allimage
The image file file is called.unmap_image
Will:image
Called when the image file is removed.
Load_images calls load, map_image, &map_images is a pointer pass that points to the address of the same block. If there is any change, you can know it immediately. The place in DYLD where sNotifyObjCMapped is called is in the notifyBatchPartial method. The notifyBatchPartial method is called in the registerObjCNotifiers when objC initializes the registration notification. So map_images is called and load_images is called.
- &map_images Address values as parameters, i.e., Pointers passed, data synchronized for change. The map_images function is a recursive function
Map_images function analysis
/*********************************************************************** * map_images * Process the given images which are being mapped in by dyld. * Calls ABI-agnostic code after taking ABI-specific locks. * * Locking: Write-locks runtimeLock * map_images * processes the given image mapped by dyLD. Map image files * invoke ABI agnostic code after acquiring an ABI specific lock. * * lock: write lock runtimeLock * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
void
map_images(unsigned count, const char * const paths[],
const struct mach_header * const mhdrs[])
{
mutex_locker_t lock(runtimeLock);
return map_images_nolock(count, paths, mhdrs);
}
Copy the code
- Map_images_nolock due to excessive code…
map_images_nolock(unsigned mhCount, const char * const mhPaths[],
const struct mach_header * const mhdrs[]){
...
// focus on the loop to start reading the image file
if (hCount > 0) { _read_images(hList, hCount, totalClasses, unoptimizedTotalClasses); }... }Copy the code
The read_images function analysis mainly accomplishes the following functions
- 1, condition control for a load
- 2. Fix ‘@selector’ confusion during precompilation
- 3. Bad, messy class handling
- 4, fix remapping some classes that were not loaded by the image file
- 5. Fix some messages
- 6. When there is a protocol in our class: readProtocol
- 7, fix the protocol that was not loaded
- 8. Classification
- 9. Class loading processing
- 10. Unprocessed classes optimize those that are violated
1. Condition control to load doneOnce
if(! doneOnce) { doneOnce = YES; launchTime = YES; . .// namedClasses
// Preoptimized classes don't go in this table.
// 4/3 is NXMapTable's load factor
// objc::unattachedCategories.init(32);
// objc::allocatedClasses.init(); // generate a table where alloc is opened.
int namedClassesSize =
(isPreoptimized()? unoptimizedTotalClasses : totalClasses) *4 / 3;
// Create a table (total table table of class names, whether implemented or not)
gdb_objc_realized_classes =
NXCreateMapTable(NXStrValueMapPrototype, namedClassesSize);
ts.log("IMAGE TIMES: first time tasks");
}
Copy the code
- Load once and you will not enter the judgment again, the first time in the main create table
gbd_objc_realized_classes
This is a list of all classes that are stored in whether they are implemented or not. It’s a master list. - The main function is to generate a summary table of all class names, whether or not the class is implemented
alloc init
allocatedClass.init()
, generates a table that has been allocated memory.
2. Fix ‘@selector’ confusion during precompilation
// Fix up @selector references
// sel name + address
static size_t UnfixedSelectors;
{
mutex_locker_t lock(selLock);
for (EACH_HEADER) {
if (hi->hasPreoptimizedSelectors()) continue;
bool isBundle = hi->isBundle(a); SEL *sels = _getObjc2SelectorRefs(hi, &count); UnfixedSelectors += count;for (i = 0; i < count; i++) {
const char *name = sel_cname(sels[i]);
SEL sel = sel_registerNameNoLock(name, isBundle);
if(sels[i] ! = sel) { sels[i] = sel; }}}}Copy the code
- The same method may exist in different classes, but the method name and address are different.
- For example, if two methods have the same name but different addresses, local processing is required. Class address redirection.
Sels [I] is _getObjc2SelectorRefs obtained from MachO, MachO has relative displacement address and offset address, sel is sel_registerNameNoLock obtained from dyLD, dyLD is linked to the whole program, so the DYLD is subject. Because methods are stored in classes, the location of each class is different, so the address of the method is different, and the messy methods must be fixed.
3. Bad, messy class handling
// Discover classes. Fix up unresolved future classes. Mark bundle classes.
// Discover class. Fix unresolved future classes. Mark package class.
bool hasDyldRoots = dyld_shared_cache_some_image_overridden(a);for (EACH_HEADER) {
if (! mustReadClasses(hi, hasDyldRoots)) {
// Image is sufficiently optimized that we need not call readClass()
continue;
}
classref_t const *classlist = _getObjc2ClassList(hi, &count);
bool headerIsBundle = hi->isBundle(a);bool headerIsPreoptimized = hi->hasPreoptimizedClasses(a);for (i = 0; i < count; i++) {
Class cls = (Class)classlist[i];
Class newCls = readClass(cls, headerIsBundle, headerIsPreoptimized);
if(newCls ! = cls && newCls) {// Class was moved but not deleted. Currently this occurs
// only when the new class resolved a future class.
// Non-lazily realize the class below.
resolvedFutureClasses = (Class *)
realloc(resolvedFutureClasses,
(resolvedFutureClassCount+1) * sizeof(Class));
resolvedFutureClasses[resolvedFutureClassCount++] = newCls;
}
}
}
ts.log("IMAGE TIMES: discover classes");
Copy the code
- Clear classes that are not cleaned up
- Class address read load.
- The readClass method associates the class name with the address.
Now let’s look at how our own classes are loaded
/*********************************************************************** * readClass * Read a class and metaclass as written by a compiler. * Returns the new class pointer. This could be: * - cls * - nil (cls has a missing weak-linked superclass) * - something else (space for this class was reserved by a future class) * * Note that all work performed by this function is preflighted by * mustReadClasses(). Do not change this function without updating that one. * * Locking: runtimeLock acquired by map_images or objc_readClassPair * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
Class readClass(Class cls, bool headerIsBundle, bool headerIsPreoptimized)
{
// Get the class name
const char *mangledName = cls->nonlazyMangledName(a);const char *LGPersonName = "LGPerson";
if (strcmp(mangledName, LGPersonName) == 0) {
// How does he write in general
printf("% s-KC: To study: - %s\n",__func__,mangledName);
}
if (missingWeakSuperclass(cls)) {
// No superclass (probably weak-linked).
// Disavow any knowledge of this subclass.
if (PrintConnecting) {
_objc_inform("CLASS: IGNORING class '%s' with "
"missing weak-linked superclass",
cls->nameForLogging());
}
addRemappedClass(cls, nil);
cls->setSuperclass(nil);
return nil;
}
cls->fixupBackwardDeployingStableSwift(a); Class replacing = nil;if(mangledName ! =nullptr) {
if (Class newCls = popFutureNamedClass(mangledName)) {
// This name was previously allocated as a future class.
// Copy objc_class to future class's struct.
// Preserve future's rw data block.
if (newCls->isAnySwift()) {
_objc_fatal("Can't complete future class request for '%s' "
"because the real class is too big.",
cls->nameForLogging());
}
class_rw_t *rw = newCls->data(a);const class_ro_t *old_ro = rw->ro(a);memcpy(newCls, cls, sizeof(objc_class));
// Manually set address-discriminated ptrauthed fields
// so that newCls gets the correct signatures.
newCls->setSuperclass(cls->getSuperclass());
newCls->initIsa(cls->getIsa());
rw->set_ro((class_ro_t *)newCls->data());
newCls->setData(rw);
freeIfMutable((char *)old_ro->getName());
free((void *)old_ro);
addRemappedClass(cls, newCls); replacing = cls; cls = newCls; }}if(headerIsPreoptimized && ! replacing) {// class list built in shared cache
// fixme strict assert doesn't work because of duplicates
// ASSERT(cls == getClass(name));
ASSERT(mangledName == nullptr || getClassExceptSomeSwift(mangledName));
} else {
if (mangledName) { //some Swift generic classes can lazily generate their names
addNamedClass(cls, mangledName, replacing);
} else {
Class meta = cls->ISA(a);const class_ro_t *metaRO = meta->bits.safe_ro(a);ASSERT(metaRO->getNonMetaclass() && "Metaclass with lazy name must have a pointer to the corresponding nonmetaclass.");
ASSERT(metaRO->getNonMetaclass() == cls && "Metaclass nonmetaclass pointer must equal the original class.");
}
addClassTableEntry(cls);
}
// for future reference: shared cache never contains MH_BUNDLEs
if (headerIsBundle) {
cls->data()->flags |= RO_FROM_BUNDLE;
cls->ISA() - >data()->flags |= RO_FROM_BUNDLE;
}
return cls;
}
Copy the code
- 1. Breakpoint before self-written classes are created.
- 2. Write statements to judge printing and breakpoint
const char *LGPersonName = "LGPerson";
if (strcmp(mangledName, LGPersonName) == 0) {
// How does he write in general
printf("% s-KC: To study: - %s\n",__func__,mangledName);
}
Copy the code
- 3. Print information
Class Loading process
- 1.
readClass
NonlazyMangleName = nonlazyMangleName = nonlazyMangleName - 2.
addNameClass(cls,magleName,replacing)
-> Associate the type and address - 3.
addClassTableEntry(cls)
, where the classes and metaclasses are loadedinset(cls)
和addMeta
- The main thing that is done here is to add the class to the table, and to insert the class and metaclass of this class name into another hash table. The classes in this table are all initialized classes
realizeClassWithoutSwift(cls, nil); Analysis process of
- MethodelizeClass () collates related methods
- PrepareMehodList writes + sort to the baseMethods() method name in ro
Lazy vs. non-lazy classes:
- The load method changes a class from a lazy-loaded class to a non-lazy-loaded class. The advantage of lazy-loaded classes is that they can allocate memory on demand and save memory.
- Lazy loading class situation: data loading is delayed until the first message
- lookUpImpOrForward
- realizeClassMaybeSwiftMaybeRelock
- realizeClassWithoutSwift
- methodizeClass
- 2. Non-lazy class loading: map_images loaded all class data
- readClass
- _getObjc2NonlazyClassList
- realizeClassWithoutSwift
- methodizeClass