Android模拟Stack内存泄漏咨询:Java堆分配无法满足需求
模拟Android中dumpsys meminfo里的Stack内存泄漏
首先明确:dumpsys meminfo里的Stack项统计的是线程栈内存——每个运行中的线程都会分配一块独立的栈空间,用于存储方法调用帧、局部变量(基本类型、对象引用)等,这和Java堆(new ArrayList<>()这类对象的分配区域)是完全隔离的内存区域,所以用Java堆对象无法影响Stack项的数值。
模拟Stack内存泄漏的可行方案
要让Stack项的内存持续增长且不释放,核心是创建大量长期存活的线程,每个线程的栈空间会被持续占用,不会被系统回收。
代码示例
import java.util.concurrent.CountDownLatch; public class StackMemLeakSimulator { // 用CountDownLatch让线程保持阻塞,永远不退出 private static final CountDownLatch HOLD_THREADS = new CountDownLatch(1); public static void startLeak() { // 创建大量线程,每个线程启动后进入阻塞状态 for (int i = 0; i < 1000; i++) { new Thread(() -> { try { HOLD_THREADS.await(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } }, "Leak-Stack-Thread-" + i).start(); } } public static void main(String[] args) { startLeak(); // 让主线程保持运行,避免程序退出 try { Thread.currentThread().join(); } catch (InterruptedException e) { Thread.currentThread().interrupt(); } } }
效果说明
- 每创建一个线程,就会占用一块默认大小的栈空间(Android中默认线程栈一般为1MB左右,可通过JVM参数
-Xss调整,比如-Xss2m将单个线程栈设为2MB)。 - 线程进入
await()后会长期阻塞,不会退出,因此栈内存会被持续持有,dumpsys meminfo里的Stack项数值会随线程数量增加而上升。 - 如果需要更快看到Stack项增长,可以增加线程数量,或者调大单个线程的栈大小。
为什么new ArrayList<>()没用?
new ArrayList<>()创建的对象属于Java堆内存,会被统计到dumpsys meminfo的Java Heap项中,和Stack项统计的线程栈内存完全无关,因此无法用来模拟Stack区域的内存泄漏。
内容的提问来源于stack exchange,提问作者lucky1928
相关产品推荐
相关产品推荐

