我的应用中存在内存泄漏。所以很自然地我想解决它。问题是我不知道如何使用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乘221px,但显然是19528kb。如果我的数学是正确的221 * 221 = 48841 * 4 = 195364 bytes = 190.7kb。这根本没有任何意义。 Anywho,请看看你能找到的东西。顺便说一下,错误的问题是以下(来自再生方法)
mBackground = Bitmap.createBitmap(getWidth(), getHeight(), Bitmap.Config.ARGB_8888);
答案 0 :(得分:4)
首先,我认为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
}
如果您的位图总是相同的大小,我建议您重新使用它们。如果您正在快速创建和销毁位图,则存在超出垃圾收集器并进入此状态的风险。
- Edit-- 至于你原来的问题。在寻找内存泄漏时,我通常会执行以下操作。
初始化步骤
<强>分析强>
您需要考虑您在这里看到的内容以及它对您的应用程序是否有意义。是否应该有1000个小内存分配?很可能不是。此时,您可以单击分配并确切了解导致分配的方法和行号。
要采取的另一种方法是为您的应用启用堆更新,并使用堆资源管理器来跟踪分配。堆资源管理器不告诉你分配来自哪里,但它会告诉你的是例如:
1k分配的数量是 成长,永不萎缩。
然后,您可以进入分配跟踪器并按大小对分配进行排序,以查看您执行1k分配的位置。
答案 1 :(得分:0)
我喜欢使用分配跟踪工具。
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
上优化的其他帖子