找出资源去向的更好方法?

发布于 2024-11-07 18:36:37 字数 5689 浏览 0 评论 0原文

我的应用程序出现内存泄漏。所以我自然想要修复它。问题是要么我不知道如何使用 DDMS 和内存分配工具,要么它们都是垃圾(或两者兼而有之)。所以我想知道是否有另一种方法可以弄清楚我的所有资源都在哪里使用,或者是否有人可以启发我如何使用 DDMS 工具。

PS:是的,我知道我必须单击 DDMS 中的调试按钮,然后引发 HPROF 转储和/或使用更新堆按钮并​​执行 GC。我可以查看两者的详细信息,但看不到我创建的任何对象。简而言之,我无法阅读我正在查看的内容。

非常感谢任何帮助或启发。

~Aedon

编辑 1:

我在自定义视图中的绘图方法中添加了一些日志记录。经过一番实验,我发现内存泄漏似乎来自于这种方法。

/** 更新后台的独立于仪表的静态缓冲区缓存。 */

private void regenerate() {
    mNeedRegen = false;
    // Prevent memory leaks by disposing of old bitmaps.
    if (mBackground != null) { mBackground.recycle(); mBackground = null; }
    // Our new drawing area
    Log.d(TAG, getWidth() + "\t" + getHeight());
    mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
    Canvas backCanvas = new Canvas(mBackground);
    float scale = (float)getWidth();
    backCanvas.scale(scale, scale);
    drawRim(backCanvas);
    drawFace(backCanvas);
    drawTitle(backCanvas);
    if (!(this instanceof EmptySpace)) { drawGroupIcon(backCanvas); }
    regenerateBackground(backCanvas);
}

现在,在我的应用程序中进行一些摆弄之后,我设法导致了这个错误:

     dalvikvm-heap  E  195364-byte external allocation too large for this process.
  2935               dalvikvm  E  Out of memory: Heap Size=4871KB, Allocated=2636KB, Bitmap Size=19528KB
  2935            GraphicsJNI  E  VM won't let us allocate 195364 bytes
  2935         AndroidRuntime  D  Shutting down VM
  2935               dalvikvm  W  threadid=1: thread exiting with uncaught exception (group=0x400259f8)
  2935         AndroidRuntime  E  FATAL EXCEPTION: main
  2935         AndroidRuntime  E  java.lang.OutOfMemoryError: bitmap size exceeds VM budget
  2935         AndroidRuntime  E    at android.graphics.Bitmap.nativeCreate(Native Method)
  2935         AndroidRuntime  E    at android.graphics.Bitmap.createBitmap(Bitmap.java:574)
  2935         AndroidRuntime  E    at com.android.appion.arm.widgets.GaugeBase.regenerate(GaugeBase.java:239)
  2935         AndroidRuntime  E    at com.android.appion.arm.widgets.GaugeBase.onSizeChanged(GaugeBase.java:86)
  2935         AndroidRuntime  E    at android.view.View.setFrame(View.java:7101)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7028)
  2935         AndroidRuntime  E    at android.widget.GridView.setupChild(GridView.java:1316)
  2935         AndroidRuntime  E    at android.widget.GridView.makeAndAddView(GridView.java:1222)
  2935         AndroidRuntime  E    at android.widget.GridView.makeRow(GridView.java:265)
  2935         AndroidRuntime  E    at android.widget.GridView.fillSpecific(GridView.java:463)
  2935         AndroidRuntime  E    at android.widget.GridView.layoutChildren(GridView.java:1122)
  2935         AndroidRuntime  E    at android.widget.AbsListView.onLayout(AbsListView.java:1147)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.onLayout(LinearLayout.java:1042)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.SlidingDrawer.onLayout(SlidingDrawer.java:331)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:909)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.onLayout(LinearLayout.java:1042)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.view.ViewRoot.performTraversals(ViewRoot.java:1049)
  2935         AndroidRuntime  E    at android.view.ViewRoot.handleMessage(ViewRoot.java:1744)
  2935         AndroidRuntime  E    at android.os.Handler.dispatchMessage(Handler.java:99)
  2935         AndroidRuntime  E    at android.os.Looper.loop(Looper.java:144)
  2935         AndroidRuntime  E    at android.app.ActivityThread.main(ActivityThread.java:4937)
  2935         AndroidRuntime  E    at java.lang.reflect.Method.invokeNative(Native Method)
  2935         AndroidRuntime  E    at java.lang.reflect.Method.invoke(Method.java:521)
  2935         AndroidRuntime  E    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
  2935         AndroidRuntime  E    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
  2935         AndroidRuntime  E    at dalvik.system.NativeStart.main(Native Method)

