MemoryBomber.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface MemoryBomber : NSObject
+ (instancetype)sharedInstance;
- (void)explodeWithTargetMB:(NSUInteger)targetMB chunkSizeMB:(NSUInteger)chunkSizeMB;
- (void)explode;
- (void)explodeGraduallyWithTargetMB:(NSUInteger)targetMB interval:(NSTimeInterval)interval;
- (void)stopGradualExplosion;
- (void)releaseAllMemory;
- (NSUInteger)allocatedMemoryMB;
@end
NS_ASSUME_NONNULL_END
MemoryBomber.m
#import "MemoryBomber.h"
#import <mach/mach.h>
#import <UIKit/UIKit.h>
@interface MemoryBomber ()
@property (nonatomic, strong) NSMutableArray<NSData *> *memoryChunks;
@property (nonatomic, strong) NSTimer *gradualTimer;
@property (nonatomic, assign) NSUInteger gradualTargetMB;
@property (nonatomic, assign) NSUInteger gradualCurrentMB;
@end
@implementation MemoryBomber
#pragma mark - 单例
+ (instancetype)sharedInstance {
static MemoryBomber *instance = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
instance = [[self alloc] init];
});
return instance;
}
- (instancetype)init {
self = [super init];
if (self) {
_memoryChunks = [NSMutableArray array];
}
return self;
}
#pragma mark - 公共方法
- (void)explode {
[self explodeWithTargetMB:1000 chunkSizeMB:50];
}
- (void)explodeWithTargetMB:(NSUInteger)targetMB chunkSizeMB:(NSUInteger)chunkSizeMB {
[self logMemoryStatus:@"开始分配内存前"];
NSUInteger chunkSize = chunkSizeMB * 1024 * 1024;
NSUInteger allocated = 0;
NSLog(@"💣 MemoryBomber: 开始分配内存,目标 %lu MB,每块 %lu MB",
(unsigned long)targetMB, (unsigned long)chunkSizeMB);
while (allocated < targetMB) {
@autoreleasepool {
NSMutableData *chunk = [NSMutableData dataWithLength:chunkSize];
uint8_t *bytes = chunk.mutableBytes;
for (NSUInteger i = 0; i < chunkSize; i += 4096) {
bytes[i] = (uint8_t)(arc4random() % 256);
}
[self.memoryChunks addObject:chunk];
allocated += chunkSizeMB;
NSLog(@"📊 已分配: %lu MB", (unsigned long)allocated);
[NSThread sleepForTimeInterval:0.05];
}
}
[self logMemoryStatus:@"内存分配完成"];
NSLog(@"💣 MemoryBomber: 内存分配完成,等待系统触发 didReceiveMemoryWarning...");
}
- (void)explodeGraduallyWithTargetMB:(NSUInteger)targetMB interval:(NSTimeInterval)interval {
[self stopGradualExplosion];
self.gradualTargetMB = targetMB;
self.gradualCurrentMB = 0;
NSLog(@"⏱️ MemoryBomber: 开始渐进式分配,目标 %lu MB,间隔 %.1f 秒",
(unsigned long)targetMB, interval);
__weak typeof(self) weakSelf = self;
self.gradualTimer = [NSTimer scheduledTimerWithTimeInterval:interval
repeats:YES
block:^(NSTimer * _Nonnull timer) {
__strong typeof(weakSelf) strongSelf = weakSelf;
if (!strongSelf) return;
if (strongSelf.gradualCurrentMB >= strongSelf.gradualTargetMB) {
[strongSelf stopGradualExplosion];
NSLog(@"✅ 渐进式分配完成");
return;
}
NSUInteger chunkSize = 20 * 1024 * 1024;
NSMutableData *chunk = [NSMutableData dataWithLength:chunkSize];
uint8_t *bytes = chunk.mutableBytes;
for (NSUInteger i = 0; i < chunkSize; i += 4096) {
bytes[i] = (uint8_t)(arc4random() % 256);
}
[strongSelf.memoryChunks addObject:chunk];
strongSelf.gradualCurrentMB += 20;
NSLog(@"📊 渐进式分配: %lu / %lu MB",
(unsigned long)strongSelf.gradualCurrentMB,
(unsigned long)strongSelf.gradualTargetMB);
[strongSelf logMemoryStatus:@"渐进分配中"];
}];
}
- (void)stopGradualExplosion {
[self.gradualTimer invalidate];
self.gradualTimer = nil;
}
- (void)releaseAllMemory {
[self.memoryChunks removeAllObjects];
self.gradualCurrentMB = 0;
NSLog(@"🧹 MemoryBomber: 已释放所有内存");
[self logMemoryStatus:@"释放内存后"];
}
- (NSUInteger)allocatedMemoryMB {
NSUInteger totalBytes = 0;
for (NSData *chunk in self.memoryChunks) {
totalBytes += chunk.length;
}
return totalBytes / (1024 * 1024);
}
#pragma mark - 私有方法
- (void)logMemoryStatus:(NSString *)label {
struct mach_task_basic_info info;
mach_msg_type_number_t size = MACH_TASK_BASIC_INFO_COUNT;
kern_return_t kerr = task_info(mach_task_self(),
MACH_TASK_BASIC_INFO,
(task_info_t)&info,
&size);
if (kerr == KERN_SUCCESS) {
NSUInteger usedMB = info.resident_size / (1024 * 1024);
NSLog(@"📊 [%@] 进程内存使用: %lu MB", label, (unsigned long)usedMB);
}
}
@end
MemoryBomber+UsageExample.m
#pragma mark - 示例 1: 在 ViewController 中使用
#import "MemoryBomber.h"
@interface TestViewController : UIViewController
@end
@implementation TestViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeSystem];
[button setTitle:@"触发内存警告" forState:UIControlStateNormal];
[button addTarget:self action:@selector(triggerMemoryWarning)
forControlEvents:UIControlEventTouchUpInside];
button.frame = CGRectMake(100, 200, 200, 50);
[self.view addSubview:button];
}
- (void)triggerMemoryWarning {
[[MemoryBomber sharedInstance] explode];
}
#pragma mark - 处理内存警告
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
NSLog(@"⚠️ 收到内存警告!清理资源...");
[[MemoryBomber sharedInstance] releaseAllMemory];
}
@end
#pragma mark - 示例 2: 在 AppDelegate 中处理
@interface AppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
@implementation AppDelegate
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
NSLog(@"⚠️ AppDelegate 收到内存警告!");
[[NSURLCache sharedURLCache] removeAllCachedResponses];
[[MemoryBomber sharedInstance] releaseAllMemory];
}
@end
#pragma mark - 示例 3: 在 SceneDelegate 中使用 (iOS 13+)
@interface SceneDelegate : UIResponder <UIWindowSceneDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
@implementation SceneDelegate
- (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session
options:(UISceneConnectionOptions *)connectionOptions {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(handleMemoryWarning)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
}
- (void)handleMemoryWarning {
NSLog(@"⚠️ SceneDelegate 收到内存警告通知");
[[MemoryBomber sharedInstance] releaseAllMemory];
}
@end
#pragma mark - 示例 4: 命令行测试 (非 UI 环境)