Boost iOS AOP Performance: Inside Alibaba’s Lokie Framework
Lokie is a high‑performance iOS AOP framework written in C++14 that replaces the slow Aspect library by using libffi‑based trampolines, offering thread‑safe method interception, detailed API usage, runtime internals, and assembly‑level trampoline implementation with significant speed improvements.
Lokie is an iOS AOP framework written in C++14 that replaces the traditional Aspect library by avoiding Objective‑C message forwarding and NSInvocation, using libffi‑based trampoline functions for much higher performance and thread‑safety.
Performance tests on iPhone 7 Plus show Aspect taking about 6 seconds for one million calls, while Lokie completes the same workload in roughly 0.35 seconds.
The public API consists of two hook methods and an enum LokieHookPolicy:
#import <Foundation/Foundation.h>
typedef enum : NSUInteger {
LokieHookPolicyBefore = 1 << 0,
LokieHookPolicyAfter = 1 << 1,
LokieHookPolicyReplace = 1 << 2,
} LokieHookPolicy;
@interface NSObject (Lokie)
+ (BOOL)Lokie_hookMemberSelector:(NSString *)selector_name withBlock:(id)block policy:(LokieHookPolicy)policy;
+ (BOOL)Lokie_hookClassSelector:(NSString *)selector_name withBlock:(id)block policy:(LokieHookPolicy)policy;
- (NSArray *)lokie_errors;
@endHooking works by specifying the selector name, a block whose first argument is the target object followed by the original method’s parameters, and a policy indicating before, after, or replace execution.
Internally Lokie builds on the Objective‑C runtime concepts SEL, IMP and Method. It uses libffi to generate a lightweight trampoline that directly calls the user block, eliminating the heavy NSInvocation path. Thread safety is achieved with a lock‑free CAS‑based synchronization.
The article also explains the Objective‑C message‑sending mechanism ( objc_msgSend), selector lookup, and how a missing method is forwarded to _objc_msgForward. It then shows how a trampoline function can be implemented in assembly (x86) using a jmp with a calculated relative offset.
Finally, a complete example demonstrates hooking a simple add function, rewriting its first five bytes with a jmp to a new implementation, and verifying the result:
#include <stdio.h>
#include <mach/mach.h>
int new_add(int a, int b) { return a+b; }
int add(int a, int b) { printf("my_add org is called!
"); return 0; }
typedef struct { uint8_t jmp; uint32_t off; } __attribute__((packed)) tramp_line_code;
void dohook(void *src, void *dst) {
vm_protect(mach_task_self(), (vm_address_t)src, 5, 0, VM_PROT_ALL);
tramp_line_code jshort;
jshort.jmp = 0xe9;
jshort.off = (uint32_t)(long)dst - (uint32_t)(long)src - 5;
memcpy(src, &jshort, sizeof(jshort));
vm_protect(mach_task_self(), (vm_address_t)src, 5, 0, VM_PROT_READ|VM_PROT_EXECUTE);
}
int main() {
dohook(add, new_add);
int c = add(10, 20); // returns 30 after hook
printf("res is %d
", c);
return 0;
}These techniques enable fast, thread‑safe method interception on iOS without the overhead of traditional AOP libraries.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Alibaba Cloud Developer
Alibaba's official tech channel, featuring all of its technology innovations.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
