【问题标题】:memory leak while bitmap processing位图处理时内存泄漏
【发布时间】:2012-05-09 15:10:02
【问题描述】:

我尝试编写一些相机意图处理程序来拍照并对其进行后期处理(如果需要)。如果我以高分辨率拍摄一些照片,我的程序会因“分配太大”而中断。如果我拿一些分辨率较低的东西,我可以拿更多,但它也会坏掉。经过一番搜索,我发现我必须回收手动制作的位图。但问题并没有消失。我的主要问题是我不知道 1. 我的代码中是否存在内存泄漏 2. 我不知道为什么它试图分配内存,因为我没有在我的程序中显示位图(现在) ,我只是保存它们以供进一步使用。

public void onClick(View view) {
    Intent i = new Intent("android.media.action.IMAGE_CAPTURE");
    this.mLastPic = new File(this.mFs.getDirPath(), this.mFs.getNextPicName()); //create and save a file for pic
    i.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(this.mLastPic));
    this.startActivityForResult(i, 0);
}

on activty 结果处理程序

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if(resultCode == Activity.RESULT_OK && requestCode == 0) {

        try {
            if(!this.mController.getSetting(R.string.USE_HEIGH_RESOLUTION)) { //use high res or not
                int quality = this.mFs.getPicQuality(); //get compress quality
                Bitmap pic = BitmapFactory.decodeFile(this.mLastPic.getPath());
                ByteArrayOutputStream outStream = new ByteArrayOutputStream();
                pic.compress(Bitmap.CompressFormat.JPEG, quality, outStream);
                String path = this.mLastPic.getPath();
                if(this.mLastPic.delete()) { //replace the old file with a now file
                    File newFile = new File(path);
                    newFile.createNewFile();
                    FileOutputStream os = new FileOutputStream(newFile);
                    os.write(outStream.toByteArray());
                    Log.d("newEntryActivity.onActivityResult", "replaced pic ");
                } else {
                    Log.d("newEntryActivity.onActivityResult", "cant delete old pic");
                }
                pic.recycle(); //cleaning up
                outStream.close();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

logcat 显示

05-09 14:35:01.694:E/dalvikvm-heap(845):6380496 字节的外部分配对于此进程来说太大。 05-09 14:35:01.694: E/(845): VM 不会让我们分配 6380496 字节

05-09 14:35:01.694: D/AndroidRuntime(845): 关闭 VM

05-09 14:35:01.694: W/dalvikvm(845): threadid=3: 线程以未捕获的异常退出 (group=0x4001b188)

05-09 14:35:01.694:E/AndroidRuntime(845):未捕获的处理程序:线程主因未捕获的异常而退出

05-09 14:35:01.714:E/AndroidRuntime(845):java.lang.RuntimeException:无法启动活动 ComponentInfo{unicorn.Heurazio/unicorn.Heurazio.SettingsActivity}:android.view.InflateException:二进制 XML文件第 2 行:膨胀类时出错 ...

05-09 14:35:01.714: E/AndroidRuntime(845): Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.view.LayoutInflater.createView(LayoutInflater.java:513)

05-09 14:35:01.714: E/AndroidRuntime(845): at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.view.LayoutInflater.inflate(LayoutInflater.java:385)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.view.LayoutInflater.inflate(LayoutInflater.java:320)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.view.LayoutInflater.inflate(LayoutInflater.java:276)

05-09 14:35:01.714: E/AndroidRuntime(845): at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:198)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.app.Activity.setContentView(Activity.java:1622)

05-09 14:35:01.714: E/AndroidRuntime(845): at unicorn.Heurazio.SettingsActivity.onCreate(SettingsActivity.java:38)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)

05-09 14:35:01.714:E/AndroidRuntime(845):在 android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2459)

05-09 14:35:01.714: E/AndroidRuntime(845): ... 11 更多

05-09 14:35:01.714:E/AndroidRuntime(845):原因:java.lang.reflect.InvocationTargetException

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.widget.LinearLayout.(LinearLayout.java:92)

05-09 14:35:01.714: E/AndroidRuntime(845): at java.lang.reflect.Constructor.constructNative(Native Method)

05-09 14:35:01.714: E/AndroidRuntime(845): at java.lang.reflect.Constructor.newInstance(Constructor.java:446)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.view.LayoutInflater.createView(LayoutInflater.java:500)

05-09 14:35:01.714: E/AndroidRuntime(845): ... 21 更多

05-09 14:35:01.714:E/AndroidRuntime(845):原因:java.lang.OutOfMemoryError:位图大小超出 VM 预算

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.graphics.Bitmap.nativeCreate(Native Method) > 05-09 14:35:01.714: E/AndroidRuntime(845): 在 android .graphics.Bitmap.createBitmap(Bitmap.java:468)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.graphics.Bitmap.createBitmap(Bitmap.java:435)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:488)

05-09 14:35:01.714:E/AndroidRuntime(845):在 android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:462)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:323)

05-09 14:35:01.714: E/AndroidRuntime(845): at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.content.res.Resources.loadDrawable(Resources.java:1705)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.content.res.TypedArray.getDrawable(TypedArray.java:548)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.view.View.(View.java:1850)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.view.View.(View.java:1799)

05-09 14:35:01.714: E/AndroidRuntime(845): 在 android.view.ViewGroup.(ViewGroup.java:284)

任何帮助都会很棒。

问候亚历克斯

【问题讨论】:

  • 编辑:我忘了说当我回到 privios 活动和/或开始其他意图时会出现问题。

标签: android bitmap out-of-memory


【解决方案1】:

如果您检查您的日志,会发现在 unicorn.Heurazio.SettingsActivity 中膨胀视图时会发生较大的 (~6MB) 位图分配。检查您的资源,看看您是否在某处使用大位图作为背景。

【讨论】:

  • 我在每个活动中都有背景图片。它的大小约为 75kB。它作为背景图像放置在布局中。 android 不是管理它们的创建和回收吗?
  • 文件大小并不总是与内存大小相同,尤其是 JPG 文件。是的,Android 应该创建/回收/释放它们,但有时它不太擅长及时处理,需要手动取消绑定视图以帮助提示。
  • 这是一个相关的帖子。阅读答案:stackoverflow.com/questions/1949066/…
【解决方案2】:

在对我的程序进行了一些阅读和修改之后,比如在重载的应用程序中添加对背景的引用,擦除所有不需要的上下文元素,我仍然遇到同样的问题,而且情况似乎更糟。

如果我可以相信我对位图大小的计算

Bitmap tmp = BitmapFactory.decodeResource(this.getResources(), R.drawable.logo);
Log.d("mainApp", tmp.getRowBytes() * tmp.getHeight() / 1024 + "kB");

我的 100kB 徽标 (.png) 采用 6mB ram(适合异常消息)。任何想法都会很棒。

【讨论】:

  • 好的,我终于找到了这个错误。在 MAT 的帮助下,我能够弄清楚我有两个对长期运行上下文的引用。
【解决方案3】:

尝试在应用程序中添加您的清单android:largeHeap="true"

【讨论】:

  • 这不是把问题推回去吗?
猜你喜欢
  • 2016-04-12
  • 2011-09-19
  • 2011-10-22
  • 1970-01-01
  • 1970-01-01
  • 2015-06-14
  • 1970-01-01
  • 2013-06-05
相关资源
最近更新 更多