【问题标题】:Android bitmap/ byte array memory leakAndroid 位图/字节数组内存泄漏
【发布时间】:2015-11-18 04:37:20
【问题描述】:

我的 Android 应用程序出现内存泄漏问题。根据我的 hprof 分析,它似乎是由来自 SurfaceView 类中的 Bitmapbyte 数组引起的。

这是几个数组之一的 MAT 分析:

以及违规类的代码:

public class AndroidFastRenderView extends SurfaceView implements Runnable {

    AndroidGame game;
    Bitmap framebuffer;
    Thread renderThread = null;
    SurfaceHolder holder;
    volatile boolean running = false;

    public AndroidFastRenderView(AndroidGame game, Bitmap framebuffer) {
        super(game);
        this.game = game;
        this.framebuffer = framebuffer;
        this.holder = getHolder();
        this.holder.setFormat(PixelFormat.RGBA_8888);
        setSystemUiVisibility(
                SYSTEM_UI_FLAG_IMMERSIVE_STICKY | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION);

    }

    public void resume() {
        setSystemUiVisibility(
                SYSTEM_UI_FLAG_IMMERSIVE_STICKY | SYSTEM_UI_FLAG_FULLSCREEN | SYSTEM_UI_FLAG_HIDE_NAVIGATION);
        running = true;
        renderThread = new Thread(this);
        renderThread.start();

    }

    public void run() {
        Rect dstRect = new Rect();
        long startTime = System.nanoTime();
        while (running) {
            if (!holder.getSurface().isValid())
                continue;
            float deltaTime = (System.nanoTime() - startTime) / 10000000.000f;
            startTime = System.nanoTime();
            game.getCurrentScreen().update(deltaTime);
            game.getCurrentScreen().paint(deltaTime);
            Canvas canvas = holder.lockCanvas();
            canvas.getClipBounds(dstRect);
            canvas.drawBitmap(framebuffer, null, dstRect, null);
            holder.unlockCanvasAndPost(canvas);

        }
    }

    public void pause() {
        running = false;
        while (true) {
            try {
                renderThread.join();
                break;
            } catch (InterruptedException e) {
            }
        }
    }

    public void release() {
        getHolder().getSurface().release();
        framebuffer.recycle();
    }
}

release() 在我的 Activity 的 onDestroy() 中被调用。

frameBuffer 使用以下行创建:

Bitmap frameBuffer = Bitmap.createBitmap(frameBufferWidth, frameBufferHeight, ARGB_8888);

在我的活动中。

【问题讨论】:

  • 帧缓冲位图是否被像素修改?还是每帧都创建新的?提供的代码没有说明这一点。
  • 那么,framebuffer 是不是每帧都重新创建?
  • @S.D.您是说需要在 Activity 类中进行更改吗?我尝试在 onCreate() 方法的末尾进行回收,但这会导致异常,因此我将 frameBuffer 设为实例变量并在 onDestroy() 中回收它。运行没有错误,但问题仍然存在。
  • Bitmap.createBitmap 行调试断点,查看它在活动生命周期中运行了多少次。它会重复运行吗?
  • @S.D.只有在创建 Activity 时才会触发断点。问题是每次创建 Activity 时,内存使用量都会跳跃,而当 Activity 被销毁时,内存不会减少。

标签: java android memory-leaks bitmap


【解决方案1】:

确保您的线程“renderThread”已停止。如果它仍然处于活动状态,则它持有对“AndroidFastRenderView”对象的引用,因此它无法释放内存...

【讨论】:

  • 你说得对,但interrupt() 也没有解决问题
  • interrupt() 不会停止线程。您通过要求它停止来停止线程,它通过从run() 返回来完成。所有interrupt() 完成的是在它正在等待/睡眠时唤醒它。发布的代码中的 pause() 函数看起来不错——只要确保它确实被调用了。
猜你喜欢
  • 2013-06-05
  • 2012-11-19
  • 1970-01-01
  • 2011-10-22
  • 1970-01-01
  • 2012-05-15
  • 2013-09-11
  • 2011-05-11
相关资源
最近更新 更多