StrictMode类是Android 2.3 (API 9)引入的一个工具类,可以用来帮助开发者发现代码中的一些不规范的问题。比如,如果你在UI线程中进行了网络或者磁盘操作,StrictMode就会通过Log(logcat )或者对话框的方式把信息提示给你,因为让你的UI线程处理这里操作会被认为是不规范的做法,可能会让你的应用变得比较卡顿。

官网文档:http://developer.android.com/reference/android/os/StrictMode.html

如何启用 StrictMode

我们通常在 Activity 或者自定义的Application类中启动 StrictMode,代码如下:

``` ` <span class="kd">public</span> <span class="kt">void</span> <span class="nf">onCreate</span><span class="o">()</span> <span class="o">{</span> <span class="k">if</span> <span class="o">(</span><span class="n">DEVELOPER_MODE</span><span class="o">)</span> <span class="o">{</span> <span class="n">StrictMode</span><span class="o">.</span><span class="na">setThreadPolicy</span><span class="o">(</span><span class="k">new</span> <span class="n">StrictMode</span><span class="o">.</span><span class="na">ThreadPolicy</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span> <span class="o">.</span><span class="na">detectDiskReads</span><span class="o">()</span> <span class="o">.</span><span class="na">detectDiskWrites</span><span class="o">()</span> <span class="o">.</span><span class="na">detectNetwork</span><span class="o">()</span> <span class="c1">// or .detectAll() for all detectable problems</span> <span class="o">.</span><span class="na">penaltyLog</span><span class="o">()</span> <span class="o">.</span><span class="na">build</span><span class="o">());</span> <span class="n">StrictMode</span><span class="o">.</span><span class="na">setVmPolicy</span><span class="o">(</span><span class="k">new</span> <span class="n">StrictMode</span><span class="o">.</span><span class="na">VmPolicy</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span> <span class="o">.</span><span class="na">detectLeakedSqlLiteObjects</span><span class="o">()</span> <span class="o">.</span><span class="na">detectLeakedClosableObjects</span><span class="o">()</span> <span class="o">.</span><span class="na">penaltyLog</span><span class="o">()</span> <span class="o">.</span><span class="na">penaltyDeath</span><span class="o">()</span> <span class="o">.</span><span class="na">build</span><span class="o">());</span> <span class="o">}</span> <span class="kd">super</span><span class="o">.</span><span class="na">onCreate</span><span class="o">();</span> <span class="o">}</span> ` ```

**注意:**我们只需要在app的开发版本下使用 StrictMode,线上版本避免使用 StrictMode,随意需要通过 诸如 DEVELOPER_MODE 这样的配置变量来进行控制。

下面我们举几个例子来说明 StrictMode 是如何发挥作用的。

代码1:

``` `<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ActivitySimple</span> <span class="kd">extends</span> <span class="n">Activity</span> <span class="o">{</span>
&lt;span class="nd">@Override&lt;/span>
&lt;span class="kd">protected&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">Bundle&lt;/span> &lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>
    &lt;span class="kd">super&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">);&lt;/span>
    &lt;span class="n">setContentView&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">activity_main&lt;/span>&lt;span class="o">);&lt;/span>

    &lt;span class="n">StrictMode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">setThreadPolicy&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">ThreadPolicy&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">Builder&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">detectAll&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">penaltyDialog&lt;/span>&lt;span class="o">()&lt;/span> &lt;span class="c1">//弹出违规提示对话框&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">penaltyLog&lt;/span>&lt;span class="o">()&lt;/span> &lt;span class="c1">//在Logcat 中打印违规异常信息&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">build&lt;/span>&lt;span class="o">());&lt;/span>
    
    &lt;span class="k">this&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">testNetwork&lt;/span>&lt;span class="o">();&lt;/span>
&lt;span class="o">}&lt;/span>


&lt;span class="kd">private&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">testNetwork&lt;/span>&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
    &lt;span class="k">try&lt;/span> &lt;span class="o">{&lt;/span>
        &lt;span class="n">URL&lt;/span> &lt;span class="n">url&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">URL&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="s">"http://www.baidu.com"&lt;/span>&lt;span class="o">);&lt;/span>
        &lt;span class="n">HttpURLConnection&lt;/span> &lt;span class="n">conn&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">HttpURLConnection&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">url&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">openConnection&lt;/span>&lt;span class="o">();&lt;/span>
        &lt;span class="n">conn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">connect&lt;/span>&lt;span class="o">();&lt;/span>
        &lt;span class="n">BufferedReader&lt;/span> &lt;span class="n">reader&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">BufferedReader&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">InputStreamReader&lt;/span>&lt;span class="o">(&lt;/span>
                &lt;span class="n">conn&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">getInputStream&lt;/span>&lt;span class="o">()));&lt;/span>
        &lt;span class="n">String&lt;/span> &lt;span class="n">lines&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="o">;&lt;/span>
        &lt;span class="n">StringBuffer&lt;/span> &lt;span class="n">sb&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">StringBuffer&lt;/span>&lt;span class="o">();&lt;/span>
        &lt;span class="k">while&lt;/span> &lt;span class="o">((&lt;/span>&lt;span class="n">lines&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="n">reader&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">readLine&lt;/span>&lt;span class="o">())&lt;/span> &lt;span class="o">!=&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>
            &lt;span class="n">sb&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">append&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">lines&lt;/span>&lt;span class="o">);&lt;/span>
        &lt;span class="o">}&lt;/span>
    &lt;span class="o">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">Exception&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>
        &lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">printStackTrace&lt;/span>&lt;span class="o">();&lt;/span>
    &lt;span class="o">}&lt;/span>
&lt;span class="o">}&lt;/span>

<span class=“o”>}</span> `

</div>

在这里例子中,我们在主线程(UI线程)中执行了网络请求,ThreadPolicy 策略中的 `detectAll()`方法 包含而来对这类违规操作的检查,同时我们通过`penaltyDialog()` 和 `penaltyLog()` 两个方法将违规信息提示给开发者。

在运行这段代码是,我们会看到下图中的对话框提示:

![](http://android-performance.com/images/android-strict-mode/dialog.png) 

在LogCat 中我们会看到这样的日志信息:

… D/StrictMode(26365): StrictMode policy violation; ~duration=58 ms: android.os.StrictMode$StrictModeNetworkViolation: policy=63 violation=4 … D/StrictMode(26365): at android.os.StrictModeAndroidBlockGuardPolicy.onNetwork(StrictMode.java:1134) … D/StrictMode(26365): at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:163) … D/StrictMode(26365): at libcore.io.IoBridge.recvfrom(IoBridge.java:557) … D/StrictMode(26365): at java.net.PlainSocketImpl.read(PlainSocketImpl.java:490) … D/StrictMode(26365): at java.net.PlainSocketImpl.access000(PlainSocketImpl.java:46) … (后面的部分省略)


# StrictMode 详解 {#tocAnchor-1-2}

StrictMode 通过策略方式来让你自定义需要检查哪方面的问题。 主要有两中策略,一个时线程方策略([ThreadPolicy][1]),一个是VM方面的策略([VmPolicy][2])。

  * ThreadPolicy 主要用于发现在UI线程中是否有读写磁盘的操作,是否有网络操作,以及检查UI线程中调用的自定义代码是否执行得比较慢。
  * VmPolicy,主要用于发现内存问题,比如 Activity内存泄露, SQL 对象内存泄露, 资源未释放,能够限定某个类的最大对象数。

## ThreadPolicy 详解 {#tocAnchor-1-2-1}

[StrictMode.ThreadPolicy.Builder][3] 主要方法如下:

  * detectNetwork() 用于检查UI线程中是否有网络请求操作,上面的代码的就是网络请求违规的问题。
  * detectDiskReads() 和 detectDiskReads() 是磁盘读写检查,触发时会打印出如下日志(以 detectDiskReads() 为例): 
    ```
... D/StrictMode(27429): StrictMode policy violation; ~duration=33 ms: android.os.StrictMode<span class="katex math inline">StrictModeDiskReadViolation: policy=31 violation=2
... D/StrictMode(27429):    at android.os.StrictMode</span>AndroidBlockGuardPolicy.onReadFromDisk(StrictMode.java:1118)
... D/StrictMode(27429):    at libcore.io.BlockGuardOs.open(BlockGuardOs.java:106)
... D/StrictMode(27429):    at java.io.File.createNewFile(File.java:941)
... D/StrictMode(27429):    at com.ap.teststrictmode.ActivityTestDisk.testWriteDisk(ActivityTestDisk.java:51)
... D/StrictMode(27429):    at com.ap.teststrictmode.ActivityTestDisk.onCreate(ActivityTestDisk.java:40)
... D/StrictMode(27429):    at android.app.Activity.performCreate(Activity.java:5122)
... D/StrictMode(27429):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081)
... D/StrictMode(27429):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
...
(后面的部分省略)
  • detectCustomSlowCalls() 主要用于帮助开发者发现UI线程调用的那些方法执行得比较慢,要和 StrictMode.noteSlowCall 配合使用,StrictMode.noteSlowCall 只有通过 StrictMode.noteSlowCall用来标记“可能会”执行比较慢的方法,只有标记过的方法才能被检测到,日志中会记录方法的执行时间(比如 ~duration=2019 ms)。看下面的例子:
    代码2:
``` `<span class="kd">public</span> <span class="kd">class</span> <span class="nc">ActivityTestDetectCustomSlowCalls</span> <span class="kd">extends</span> <span class="n">Activity</span> <span class="o">{</span>` ```
    <span class="kd">private</span> <span class="n">TextView</span> <span class="n">textView</span> <span class="o">=</span> <span class="kc">null</span><span class="o">;</span>
  

  
  

    <span class="kd">private</span> <span class="kd">static</span> <span class="kt">boolean</span> <span class="n">isStrictMode</span> <span class="o">=</span> <span class="kc">false</span><span class="o">;</span>
  

  
  

    <span class="nd">@Override</span> <span class="kd">protected</span> <span class="kt">void</span> <span class="nf">onCreate</span><span class="o">(</span><span class="n">Bundle</span> <span class="n">savedInstanceState</span><span class="o">)</span> <span class="o">{</span> <span class="kd">super</span><span class="o">.</span><span class="na">onCreate</span><span class="o">(</span><span class="n">savedInstanceState</span><span class="o">);</span> <span class="n">setContentView</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">layout</span><span class="o">.</span><span class="na">activity*main*</span>*<span class="o">);</span> <span class="k">this</span><span class="o">.</span><span class="na">textView</span> <span class="o">=</span> <span class="o">(</span><span class="n">TextView</span><span class="o">)</span> <span class="n">findViewById</span><span class="o">(</span><span class="n">R</span><span class="o">.</span><span class="na">id</span><span class="o">.</span><span class="na">text</span>*view<span class="o">);</span> <span class="k">this</span><span class="o">.</span><span class="na">textView</span><span class="o">.</span><span class="na">setText</span><span class="o">(</span><span class="s">&#8220;In ActivityTestDetectCustomSlowCalls&#8221;</span><span class="o">);</span> <span class="k">if</span><span class="o">(!</span> <span class="n">isStrictMode</span><span class="o">){</span> <span class="n">StrictMode</span><span class="o">.</span><span class="na">setThreadPolicy</span><span class="o">(</span><span class="k">new</span> <span class="n">ThreadPolicy</span><span class="o">.</span><span class="na">Builder</span><span class="o">()</span> <span class="o">.</span><span class="na">detectCustomSlowCalls</span><span class="o">()</span> <span class="o">.</span><span class="na">penaltyLog</span><span class="o">()</span> <span class="o">.</span><span class="na">build</span><span class="o">());</span> <span class="n">isStrictMode</span> <span class="o">=</span> <span class="kc">true</span><span class="o">;</span> <span class="o">}</span> <span class="k">this</span><span class="o">.</span><span class="na">slowCall*1*</span>*<span class="o">();</span> <span class="k">this</span><span class="o">.</span><span class="na">slowCall</span>*2<span class="o">();</span> <span class="o">}</span>
  

  
  

    <span class="cm">/*</span>* <span class="cm"> * 没有标记的方法</span> <span class="cm"> */</span> <span class="kd">private</span> <span class="kt">void</span> <span class="nf">slowCall_1</span><span class="o">(){</span> <span class="c1">//用来标记潜在执行比较慢的方法</span> <span class="n">SystemClock</span><span class="o">.</span><span class="na">sleep</span><span class="o">(</span><span class="mi">1000</span> * <span class="mi">2</span><span class="o">);</span> <span class="o">}</span>
  

  
  

    `&lt;span class="cm">/&lt;/span>&lt;strong> &lt;span class="cm"> * 标记过的方法&lt;/span> &lt;span class="cm"> &lt;em>/&lt;/em>&lt;/span>&lt;em> &lt;span class="kd">private&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">slowCall_2&lt;/span>&lt;span class="o">(){&lt;/span> &lt;span class="c1">//用来标记潜在执行比较慢的方法&lt;/span> &lt;span class="n">StrictMode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">noteSlowCall&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="s">"slowCall 2"&lt;/span>&lt;span class="o">);&lt;/span> &lt;span class="n">SystemClock&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">sleep&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="mi">1000&lt;/span> &lt;/em> &lt;span class="mi">2&lt;/span>&lt;span class="o">);&lt;/span> &lt;span class="o">}&lt;/span> &lt;span class="o">}&lt;/span> &lt;/strong>`
  

</div>

**  
在logcat 中我们只能看到和方法 `slowCall_2()`(因为通过`StrictMode.noteSlowCall()`标记过)相关的日志:  

**

```

**…: D/StrictMode(1349): StrictMode policy violation; ~duration=2019 ms: android.os.StrictModeStrictModeCustomViolation: policy=24 violation=8 msg=slowCall 2 …: D/StrictMode(1349): at android.os.StrictModeAndroidBlockGuardPolicy.onCustomSlowCall(StrictMode.java:1105) …: D/StrictMode(1349): at android.os.StrictMode.noteSlowCall(StrictMode.java:1903) …: D/StrictMode(1349): at com.ap.teststrictmode.ActivityTestDetectCustomSlowCalls.slowCall_2(ActivityTestDetectCustomSlowCalls.java:52) …: D/StrictMode(1349): at com.ap.teststrictmode.ActivityTestDetectCustomSlowCalls.onCreate(ActivityTestDetectCustomSlowCalls.java:35) …: D/StrictMode(1349): at android.app.Activity.performCreate(Activity.java:5122) …: D/StrictMode(1349): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081) …: D/StrictMode(1349): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270) …: D/StrictMode(1349): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2358) …: D/StrictMode(1349): at android.app.ActivityThread.access600(ActivityThread.java:156) …: D/StrictMode(1349): at android.app.ActivityThreadH.handleMessage(ActivityThread.java:1340) …: D/StrictMode(1349): at android.os.Handler.dispatchMessage(Handler.java:99) …: D/StrictMode(1349): at android.os.Looper.loop(Looper.java:153) … (后面的部分省略)

    
    当然你也可以在其他线程中使用 detectCustomSlowCalls(),但是没有什么实际意义,也看不到方法执行时间,比如:  
    
    <div class="highlight">
      ```
`&lt;span class="kd">public&lt;/span> &lt;span class="kd">class&lt;/span> &lt;span class="nc">ActivityTestDetectCustomSlowCalls&lt;/span> &lt;span class="kd">extends&lt;/span> &lt;span class="n">Activity&lt;/span> &lt;span class="o">{&lt;/span>
    
    &lt;span class="kd">private&lt;/span> &lt;span class="n">TextView&lt;/span> &lt;span class="n">textView&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="o">;&lt;/span>
    
    &lt;span class="nd">@Override&lt;/span>
    &lt;span class="kd">protected&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">Bundle&lt;/span> &lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>
        &lt;span class="kd">super&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">);&lt;/span>
        &lt;span class="n">setContentView&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">activity_main&lt;/span>&lt;span class="o">);&lt;/span>

        &lt;span class="k">this&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">textView&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">TextView&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">findViewById&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">id&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">text_view&lt;/span>&lt;span class="o">);&lt;/span>
        
        &lt;span class="k">this&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">textView&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">setText&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="s">"In ActivityTestDetectCustomSlowCalls"&lt;/span>&lt;span class="o">);&lt;/span>
        
        &lt;span class="k">new&lt;/span> &lt;span class="nf">Thread&lt;/span>&lt;span class="o">(){&lt;/span>
            &lt;span class="kd">public&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">run&lt;/span>&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
                &lt;span class="n">StrictMode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">setThreadPolicy&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">ThreadPolicy&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">Builder&lt;/span>&lt;span class="o">()&lt;/span>
                    &lt;span class="o">.&lt;/span>&lt;span class="na">detectCustomSlowCalls&lt;/span>&lt;span class="o">()&lt;/span>
                    &lt;span class="o">.&lt;/span>&lt;span class="na">penaltyLog&lt;/span>&lt;span class="o">()&lt;/span>
                    &lt;span class="o">.&lt;/span>&lt;span class="na">build&lt;/span>&lt;span class="o">());&lt;/span>
                
                &lt;span class="k">this&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">slowCallInCustomThread&lt;/span>&lt;span class="o">();&lt;/span>
            &lt;span class="o">};&lt;/span>
            
            &lt;span class="kd">private&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">slowCallInCustomThread&lt;/span>&lt;span class="o">(){&lt;/span>
                &lt;span class="c1">//用来标记潜在执行比较慢的方法&lt;/span>
                &lt;span class="n">StrictMode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">noteSlowCall&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="s">"slowCallInCustomThread"&lt;/span>&lt;span class="o">);&lt;/span>
                &lt;span class="n">SystemClock&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">sleep&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="mi">1000&lt;/span> &lt;span class="o">*&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="o">);&lt;/span>
            &lt;span class="o">}&lt;/span>            
        &lt;span class="o">}.&lt;/span>&lt;span class="na">start&lt;/span>&lt;span class="o">();;&lt;/span>
    &lt;span class="o">}&lt;/span>
&lt;span class="o">}&lt;/span>
`
</div>

日志输出如下:

```

…: D/StrictMode(2418): StrictMode policy violation: android.os.StrictModeStrictModeCustomViolation: policy=24 violation=8 msg=slowCallInCustomThread …: D/StrictMode(2418): at android.os.StrictModeAndroidBlockGuardPolicy.onCustomSlowCall(StrictMode.java:1105) …: D/StrictMode(2418): at android.os.StrictMode.noteSlowCall(StrictMode.java:1903) …: D/StrictMode(2418): at com.ap.teststrictmode.ActivityTestDetectCustomSlowCalls1.slowCallInCustomThread(ActivityTestDetectCustomSlowCalls.java:35) …: D/StrictMode(2418): at com.ap.teststrictmode.ActivityTestDetectCustomSlowCalls1.run(ActivityTestDetectCustomSlowCalls.java:30) … (后面的部分省略)

    
      * penaltyDeath(),当触发违规条件时,直接Crash掉当前应用程序。
      * penaltyDeathOnNetwork(),当触发网络违规时,Crash掉当前应用程序。
      * penaltyDialog(),触发违规时,显示对违规信息对话框。
      * penaltyFlashScreen(),会造成屏幕闪烁,不过一般的设备可能没有这个功能。
      * penaltyDropBox(),将违规信息记录到 dropbox 系统日志目录中(/data/system/dropbox),你可以通过如下命令进行插件: 
        ```
*adb shell dumpsys dropbox data*app*strictmode  --print*
    会得到如下的信息:
    
    ```

2014-05-04 14:56:32 dataappstrictmode (text, 2627 bytes) Process: com.ap.teststrictmode Flags: 0x40a8be46 Package: com.ap.teststrictmode v1 (1.0) Build: Xiaomi/pisces/pisces:4.2.1/JOP40D/JXCCNBA13.0:user/release-keys System-App: false Uptime-Millis: 66679049 Loop-Violation-Number: 10 Duration-Millis: 24 android.os.StrictModeStrictModeNetworkViolation: policy=191 violation=4 at android.os.StrictModeAndroidBlockGuardPolicy.onNetwork(StrictMode.java:1136) at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:163) at libcore.io.IoBridge.recvfrom(IoBridge.java:513) at java.net.PlainSocketImpl.read(PlainSocketImpl.java:488) at java.net.PlainSocketImpl.access000(PlainSocketImpl.java:46) at java.net.PlainSocketImplPlainSocketInputStream.read(PlainSocketImpl.java:240) at java.io.InputStream.read(InputStream.java:163) at java.io.BufferedInputStream.fillbuf(BufferedInputStream.java:142) at java.io.BufferedInputStream.read(BufferedInputStream.java:227) at libcore.io.Streams.readAsciiLine(Streams.java:201) at libcore.net.http.ChunkedInputStream.readChunkSize(ChunkedInputStream.java:77) at libcore.net.http.ChunkedInputStream.read(ChunkedInputStream.java:68) at java.io.InputStream.read(InputStream.java:163) at java.util.zip.InflaterInputStream.fill(InflaterInputStream.java:200) at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:154) at java.util.zip.GZIPInputStream.read(GZIPInputStream.java:167) …

    
      * permitCustomSlowCalls()、permitDiskReads ()、permitDiskWrites()、permitNetwork: 如果你想关闭某一项检测,可以使用对应的permit*方法。
    
    ## VMPolicy 详解 {#tocAnchor-1-2-2}
    
      * detectActivityLeaks() 用户检查 Activity 的内存泄露情况,比如下面的代码:
    
    <div class="highlight">
      ```
`&lt;span class="kd">public&lt;/span> &lt;span class="kd">class&lt;/span> &lt;span class="nc">ActivityTestActivityLeaks&lt;/span> &lt;span class="kd">extends&lt;/span> &lt;span class="n">Activity&lt;/span> &lt;span class="o">{&lt;/span>
    
    &lt;span class="kd">private&lt;/span> &lt;span class="kd">static&lt;/span> &lt;span class="kt">boolean&lt;/span> &lt;span class="n">isStrictMode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="o">;&lt;/span>
    
    &lt;span class="nd">@Override&lt;/span>
    &lt;span class="kd">protected&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">Bundle&lt;/span> &lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>
        &lt;span class="kd">super&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">);&lt;/span>
        &lt;span class="n">setContentView&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">activity_main&lt;/span>&lt;span class="o">);&lt;/span>

        &lt;span class="k">if&lt;/span>&lt;span class="o">(!&lt;/span> &lt;span class="n">isStrictMode&lt;/span>&lt;span class="o">){&lt;/span>
            
            &lt;span class="n">StrictMode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">setVmPolicy&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">VmPolicy&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">Builder&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">detectActivityLeaks&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">penaltyLog&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">build&lt;/span>&lt;span class="o">());&lt;/span>
            &lt;span class="n">isStrictMode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="o">;&lt;/span>
        &lt;span class="o">}&lt;/span>
        
        &lt;span class="k">new&lt;/span> &lt;span class="nf">Thread&lt;/span>&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
              &lt;span class="nd">@Override&lt;/span>
              &lt;span class="kd">public&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">run&lt;/span>&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
                &lt;span class="k">while&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="kc">true&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>
                    
                  &lt;span class="n">SystemClock&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">sleep&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="mi">1000&lt;/span>&lt;span class="o">);&lt;/span>
                &lt;span class="o">}&lt;/span>
              &lt;span class="o">}&lt;/span>
        &lt;span class="o">}.&lt;/span>&lt;span class="na">start&lt;/span>&lt;span class="o">();&lt;/span>
    &lt;span class="o">}&lt;/span>
&lt;span class="o">}&lt;/span>
`
</div>

我们反复旋转屏幕就会输出如下信息(重点在 instances=4; limit=1 这一行):

```

…: E/StrictMode(4784): class com.ap.teststrictmode.ActivityTestActivityLeaks; instances=4; limit=1 …: E/StrictMode(4784): android.os.StrictMode$InstanceCountViolation: class com.ap.teststrictmode.ActivityTestActivityLeaks; instances=4; limit=1 …: E/StrictMode(4784): at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)

    
    这时因为,我们在Activity中创建了一个Thread匿名内部类,而匿名内部类隐式持有外部类的引用。而每次旋转屏幕是,Android会新创建一个Activity,而原来的Activity实例又被我们启动的匿名内部类线程持有,所以不会释放,从日志上看,当先系统中该Activty有4个实例,而限制是只能创建1各实例。我们不断翻转屏幕,instances 的个数还会持续增加。
    
      * detectLeakedClosableObjects() 和 detectLeakedSqlLiteObjects(),资源没有正确关闭时回触发,比如下面的代码:
    
    <div class="highlight">
      ```
` 
&lt;span class="kd">public&lt;/span> &lt;span class="kd">class&lt;/span> &lt;span class="nc">MainActivityTestDetectLeakedClosableObjects&lt;/span> &lt;span class="kd">extends&lt;/span> &lt;span class="n">Activity&lt;/span> &lt;span class="o">{&lt;/span>
    
    &lt;span class="kd">private&lt;/span> &lt;span class="kd">static&lt;/span> &lt;span class="kt">boolean&lt;/span> &lt;span class="n">isStrictMode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="o">;&lt;/span>
    
    &lt;span class="nd">@Override&lt;/span>
    &lt;span class="kd">protected&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">Bundle&lt;/span> &lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>
        &lt;span class="kd">super&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">);&lt;/span>
        &lt;span class="n">setContentView&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">activity_main&lt;/span>&lt;span class="o">);&lt;/span>

        
        &lt;span class="k">if&lt;/span>&lt;span class="o">(!&lt;/span> &lt;span class="n">isStrictMode&lt;/span>&lt;span class="o">){&lt;/span>
            &lt;span class="n">StrictMode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">setVmPolicy&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">VmPolicy&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">Builder&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">detectLeakedClosableObjects&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">penaltyLog&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">build&lt;/span>&lt;span class="o">());&lt;/span>
            &lt;span class="n">isStrictMode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="o">;&lt;/span>
        &lt;span class="o">}&lt;/span>
        
        &lt;span class="n">File&lt;/span> &lt;span class="n">newxmlfile&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">File&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">Environment&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">getExternalStorageDirectory&lt;/span>&lt;span class="o">(),&lt;/span> &lt;span class="s">"aaa.txt"&lt;/span>&lt;span class="o">);&lt;/span>
        &lt;span class="k">try&lt;/span> &lt;span class="o">{&lt;/span>
            &lt;span class="n">newxmlfile&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">createNewFile&lt;/span>&lt;span class="o">();&lt;/span>
            &lt;span class="n">FileWriter&lt;/span> &lt;span class="n">fw&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">FileWriter&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">newxmlfile&lt;/span>&lt;span class="o">);&lt;/span>
            &lt;span class="n">fw&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">write&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="s">"aaaaaaaaaaa"&lt;/span>&lt;span class="o">);&lt;/span>
            &lt;span class="c1">//fw.close(); 我们在这里故意没有关闭 fw&lt;/span>
        &lt;span class="o">}&lt;/span> &lt;span class="k">catch&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">IOException&lt;/span> &lt;span class="n">e&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>
            &lt;span class="n">e&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">printStackTrace&lt;/span>&lt;span class="o">();&lt;/span>
        &lt;span class="o">}&lt;/span>

    &lt;span class="o">}&lt;/span>
&lt;span class="o">}&lt;/span>
`
</div>

会产生如下异常信息:

```

… E/StrictMode(22056): A resource was acquired at attached stack trace but never released. See java.io.Closeable for information on avoiding resource leaks. … E/StrictMode(22056): java.lang.Throwable: Explicit termination method ‘close’ not called … E/StrictMode(22056): at dalvik.system.CloseGuard.open(CloseGuard.java:184) … E/StrictMode(22056): at java.io.FileOutputStream.(FileOutputStream.java:90) … E/StrictMode(22056): at java.io.FileOutputStream.(FileOutputStream.java:73) … E/StrictMode(22056): at java.io.FileWriter.(FileWriter.java:42) … E/StrictMode(22056): at com.ap.teststrictmode.MainActivityTestDetectLeakedClosableObjects.onCreate(MainActivityTestDetectLeakedClosableObjects.java:44) … E/StrictMode(22056): at android.app.Activity.performCreate(Activity.java:5122) … E/StrictMode(22056): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1081) … E/StrictMode(22056): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270) … E/StrictMode(22056): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2358) … E/StrictMode(22056): at android.app.ActivityThread.handleRelaunchActivity(ActivityThread.java:3865) (后面的省略)

    
    detectLeakedSqlLiteObjects() 和 detectLeakedClosableObjects()的用法类似,只不过是用来检查 SQLiteCursor 或者 其他 SQLite 对象是否被正确关闭。
    
      * detectLeakedRegistrationObjects() 用来检查 BroadcastReceiver 或者 ServiceConnection 注册类对象是否被正确释放,看下面的代码
    
    <div class="highlight">
      ```
`&lt;span class="kd">public&lt;/span> &lt;span class="kd">class&lt;/span> &lt;span class="nc">ActivityTestLeakedRegistrationObjects&lt;/span> &lt;span class="kd">extends&lt;/span> &lt;span class="n">Activity&lt;/span> &lt;span class="o">{&lt;/span>
    &lt;span class="kd">private&lt;/span> &lt;span class="n">TextView&lt;/span> &lt;span class="n">textView&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="o">;&lt;/span>
    &lt;span class="kd">private&lt;/span> &lt;span class="kd">static&lt;/span> &lt;span class="kt">boolean&lt;/span> &lt;span class="n">isStrictMode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="o">;&lt;/span>
    &lt;span class="kd">private&lt;/span> &lt;span class="n">MyReceiver&lt;/span> &lt;span class="n">receiver&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">null&lt;/span>&lt;span class="o">;&lt;/span>
    
    &lt;span class="nd">@Override&lt;/span>
    &lt;span class="kd">protected&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">Bundle&lt;/span> &lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>
        &lt;span class="kd">super&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">);&lt;/span>
        &lt;span class="n">setContentView&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">activity_main&lt;/span>&lt;span class="o">);&lt;/span>

        &lt;span class="k">this&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">textView&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="o">(&lt;/span>&lt;span class="n">TextView&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="n">findViewById&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">id&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">text_view&lt;/span>&lt;span class="o">);&lt;/span>
        
        &lt;span class="k">this&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">textView&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">setText&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="s">"In ActivityTestLeakedRegistrationObjects"&lt;/span>&lt;span class="o">);&lt;/span>

        
        &lt;span class="k">if&lt;/span>&lt;span class="o">(!&lt;/span> &lt;span class="n">isStrictMode&lt;/span>&lt;span class="o">){&lt;/span>
            &lt;span class="n">StrictMode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">setVmPolicy&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">VmPolicy&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">Builder&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">detectLeakedRegistrationObjects&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">penaltyLog&lt;/span>&lt;span class="o">()&lt;/span>
            &lt;span class="o">.&lt;/span>&lt;span class="na">build&lt;/span>&lt;span class="o">());&lt;/span>
            &lt;span class="n">isStrictMode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="o">;&lt;/span>
        &lt;span class="o">}&lt;/span>
        
        &lt;span class="k">this&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">receiver&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">MyReceiver&lt;/span>&lt;span class="o">();&lt;/span>  
        &lt;span class="n">IntentFilter&lt;/span> &lt;span class="n">filter&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">IntentFilter&lt;/span>&lt;span class="o">();&lt;/span>  
        &lt;span class="n">filter&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">addAction&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="s">"android.intent.action.MY_BROADCAST"&lt;/span>&lt;span class="o">);&lt;/span> 
        &lt;span class="n">registerReceiver&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">this&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">receiver&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="n">filter&lt;/span>&lt;span class="o">);&lt;/span> 
    &lt;span class="o">}&lt;/span>
    
    &lt;span class="nd">@Override&lt;/span>
    &lt;span class="kd">protected&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">onDestroy&lt;/span>&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
        &lt;span class="kd">super&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">onDestroy&lt;/span>&lt;span class="o">();&lt;/span>
    &lt;span class="o">}&lt;/span>
&lt;span class="o">}&lt;/span>
`
</div>

输入信息如下:

```

…: E/ActivityThread(24442): Activity com.ap.teststrictmode.ActivityTestLeakedRegistrationObjects has leaked IntentReceiver com.ap.teststrictmode.MyReceiver@41f1f128 that was originally registered here. Are you missing a call to unregisterReceiver()? …: E/ActivityThread(24442): android.app.IntentReceiverLeaked: Activity com.ap.teststrictmode.ActivityTestLeakedRegistrationObjects has leaked IntentReceiver com.ap.teststrictmode.MyReceiver@41f1f128 that was originally registered here. Are you missing a call to unregisterReceiver()? …: E/ActivityThread(24442): at android.app.LoadedApk$ReceiverDispatcher.(LoadedApk.java:825) …: E/ActivityThread(24442): at android.app.LoadedApk.getReceiverDispatcher(LoadedApk.java:596) …: E/ActivityThread(24442): at android.app.ContextImpl.registerReceiverInternal(ContextImpl.java:1388) …: E/ActivityThread(24442): at android.app.ContextImpl.registerReceiver(ContextImpl.java:1368) …

    
    正确做法应该是在 onDestroy() 方法中将 receiver 释放掉:
    
    <div class="highlight">
      ```
` &lt;span class="nd">@Override&lt;/span>
    &lt;span class="kd">protected&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">onDestroy&lt;/span>&lt;span class="o">()&lt;/span> &lt;span class="o">{&lt;/span>
        &lt;span class="n">unregisterReceiver&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">this&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">receiver&lt;/span>&lt;span class="o">);&lt;/span>
        &lt;span class="kd">super&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">onDestroy&lt;/span>&lt;span class="o">();&lt;/span>
    &lt;span class="o">}&lt;/span>
`
</div>

  * setClassInstanceLimit(),设置某个类的同时处于内存中的实例上限,可以协助检查内存泄露。比如下面的代码:

<div class="highlight">
  ```

`<span class=“kd”>public</span> <span class=“kd”>class</span> <span class=“nc”>ActivityTestObjectLimit</span> <span class=“kd”>extends</span> <span class=“n”>Activity</span> <span class=“o”>{</span> <span class=“kd”>private</span> <span class=“kd”>static</span> <span class=“kd”>class</span> <span class=“nc”>MyClass</span><span class=“o”>{}</span>

&lt;span class="kd">private&lt;/span> &lt;span class="kd">static&lt;/span> &lt;span class="kt">boolean&lt;/span> &lt;span class="n">isStrictMode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">false&lt;/span>&lt;span class="o">;&lt;/span>

&lt;span class="kd">private&lt;/span> &lt;span class="kd">static&lt;/span> &lt;span class="n">List&lt;/span>&lt;span class="o">&lt;&lt;/span>&lt;span class="n">MyClass&lt;/span>&lt;span class="o">&gt;&lt;/span> &lt;span class="n">classList&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="k">new&lt;/span> &lt;span class="n">ArrayList&lt;/span>&lt;span class="o">&lt;&lt;/span>&lt;span class="n">ActivityTestObjectLimit&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">MyClass&lt;/span>&lt;span class="o">&gt;();&lt;/span>

&lt;span class="nd">@Override&lt;/span>
&lt;span class="kd">protected&lt;/span> &lt;span class="kt">void&lt;/span> &lt;span class="nf">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">Bundle&lt;/span> &lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">)&lt;/span> &lt;span class="o">{&lt;/span>
    &lt;span class="kd">super&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">onCreate&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">savedInstanceState&lt;/span>&lt;span class="o">);&lt;/span>
    &lt;span class="n">setContentView&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">R&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">layout&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">activity_main&lt;/span>&lt;span class="o">);&lt;/span>

    &lt;span class="k">if&lt;/span>&lt;span class="o">(!&lt;/span> &lt;span class="n">isStrictMode&lt;/span>&lt;span class="o">){&lt;/span>
        &lt;span class="n">StrictMode&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">setVmPolicy&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">VmPolicy&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">Builder&lt;/span>&lt;span class="o">()&lt;/span>
        &lt;span class="o">.&lt;/span>&lt;span class="na">setClassInstanceLimit&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="n">MyClass&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">class&lt;/span>&lt;span class="o">,&lt;/span> &lt;span class="mi">2&lt;/span>&lt;span class="o">)&lt;/span>
        &lt;span class="o">.&lt;/span>&lt;span class="na">penaltyLog&lt;/span>&lt;span class="o">()&lt;/span>
        &lt;span class="o">.&lt;/span>&lt;span class="na">build&lt;/span>&lt;span class="o">());&lt;/span>
        &lt;span class="n">isStrictMode&lt;/span> &lt;span class="o">=&lt;/span> &lt;span class="kc">true&lt;/span>&lt;span class="o">;&lt;/span>
    &lt;span class="o">}&lt;/span>
    
    &lt;span class="n">classList&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">add&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">MyClass&lt;/span>&lt;span class="o">());&lt;/span>
    &lt;span class="n">classList&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">add&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">MyClass&lt;/span>&lt;span class="o">());&lt;/span>
    &lt;span class="n">classList&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">add&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">MyClass&lt;/span>&lt;span class="o">());&lt;/span>
    &lt;span class="n">classList&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">add&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">MyClass&lt;/span>&lt;span class="o">());&lt;/span>
    &lt;span class="n">classList&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">add&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">MyClass&lt;/span>&lt;span class="o">());&lt;/span>
    &lt;span class="n">classList&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">add&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">MyClass&lt;/span>&lt;span class="o">());&lt;/span>
    &lt;span class="n">classList&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">add&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">MyClass&lt;/span>&lt;span class="o">());&lt;/span>
    &lt;span class="n">classList&lt;/span>&lt;span class="o">.&lt;/span>&lt;span class="na">add&lt;/span>&lt;span class="o">(&lt;/span>&lt;span class="k">new&lt;/span> &lt;span class="n">MyClass&lt;/span>&lt;span class="o">());&lt;/span>
&lt;span class="o">}&lt;/span>

<span class=“o”>}</span> `

    </div>
    
    日志信息如下:
    
    ```
...: E/StrictMode(27681): class com.ap.teststrictmode.ActivityTestObjectLimit<span class="katex math inline">MyClass; instances=72; limit=2
...: E/StrictMode(27681): android.os.StrictMode</span>InstanceCountViolation: class com.ap.teststrictmode.ActivityTestObjectLimit$MyClass; instances=8; limit=2
...: E/StrictMode(27681):   at android.os.StrictMode.setClassInstanceLimit(StrictMode.java:1)
注意:上面的异常一般都在GC之后抛出,如果测试的时候没有现象,可以多翻转几次屏幕,或者通过DDMS工具手动触发一下。

💬 评论