Android StrictMode 检测
来源:互联网 发布:遗传算法理解 编辑:程序博客网 时间:2024/05/21 18:48
StrictMode是Android为了提高性能,当在主线程进行了IO、网络等操作是,进行的严格模式检测。StrictMode有两两种级别的policy检测,Thread和dalvikvm,开启方式如下:
Thread policy:
strictmode.setthreadpolicy(new strictmode.threadpolicy.builder()
.detectdiskreads()
.detectdiskwrites()
.detectnetwork() // or .detectall() for all detectable problems
.penaltylog()
.build());
dalvikvm policy:
StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}()
.detectLeakedSqlLiteObjects()
.detectLeakedClosableObjects()
.penaltyLog()
.penaltyDeath()
.build());
打开之后,当检测到有异常时,会抛出stack信息:
08-17 17:19:28.482 D/StrictMode(20180): at android.os.StrictMode$AndroidBlockGuardPolicy.onWriteToDisk(StrictMode.java:1108)
08-17 17:19:28.482 D/StrictMode(20180): at libcore.io.BlockGuardOs.fsync(BlockGuardOs.java:96)
08-17 17:19:28.482 D/StrictMode(20180): at java.io.FileDescriptor.sync(FileDescriptor.java:74)
08-17 17:19:28.482 D/StrictMode(20180): at android.os.FileUtils.sync(FileUtils.java:161)
08-17 17:19:28.482 D/StrictMode(20180): at android.app.SharedPreferencesImpl.writeToFile(SharedPreferencesImpl.java:597)
08-17 17:19:28.482 D/StrictMode(20180): at android.app.SharedPreferencesImpl.access$800(SharedPreferencesImpl.java:52)
08-17 17:19:28.482 D/StrictMode(20180): at android.app.SharedPreferencesImpl$2.run(SharedPreferencesImpl.java:511)
08-17 17:19:28.482 D/StrictMode(20180): at android.app.SharedPreferencesImpl.enqueueDiskWrite(SharedPreferencesImpl.java:532)
08-17 17:19:28.482 D/StrictMode(20180): at android.app.SharedPreferencesImpl.access$100(SharedPreferencesImpl.java:52)
08-17 17:19:28.482 D/StrictMode(20180): at android.app.SharedPreferencesImpl$EditorImpl.commit(SharedPreferencesImpl.java:454)
08-17 17:19:28.482 D/StrictMode(20180): at android.os.Handler.dispatchMessage(Handler.java:102)
08-17 17:19:28.482 D/StrictMode(20180): at android.os.Looper.loop(Looper.java:137)
08-17 17:19:28.482 D/StrictMode(20180): at android.app.ActivityThread.main(ActivityThread.java:4998)
08-17 17:19:28.482 D/StrictMode(20180): at java.lang.reflect.Method.invokeNative(Native Method)
08-17 17:19:28.482 D/StrictMode(20180): at java.lang.reflect.Method.invoke(Method.java:515)
08-17 17:19:28.482 D/StrictMode(20180): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
08-17 17:19:28.482 D/StrictMode(20180): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
08-17 17:19:28.482 D/StrictMode(20180): at dalvik.system.NativeStart.main(Native Method)
抛出的异常里面,可以看到操作的耗时情况,及可以从stack里面找到对应的位置和进行了什么操作,显然对于在主线程里面进行了IO等异常影响性能的进行检测,是非常有用的。
栅栏里面,在application onCreate的时候,打开了StrictMode检测:
strictmode.setthreadpolicy(new strictmode.threadpolicy.builder()
.detectdiskreads()
.detectdiskwrites()
.detectnetwork() // or .detectall() for all detectable problems
.penaltylog()
.build());
但是一直没有效果,在主线程里面进行了读写大文件,依然没有看到有StrictMode policy检测的log出来,调试了半天,也不知道什么原因,甚是奇怪。突然想,竟然在栅栏里面设置StrictMode没有用,那我主动在Activity onCreate的时候设置:
public class ExampleActivity extends Activity{
...
public void onCreate(Bundle savedInstanceState){
strictmode.setthreadpolicy(new strictmode.threadpolicy.builder()
.detectdiskreads()
.detectdiskwrites()
.detectnetwork() // or .detectall() for all detectable problems
.penaltylog()
.build());
这样开启以后,StrictMode竟然起了作用,难道栅栏的设置是没有效果的?越来越搞不懂了。
查看framework StrictMode.java(在frameworks/base/core/java/android/os目录下),突然发现有StriceMode.java里面有得到thread policy的接口:
/**
* Returns the current thread's policy.
*/
public static ThreadPolicy getThreadPolicy() {
// TODO: this was a last minute Gingerbread API change (to
// introduce VmPolicy cleanly) but this isn't particularly
// optimal for users who might call this method often. This
// should be in a thread-local and not allocate on each call.
return new ThreadPolicy(getThreadPolicyMask());
}
那分别得到栅栏设置StrictMode、Activity onCreate里面设置了StrictMode、没有添加StrictMode检测三种情况的thread policy:
栅栏:
thread policy : [StrictMode.ThreadPolicy; mask=516] , vm policy : [StrictMode.VmPolicy; mask=9744]
Activity onCreate:
thread policy : [StrictMode.ThreadPolicy; mask=29] , vm policy : [StrictMode.VmPolicy; mask=9744]
无StrictMode检测:
thread policy : [StrictMode.ThreadPolicy; mask=516] , vm policy : [StrictMode.VmPolicy; mask=0]
显然可以看到栅栏设置的StrictMode跟没有设置StrictMode检测的ThreadPolicy mask是一样的,而在Activity onCreate设置的StrictMode ThreadPolicy mask却是另一个值,通过在StrictMode.java check标志位的意义后发现,栅栏设置的StrictMode跟默认值一样,没有起到我们想要的效果,当然对比在Activity onCreate的值就能看出来,有两种可能存在:
1、栅栏里面StrictMode从始至终就没有把StrictMode打开。
2、栅栏设置成功了,存在其他地方设置StrictMode,从而使栅栏设置没有效果。
第1种情况好验证,在栅栏设置了StrictMode后,马上getThreadPolicy一下,结果得到如下log:
thread policy : [StrictMode.ThreadPolicy; mask=29] , vm policy : [StrictMode.VmPolicy; mask=9744]
说明栅栏设置成功了,那就是说第2种情况导致的栅栏StrictMode无效,那在重新设置了StrictMode呢?
查看StrictMode.java的代码可以发现:
public static void setThreadPolicy(final ThreadPolicy policy) {
setThreadPolicyMask(policy.mask);
}setThreadPolicyMask(policy.mask);
}
private static voidsetThreadPolicyMask(final int policyMask) {
// In addition to the Java-level thread-local in Dalvik's
// BlockGuard, we also need to keep a native thread-local in
// Binder in order to propagate the value across Binder calls,
// even across native-only processes. The two are kept in
// sync via the callback to onStrictModePolicyChange, below.
setBlockGuardPolicy(policyMask);
// And set the Android native version...
Binder.setThreadStrictModePolicy(policyMask);
}
StriceMode的设置通过调用setThreadPolicy,然后再调用setThreadPolicyMask,在setThreadPolicyMask打印堆栈:
08-17 18:19:14.438 D/StrictDetecter(24163):at android.os.StrictMode.setThreadPolicy(Native Method)
08-17 18:19:14.438 D/StrictDetecter(24163):at android.app.ActivityThread.handleBindApplication(ActivityThread.java:4334)
08-17 18:19:14.438 D/StrictDetecter(24163):at android.app.ActivityThread.access$1400(ActivityThread.java:135)
08-17 18:19:14.438 D/StrictDetecter(24163):at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1457)
08-17 18:19:14.438 D/StrictDetecter(24163):at android.os.Handler.dispatchMessage(Handler.java:102)
08-17 18:19:14.438 D/StrictDetecter(24163):at android.os.Looper.loop(Looper.java:137)
08-17 18:19:14.438 D/StrictDetecter(24163):at android.app.ActivityThread.main(ActivityThread.java:4998)
08-17 18:19:14.438 D/StrictDetecter(24163):at java.lang.reflect.Method.invokeNative(Native Method)
08-17 18:19:14.438 D/StrictDetecter(24163):at java.lang.reflect.Method.invoke(Method.java:515)
08-17 18:19:14.438 D/StrictDetecter(24163):at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:777)
08-17 18:19:14.438 D/StrictDetecter(24163):at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:593)
08-17 18:19:14.438 D/StrictDetecter(24163):at dalvik.system.NativeStart.main(Native Method)
在ActivityThread.java的handleBindApplication里面进行了StrictMode操作:
private void handleBindApplication(AppBindData data) {
...
try {
mInstrumentation.callApplicationOnCreate(app);
} catch (Exception e) {
if (!mInstrumentation.onException(app, e)) {
throw new RuntimeException(
"Unable to create application " + app.getClass().getName()
+ ": " + e.toString(), e);
}
}
} finally {
StrictMode.setThreadPolicy(savedPolicy);
}
最后把savedPolicy(函数前面保存的thread policy值)设置回去,似乎没有起到效果,Google的bug?不得而知。
终于知道原因了,栅栏在Application起来的时候设置StrictMode检测,framework在Activity 起来的时候会再设置一次,改变了原来的值,导致栅栏前面的设置没有效果,或者说栅栏设置StrictMode的时机不对,可以修改栅栏在Activity 起来的时候设置,避免这样的问题。
我不知道同事看了几天这个问题,但我知道我为此问题花费了不少于两天的时间,我本来是寄希望与同事的(技术高手),想放弃了,看了一两天后还是一点头绪都没有,到最后分析StrictMode.java时,看到有getThreadPolicy的接口时,打印policy的值,对比各种情况,才看到了一点曙光,最后一起联调,解决这个问题。不得不说,使用对比的方式去分析问题,有时真能得到意想不到的效果,无论是在性能分析,还是在其他地方(debug、生活、工作),因此记录一下,希望自己以后能更好的利用这种方法
- Android StrictMode 检测
- Android中用StrictMode检测内存泄露
- android strictmode
- 【Android】StrictMode
- Android开发响应检测及内存分析 - 【StrictMode】
- android内存泄漏检测StrictMode和MAT工具使用
- StrictMode检测内存泄漏
- android StrictMode学习android StrictMode学习
- android 2.3 api StrictMode
- android 2.3 StrictMode 使用
- ANDROID StrictMode 使用
- Android StrictMode 介绍
- Android中的StrictMode
- Android Developers:StrictMode类
- Android中的StrictMode简介
- android 2.3 StrictMode 使用
- ANDROID StrictMode 使用
- Android StrictMode学习
- 解决登录Odoo(OpenERP)时的Postgresql数据库编码错误
- [leetcode][search] Find Minimum in Rotated Sorted Array
- 播放视频代码
- Linux正则表达式-元字符
- Ubuntu+Apache+PHP+Mysql环境搭建(完整版)
- Android StrictMode 检测
- python 多线程
- 数据结构与算法 (二叉搜索树)
- 并查集
- 清华赵骥主任与CIO石海军研讨互联网信息化
- inline内联函数
- webkit开发前的准备工作
- android 调用系统的照相机和图库实例详解
- 五分钟一个设计模式之工厂方法模式