You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.23 10:23:19