【问题标题】:Android Memory Usage Problem on possibly using ActivityGroup可能使用 ActivityGroup 的 Android 内存使用问题
【发布时间】:2011-07-04 06:08:41
【问题描述】:

Android 可能使用 ActivityGroup 的内存使用问题

这是一个有点长的故事,我最终搞砸了记忆问题。我通过使用大量的活动和框架开发了非常深入的 android 应用程序。首先,我不得不说我使用 ActivityGroups 作为主要类别来轻松处理活动。我可以通过getLocalActivityManager() 完成所有活动。我收到此错误消息:

02-25 11:34:13.749:
ERROR/dalvikvm-heap(3042):
2764800-byte external allocation too
large for this process.

02-25 11:34:13.749:
ERROR/GraphicsJNI(3042): VM won't let
us allocate 2764800 bytes

然后我的应用程序将崩溃并出现各种异常,例如;

02-25 11:34:13.772: ERROR/AndroidRuntime(3042): FATAL EXCEPTION: main
02-25 11:34:13.772: ERROR/AndroidRuntime(3042): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.turkcell.seyahat/com.matriksdata.ui.schedule.MessageDetail}: android.view.InflateException: Binary XML file line #2: Error inflating class <unknown>
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2663)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.ActivityThread.startActivityNow(ActivityThread.java:2503)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.LocalActivityManager.moveToState(LocalActivityManager.java:127)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.LocalActivityManager.startActivity(LocalActivityManager.java:339)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.matriksdata.app.XActivityGroup.goForward(XActivityGroup.java:122)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.matriksdata.ui.parents.ScheduleActivityGroup.goForward(ScheduleActivityGroup.java:143)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.matriksdata.ui.schedule.MessageBox.onItemClick(MessageBox.java:81)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.widget.AdapterView.performItemClick(AdapterView.java:284)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.widget.ListView.performItemClick(ListView.java:3730)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.widget.AbsListView$PerformClick.run(AbsListView.java:1808)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.os.Handler.handleCallback(Handler.java:587)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.os.Handler.dispatchMessage(Handler.java:92)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.os.Looper.loop(Looper.java:123)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.ActivityThread.main(ActivityThread.java:4627)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at java.lang.reflect.Method.invokeNative(Native Method)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at java.lang.reflect.Method.invoke(Method.java:521)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:871)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:629)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at dalvik.system.NativeStart.main(Native Method)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042): Caused by: android.view.InflateException: Binary XML file line #2: Error inflating class <unknown>
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.createView(LayoutInflater.java:513)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:56)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:563)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.inflate(LayoutInflater.java:385)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.inflate(LayoutInflater.java:320)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.inflate(LayoutInflater.java:276)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:210)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.Activity.setContentView(Activity.java:1647)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at com.matriksdata.ui.schedule.MessageDetail.onCreate(MessageDetail.java:33)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2627)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     ... 18 more
02-25 11:34:13.772: ERROR/AndroidRuntime(3042): Caused by: java.lang.reflect.InvocationTargetException
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.widget.LinearLayout.<init>(LinearLayout.java:115)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at java.lang.reflect.Constructor.constructNative(Native Method)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at java.lang.reflect.Constructor.newInstance(Constructor.java:446)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.LayoutInflater.createView(LayoutInflater.java:500)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     ... 28 more
02-25 11:34:13.772: ERROR/AndroidRuntime(3042): Caused by: java.lang.OutOfMemoryError: bitmap size exceeds VM budget
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.Bitmap.nativeCreate(Native Method)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.Bitmap.createBitmap(Bitmap.java:468)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.Bitmap.createBitmap(Bitmap.java:435)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:340)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.BitmapFactory.finishDecode(BitmapFactory.java:590)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:564)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:425)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:697)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.content.res.Resources.loadDrawable(Resources.java:1709)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.content.res.TypedArray.getDrawable(TypedArray.java:601)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.View.<init>(View.java:1885)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.View.<init>(View.java:1834)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     at android.view.ViewGroup.<init>(ViewGroup.java:285)
02-25 11:34:13.772: ERROR/AndroidRuntime(3042):     ... 32 more

当然我没有 2764800 字节的 png 图像,但我认为它的解码大小。所以我认为我有图像处理问题,我检查并修复了我的项目的每一个细节,以正确处理图像。我检查了 android-developers.blogspot.com/2009/01/avoiding-memory-leaks.html 中描述的所有内容。我检查了 null drawables,我遵循模型可重用性说明,我更改了以下描述的加载方法:stackoverflow.com/questions/477572/android-strange-out-of-memory-issue/823966#823966。

我也有几个位图要从磁盘加载。我由 android xml 布局文件创建的所有布局。我也有很多在 xml 文件中描述的位图。

然后我看到我在内存分析器的应用程序中有很大的静态类。我通过按需加载和使用后释放来释放静态属性。所以最后我在 MAT 中发现了这个内存泄漏嫌疑人;

问题嫌疑人 1

“java.lang.Class”的3043个实例,由“”加载,占用871304(17.97%)字节。