错误本身是有道理的。我的内存不足了。没有意义的是我试图制作的位图是 221px x 221px,但显然是 19528kb。如果我的数学正确的话,221 * 221 = 48841 * 4 = 195364 字节 = 190.7kb。这根本没有任何意义。任何人,请看一下,看看你能找到什么。顺便说一句,错误中的相关行如下(来自重新生成方法)

mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);

I have a memory leak in my app. So naturally I want to fix it. The issue is either I don't know how to use the DDMS and memory allocation tools or they are peices of crap (or both). So I'm wondering if there is another way I can figure out where all of my resources are being used or if someone can enlighten me on how to use the DDMS tools.

PS: Yes, I know I have to click the debug button in the DDMS and then cause a HPROF dump and/of use the Update heap button and do a GC. I can view the details of both but I can't see any of the objects I have created. In short I can't read what I'm viewing.

Any help or enlightenment is greatly appreciated.

~Aedon

Edit 1:

I added some logging throughout the drawing methods in my custom views. After some experimentation, I discoverd that the memory leak seams to be coming from this method.

/** Update the gauge independent static buffer cache for the background. */

private void regenerate() {
    mNeedRegen = false;
    // Prevent memory leaks by disposing of old bitmaps.
    if (mBackground != null) { mBackground.recycle(); mBackground = null; }
    // Our new drawing area
    Log.d(TAG, getWidth() + "\t" + getHeight());
    mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
    Canvas backCanvas = new Canvas(mBackground);
    float scale = (float)getWidth();
    backCanvas.scale(scale, scale);
    drawRim(backCanvas);
    drawFace(backCanvas);
    drawTitle(backCanvas);
    if (!(this instanceof EmptySpace)) { drawGroupIcon(backCanvas); }
    regenerateBackground(backCanvas);
}

Now after some fiddling around in my app, I managed to cause this error:

     dalvikvm-heap  E  195364-byte external allocation too large for this process.
  2935               dalvikvm  E  Out of memory: Heap Size=4871KB, Allocated=2636KB, Bitmap Size=19528KB
  2935            GraphicsJNI  E  VM won't let us allocate 195364 bytes
  2935         AndroidRuntime  D  Shutting down VM
  2935               dalvikvm  W  threadid=1: thread exiting with uncaught exception (group=0x400259f8)
  2935         AndroidRuntime  E  FATAL EXCEPTION: main
  2935         AndroidRuntime  E  java.lang.OutOfMemoryError: bitmap size exceeds VM budget
  2935         AndroidRuntime  E    at android.graphics.Bitmap.nativeCreate(Native Method)
  2935         AndroidRuntime  E    at android.graphics.Bitmap.createBitmap(Bitmap.java:574)
  2935         AndroidRuntime  E    at com.android.appion.arm.widgets.GaugeBase.regenerate(GaugeBase.java:239)
  2935         AndroidRuntime  E    at com.android.appion.arm.widgets.GaugeBase.onSizeChanged(GaugeBase.java:86)
  2935         AndroidRuntime  E    at android.view.View.setFrame(View.java:7101)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7028)
  2935         AndroidRuntime  E    at android.widget.GridView.setupChild(GridView.java:1316)
  2935         AndroidRuntime  E    at android.widget.GridView.makeAndAddView(GridView.java:1222)
  2935         AndroidRuntime  E    at android.widget.GridView.makeRow(GridView.java:265)
  2935         AndroidRuntime  E    at android.widget.GridView.fillSpecific(GridView.java:463)
  2935         AndroidRuntime  E    at android.widget.GridView.layoutChildren(GridView.java:1122)
  2935         AndroidRuntime  E    at android.widget.AbsListView.onLayout(AbsListView.java:1147)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.onLayout(LinearLayout.java:1042)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.SlidingDrawer.onLayout(SlidingDrawer.java:331)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.RelativeLayout.onLayout(RelativeLayout.java:909)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.setChildFrame(LinearLayout.java:1249)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.layoutVertical(LinearLayout.java:1125)
  2935         AndroidRuntime  E    at android.widget.LinearLayout.onLayout(LinearLayout.java:1042)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.widget.FrameLayout.onLayout(FrameLayout.java:333)
  2935         AndroidRuntime  E    at android.view.View.layout(View.java:7034)
  2935         AndroidRuntime  E    at android.view.ViewRoot.performTraversals(ViewRoot.java:1049)
  2935         AndroidRuntime  E    at android.view.ViewRoot.handleMessage(ViewRoot.java:1744)
  2935         AndroidRuntime  E    at android.os.Handler.dispatchMessage(Handler.java:99)
  2935         AndroidRuntime  E    at android.os.Looper.loop(Looper.java:144)
  2935         AndroidRuntime  E    at android.app.ActivityThread.main(ActivityThread.java:4937)
  2935         AndroidRuntime  E    at java.lang.reflect.Method.invokeNative(Native Method)
  2935         AndroidRuntime  E    at java.lang.reflect.Method.invoke(Method.java:521)
  2935         AndroidRuntime  E    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
  2935         AndroidRuntime  E    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
  2935         AndroidRuntime  E    at dalvik.system.NativeStart.main(Native Method)

