Android StrictMode InstanceCountViolation

Man*_*ser 48 android android-strictmode

我正在运行我的应用程序,在开发中激活StrictMode,如下所示StrictMode用于较低平台版本, 并注意到一条错误消息,我不知道该考虑什么,也无法找到任何参考.

我得到一个android.os.StrictMode$InstanceCountViolation与价值观instanceslimit

实例= 3; 极限= 2

现在我想知道:

  • A)如何计算限制
  • B)如何实际发生这种违规行为,然后我会调查回避行动.

有任何想法吗?

TWi*_*Rob 27

一切都在代码中

关键是StrictMode.sExpectedActivityInstanceCountincrementExpectedActivityCountdecrementExpectedActivityCount:

因此,limit每次活动被销毁时都会减少,但是如果实例被泄露,实际实例数将大于限制,以检测它是否泄漏,他们会做一些GC魔法(in decrementExpectedActivityCount):

    System.gc();
    System.runFinalization(); // added in https://github.com/android/platform_frameworks_base/commit/6f3a38f3afd79ed6dddcef5c83cb442d6749e2ff
    System.gc();
Run Code Online (Sandbox Code Playgroud)

如果在此之后GC没有从应用程序的内存中删除活动,则认为它是泄漏.

结论

基于以上所述,唯一的防范方法是确保之后没有引用违规行为onDestroy.问题是有些可能WeakReference仍然可以通过一些本机对象访问,这些对象似乎具有不同的生命周期.以下是我得出这个结论的方法:

  • 退出MyActivity并查看日志消息后
  • 进行堆转储(.hprof)
  • Eclipse Memory Analyzer中打开它
  • 运行OQL: select * from instanceof full.package.name.of.MyActivity
  • Ctrl+Click或选择全部Shift+Click
  • 右键单击并合并到GC根的最短路径>以及所有引用

解决方法

如果我们最初增加计数,我们会在报告特定类别的泄漏之前有更多的腿部空间:

// Application.onCreate or nearby where you set up StrictMode detectActivityLeaks
Method incrementExpectedActivityCount = StrictMode.class.getMethod("incrementExpectedActivityCount", Class.class)
incrementExpectedActivityCount.invoke(null, MyActivity.class);
incrementExpectedActivityCount.invoke(null, MyActivity2.class);
Run Code Online (Sandbox Code Playgroud)

进一步阅读


Ner*_*cer 9

似乎在某些设备上的StrictMode检查中可能存在错误.

如果一个Activity已启动,并且很快退出并重新启动,则可以获得StrictMode.InstanceCountViolation.

但这只是因为垃圾收集器尚未完成活动的第一个实例,这意味着内存中暂时有2个(或更多个)实例.

在startActivity()或startActivityForResult()之前调用System.gc()将停止StrictMode.InstanceCountViolation.

这似乎表明StrictMode检查中存在错误(或者可能是某个功能?).


jpo*_*s18 7

以下是有关处理StrictMode InstanceCountViolation的 Google网上论坛的讨论.看起来每个不同的Android版本都有不同的策略,因此它们似乎只是禁用它.此外,Android文档也谈到了严格模式

但是不要觉得有必要修复StrictMode找到的所有内容.特别是,在正常的活动生命周期中,通常需要许多磁盘访问的情况.使用StrictMode查找您意外执行的操作.但是,UI线程上的网络请求几乎总是一个问题.

我认为这就是@sri试图用他的代码展示的东西.

public class MyApplication extends Application {

@Override 
public void onCreate (){
   super.onCreate();
   // when you create a new application you can set the Thread and VM Policy
   StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
   .detectCustomSlowCalls() // API level 11, to use with StrictMode.noteSlowCode
   .detectDiskReads()
   .detectDiskWrites()
   .detectNetwork()
   .penaltyLog()
   .penaltyFlashScreen() // API level 11
   .build());

//If you use StrictMode you might as well define a VM policy too

   StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder()
   .detectLeakedSqlLiteObjects()
   .detectLeakedClosableObjects() // API level 11
   .setClassInstanceLimit(Class.forName(“com.apress.proandroid.SomeClass”), 100)
   .penaltyLog()
   .build());
 }
}
Run Code Online (Sandbox Code Playgroud)

  • 这一切都有道理,我知道这一点.但是,它仍然没有真正解释如何计算实例计数以及计算错误或者我做错了什么. (4认同)