我正在运行我的应用程序,在开发中激活StrictMode,如此处所述StrictMode for lower platform versions 并注意到一条错误信息,我不知道该怎么想,也找不到任何参考。
我得到android.os.StrictMode$InstanceCountViolation
instances
和limit
的值,例如
实例= 3;极限= 2
现在我想知道:
有什么想法吗?
答案 0 :(得分:26)
ActivityThread.performLaunchActivity
中调用增量
在创建Activity
实例之后。ActivityThread.performDestroyActivity
中调用减法
活动从应用程序中删除后。因此,每次活动被销毁时limit
都会减少,但是如果某个实例被泄露,实际实例数将大于限制,以检测它是否泄露它们是否会产生一些GC魔法(在decrementExpectedActivityCount
中):
System.gc();
System.runFinalization(); // added in https://github.com/android/platform_frameworks_base/commit/6f3a38f3afd79ed6dddcef5c83cb442d6749e2ff
System.gc();
如果在此之后GC没有从应用程序的内存中删除活动,则认为它是泄漏。
基于以上所述,唯一的预防方法是确保在onDestroy
之后没有引用违规活动。问题是有些WeakReference
可能仍然可以通过一些本地对象访问,这些对象似乎有不同的生命周期。以下是我得出这个结论的方法:
MyActivity
退出并看到日志消息后select * from instanceof full.package.name.of.MyActivity
如果我们increase the count initially我们在报告特定类别的泄漏之前会有更多的腿部空间:
// 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);
答案 1 :(得分:9)
似乎某些设备上的StrictMode检查中可能存在错误。
如果Activity已启动,并且很快退出并重新启动,则可以获得StrictMode.InstanceCountViolation。
然而,这只是因为垃圾收集器尚未完成活动的第一个实例,这意味着内存中暂时有2个(或更多个)实例。
在startActivity()或startActivityForResult()之前调用System.gc()将停止StrictMode.InstanceCountViolation。
这似乎表明StrictMode检查中存在错误(或者可能是某个功能?)。
答案 2 :(得分:7)
以下是有关处理StrictMode InstanceCountViolation的Google群组的讨论。看起来每个不同的Android版本都有不同的策略,因此它们似乎只是禁用它。此外,Android文档还提到Strict Mode
但是不要觉得有必要修复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());
}
}
答案 3 :(得分:2)
我的理解是这种违规用于检测内存泄漏。因此,此时您应该只加载2个类的实例,但VM找到3个。
我在代码中也看到了这种违规行为,但是我的额外实例都被弱指针引用了。所以我选择禁用此规则。
答案 4 :(得分:-3)
见下面的例子,根据Android版本的不同而不同
public class MyApplication extends Application {
@Override
public void onCreate() {
super.onCreate();
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder()
.detectCustomSlowCalls() // API level 11, to use with StrictMode.noteSlowCode
.detectDiskReads()
.detectDiskWrites()
.detectNetwork()
.penaltyLog()
.penaltyFlashScreen() // API level 11
.build());
// not really performance-related, but 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) // API level 11
.penaltyLog()
.build());
}
}
答案 5 :(得分:-3)
从创建时删除下面的一行。
//StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().penaltyDeath().detectLeakedSqlLiteObjects().build());