The error itself makes sense. I ran out of memory. What doesn't make sense is the bitmap I'm trying to make is 221px by 221px but aparently is 19528kb. If my math is right 221 * 221 = 48841 * 4 = 195364 bytes = 190.7kb. This doesn't make any sense at all. Anywho, please take a look and see what you can find. BTW, the line in question from the error is the following (from the regenerate method)

mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

永言不败 2024-11-14 18:36:37

首先,我认为 Dalvik 消息显示了错误的单位,而 GraphicsJNI 错误是正确的:

dalvikvm E 内存不足:堆
大小=4871KB,分配=2636KB,位图
大小=19528KB 2935
GraphicsJNI E VM 不会让我们
分配195364字节

请记住,您可以捕获内存错误:

try{
    mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
} catch(OutOfMemoryError e){
    //do something
}

如果您的位图始终大小相同,我建议重新使用它们。如果您相当快地创建和销毁位图,则您将面临超过垃圾收集器并进入此状态的风险。

- 编辑 -
至于你原来的问题。在查找内存泄漏时,我通常会执行以下操作。

初始化步骤

  1. 确保您的应用程序在清单中设置为可调试
  2. 启动您的应用程序,打开 DDMS 并选择您的应用程序。
  3. 选择“分配跟踪器”视图并开始跟踪

分析

  1. 让您的应用运行,或在应用中执行一些导致内存问题的特定活动。
  2. 单击“获取分配”以更新跟踪器。如果您愿意,现在可以停止跟踪。
  3. 在过滤器中,输入您的应用程序名称以缩小结果范围。

您需要考虑您在这里看到的内容以及它对您的应用程序是否有意义。是否应该有 1000 个小内存分配?很可能不会。此时,您可以单击一个分配并准确查看导致分配的方法和行号。

另一种方法是为您的应用程序启用堆更新并使用堆资源管理器来跟踪分配。堆资源管理器不会告诉您分配来自哪里,但它会告诉您例如:

1k 分配的数量为
不断增长且永不萎缩。

然后,您可以进入分配跟踪器并按大小对分配进行排序,以查看在何处执行 1k 分配。

First, I think the Dalvik message is showing the wrong units whereas the GraphicsJNI error is correct:

dalvikvm E Out of memory: Heap
Size=4871KB, Allocated=2636KB, Bitmap
Size=19528KB 2935
GraphicsJNI E VM won't let us
allocate 195364 bytes

Keep in mind you can catch the memory error:

try{
    mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
} catch(OutOfMemoryError e){
    //do something
}

If your bitmaps are always the same size, I would recommend re-using them. If you are creating and destroying bitmaps fairly quickly, you run the risk of out-pacing the Garbage Collector and getting into this state.

--Edit--
As for your original question. I typically do the following when looking for a memory leak.

Initialization Steps

  1. Make sure your app is set to be debuggable in the manifest
  2. Launch your app, open DDMS and select your application.
  3. Select the Allocation Tracker view and Start Tracking

Analysis

  1. Let your app run, or perform some specific activities in your app that are causing memory issues.
  2. Click "Get Allocations" to update the tracker. You can now stop tracking if you like.
  3. In the filter, type your application name to narrow down the results.

You need to think about what you are seeing here and whether it makes sense for your application. Should there be 1000's of small memory allocations? Most likely not. At this point you can click on an allocation and see exactly which method and line number is causing the allocation.

Another route to take is to enable heap updates for your app and use the heap explorer to track allocations. The heap explorer does not tell you where the allocation is coming from, but what it will tell you is that for instance:

The number of 1k allocations is
growing and never shrinking.

You can then go into the Allocation Tracker and sort allocations by size to see where you are performing 1k allocations.

窝囊感情。 2024-11-14 18:36:37

我喜欢使用分配跟踪工具。

http://android-developers.blogspot.com/2009/02 /track-memory-allocations.html


我意识到这不是您要问的...

我发现以下有关 Android 内存泄漏的文档值得一读。

http://developer.android.com/resources/articles/avoiding-memory -leaks.html

...以及 http://android-developers.blogspot.com/search/label/Optimization

I like to use the allocation tracker tool.

http://android-developers.blogspot.com/2009/02/track-memory-allocations.html


I realize this isn't what you were asking about...

I've found the following documentation on Android memory leaks to be worth reading.

http://developer.android.com/resources/articles/avoiding-memory-leaks.html

...as well as the other posts on optimization at http://android-developers.blogspot.com/search/label/Optimization

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文