Android StrictMode InstanceCountViolation

I run my application with StrictMode activated in development, as described here by StrictMode for lower versions of the platform and noticed an error message that I don’t know what to think about and cannot find the link.

I get android.os.StrictMode$InstanceCountViolation with values ​​for instances and limit , for example.

instances = 3; limit = 2

Now I am wondering:

  • A) how the limit is calculated
  • B) how such a violation can occur, and then I would look at evasive actions.

Any ideas?

+45
android strictmode
May 10 '11 at 20:34
source share
6 answers

All this in code

Key StrictMode.sExpectedActivityInstanceCount and incrementExpectedActivityCount and decrementExpectedActivityCount :

Thus, the limit less each time the action is destroyed, however if the instance is leaked, the real counter of the instances will be more than the limit, to determine if it has leaked, they perform some GC magic (in decrementExpectedActivityCount ).

  System.gc(); System.runFinalization(); // added in https://github.com/android/platform_frameworks_base/commit/6f3a38f3afd79ed6dddcef5c83cb442d6749e2ff System.gc(); 

if after that the GC does not delete the activity from the application memory, this is considered a leak.

Conclusion

Based on the foregoing, the only way to prevent it is to make sure that there are no links to abusive activity after onDestroy . The problem is that some may be some WeakReference that are still accessible through some native objects that seem to have a different life cycle. This is how I came to this conclusion:

  • after returning from MyActivity and viewing the log message
  • make a bunch of dump (.hprof)
  • open it in Eclipse Memory Analyzer
  • run OQL: select * from instanceof full.package.name.of.MyActivity
  • select everything with Ctrl + Click or Shift + Click
  • right click and merge the shortest path to GC Roots> with all the links

Bypass

If we increase the amount initially , we will have more legroom before he reports a leak for certain classes:

 // 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); 

Further reading

+23
Dec 28 '14 at 18:38
source share

There seems to be a bug in checking StrictMode on some devices.

If the action started and exited and restarted very quickly, you can get StrictMode.InstanceCountViolation.

However, this is simply because the garbage collector has not yet completed the first instance of Activity, which means that there are temporarily 2 (or more) instances in memory.

Calling System.gc () before startingActivity () or startActivityForResult () will stop StrictMode.InstanceCountViolation.

This seems to indicate an error (or perhaps a function?) In the StrictMode check.

+8
Mar 10 '14 at 16:51
source share

The following is a discussion of google groups about handling StrictMode InstanceCountViolation . It seems that every other version of Android has a different policy, so they just turned it off. Also, Android docs talk about String mode

But don't feel obligated to fix everything that StrictMode has discovered. In particular, during a normal activity life cycle, many disk access cases are often required. Use StrictMode to find what you did by accident. Network requests in the user interface thread are almost always a problem.

I think this is what @sri is trying to show with its code.

 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()); } } 
+6
Jan 24 '13 at 9:19
source share

I understand that this violation is used to detect memory leaks. So, at this point you should only have 2 instances of the class, but VM found 3.

I also saw this violation in my code, but my additional instances were all referenced by weak pointers. Therefore, I decided to disable this rule.

+2
Jul 13 '11 at 16:16
source share

Remove the line below from create.

 //StrictMode.setVmPolicy(new StrictMode.VmPolicy.Builder().detectAll().penaltyLog().penaltyDeath().detectLeakedSqlLiteObjects().build()); 
-2
Mar 23 '15 at 11:02
source share

see the example below, it depends on the version of 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()); } } 
-3
Jan 22 '13 at 11:50
source share



All Articles