最大实例:
com.ibm.icu4jni.util.Resources$DefaultTimeZones 类 @ 0x4014c3b0 - 166,768 (3.44%) 字节。
类 android.text.Html$HtmlParser @ 0x400fe448 - 126,592 (2.61%) 字节。
com.google.googlenav.proto.GmmMessageTypes 类 @ 0x4835d450 - 56,944 (1.17%) 字节。
类 org.apache.harmony.luni.internal.net.www.protocol.http.HttpConnectionPool @ 0x47caea20 - 51,872 (1.07%) 字节。
类 org.apache.harmony.security.fortress.Services @ 0x4008c4d0 - 51,456 (1.06%) 字节。

问题嫌疑人 2

由“系统类加载器”加载的 8,721 个“java.lang.String”实例占用 549,624 (11.33%) 个字节。关键字java.lang.String

问题嫌疑人 3

由“系统类加载器”加载的“org.bouncycastle.jce.provider.X509CertificateObject”的 60 个实例占用 300,024 (10.76%) 个字节。这些实例引用自“java.util.Hashtable$HashtableEntry[]”的一个实例,由“系统类加载器”Keywordsorg.bouncycastle.jce.provider.X509CertificateObjectjava.util.Hashtable$HashtableEntry[] 加载

这第三个不是每次都发生。通常当我在 GalaxyTab 中使用内存管理器时。

我最大的顶级支配者课程是这些。 http://www.matriks.mobi/arge/android/Screen%20shot%202011-02-25%20at%2012.19.08%20PM.png

我只有 2 或 3 个活动正在直播,其余活动已暂停。我在组件报告中收到此消息。当然,这不是我只使用 1.5 MB 内存的解释,因为根据内存管理器的说法,我的应用程序使用了 48 MB 的内存,而不是大约 20 MB。

可能的内存浪费 * 重复的字符串* 找到 0 次出现的 char[],其中至少 10 个实例具有相同的内容。总大小为 0 字节。

我认为这不是我想要的 :) hprof 文件位于 http://www.matriks.mobi/arge/android/android5706014442078310727.hprof.zip

我猜我的 ActivityGroup 类有问题。至少我将 LocalActivityManager 中的活动和活动 ID 保存在堆栈中。但即使我不创建新的活动,并在加载的活动之间传递,内存也会增加。

我知道这不是搜索泄漏的方式,并且可能我有一个基于代码的问题导致此内存泄漏。但是我应该检查的任何一个想法在这里都会非常受欢迎,因为我有点卡在这里。

【问题讨论】:

  • 编辑:我发现了问题。每次创建活动组时,我都在重置背景图像; background.setBackgroundResource(R.drawable.background);我删除了这个并在xml中留下了描述,所以问题解决了。这种方法会导致内存泄漏。

标签: android memory-management memory-leaks android-activity memoryanalyzer


【解决方案1】:

在应用程序正在使用时尝试tracking memory allocations

另外,持有对位图可绘制对象的引用可以produce memory leaks。当一个 Drawable 添加到 View 时,会创建一个循环引用。因此,当您持有对 Bitmap drawable 的引用时,它会进一步持有对 View 的引用,并且该 View 永远不会被 GCed。

避免它的最简单方法是从 Bitmap Drawable 中提取位图并持有对它的引用,然后当 Activity 重新启动/重新加载时,您可以从该位图创建新的 Bitmap Drawables。这就是 Photostream 示例的工作方式(在最后描述): Faster screen orientation change

【讨论】:

  • 我正在跟踪内存分配,我只是看到堆大小和百分比正在增加。我认为这就是为什么我在内存分配中看不到任何可绘制对象的原因。正如我所写的,我在您引用的网站中使用了每一个解决方案。没有任何改变。
  • 该链接说:“作为我工作的一部分,我在 Android 应用程序中遇到了内存泄漏问题,它们大部分时间都是由于相同的错误:保持对 Context 的长期引用。”您是否在 ActivityGroup 中保留对活动的长期引用?尝试使用 Wea​​kReferences。
  • 我不知道我是否可以告诉我不保留长期引用。但我试图让每一个活动都有意图。在内存分析器中,我知道我最多有 3 个实时活动。我正在使用以下描述的弱哈希映射:ibm.com/developerworks/java/library/j-jtp11225
【解决方案2】:

你对 ListView 的行使用这种布局吗?

【讨论】:

  • 2764800 字节对于图像来说并不是一个令人难以置信的大小
  • 在某些活动中是的。但一般不会。而且我相信这不是问题,因为即使我不加载任何使用 listview 的活动,每次我来回并通过活动组时内存都会增加 1-2 mb(每个活动组最初有 1 个活动)。
  • 2764800 byte 对于一个 png 来说不是很大,但是工程中最大的 png 文件是 499,246 个字节
  • 我也使用 LayoutInflater 从 xml 创建用户控件。也许这是问题,但我不确定。我为每个控件使用LayoutInflater layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE); layoutInflater.inflate(getId(), this, true);
  • 499,246字节是图片压缩后的大小,加载到内存时会解压。Bitmap使用Native Heap而不是Dalvik heap进行内存分配,尝试回收它们来解决问题。是了解位图是在 Nativhe 堆中分配的,并且您无法在 DDMS 上看到它们的内存,这一点非常重要。 (没有技巧)
【解决方案3】:

每次创建活动组时,我都会重置背景图片;

 background.setBackgroundResource(R.drawable.background); 

我删除了这个并在 xml 中留下了描述,所以问题解决了。此方法会导致内存泄漏。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-02-28
    • 2014-03-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多