Android StrictMode运行流程(推荐)

Android StrictMode运行流程(推荐),第1张

概述什么是StrictMode(严苛模式)strictmode是android在API9后引入的检测影响app运行流畅性的一种机制,例如我们都知道的主线程中不允许有网络 *** 作这条规则就是严苛模式规则的一种.

什么是 StrictMode(严苛模式)

strictmode是androID在 API9后引入的检测影响app运行流畅性的一种机制,例如我们都知道的主线程中不允许有网络 *** 作这条规则就是严苛模式规则的一种.

strictmode.java 这个类中设定了许多detect标志位例如 DETECT_NETWORK ,还有许多 penalty标志位例如 PENALTY_NETWORK , DETECT标志位决定strictmode是否要对这项内容进行检测,PENALTY标志位决定了在这项内容发生时是否要抛出异常(相当于一种惩罚机制,PENALTY的意思就是惩罚).

StrictMode 类的作用之一就是对这些标志位进行管理,通过 setThreadPolicy() 方法可以设定 Policy 变量中的mask值.

之后会将 POliCY 变量传入 BlockGuard 中,BlockGuard 运行在 Dalvik虚拟机中,对所有的异常 *** 作进行统一的管理.

AndroID官方文档中对于strict mode 给出的解释

strictmode 是一种开发工具,引入它可以使你发现在开发过程中产生的问题,并修复它们.

在 application main thread中常有UI相关的 *** 作和动画发生,strictmode可以在主线程中检测硬盘和网络相关的 *** 作.将硬盘读写 *** 作和网络相关 *** 作挪出主线程可以使你的app更加流畅和具有响应性.同时为了使app更加响应性,你可以屏蔽ANR发生时d出的dialog.

需要注意的是,尽管androID设备的硬盘类型大多为 flash memory,建立在这种存储介质上的文件系统的并发性仍然是非常有限的(速度上肯定是RAM比较快).

大部分情况下,硬盘的读写 *** 作都是非常快的,但在某些情况下,后台进程中会运行耗费很大的I/O *** 作,在这种情况下,app的响应速度会下降很多.

一.setThreadPolicy()流程

StrictMode类的文档中给出的strictmode启动方式

 * public voID onCreate() { * if (DEVELOPER_MODE) { * StrictMode.setThreadPolicy(new {@link ThreadPolicy.Builder StrictMode.ThreadPolicy.Builder}() *  .detectdiskReads() *  .detectdiskWrites() *  .detectNetwork() // or .detectAll() for all detectable problems *  .penaltyLog() *  .build()); * StrictMode.setVmPolicy(new {@link VmPolicy.Builder StrictMode.VmPolicy.Builder}() *  .detectLeakedsqlliteObjects() *  .detectLeakedClosableObjects() *  .penaltyLog() *  .penaltyDeath() *  .build()); * } * super.onCreate();

1.

在执行了 setThreadPolicy()函数后会调用 setThreadPolicyMask()方法.

 public static voID setThreadPolicy(final ThreadPolicy policy) { setThreadPolicyMask(policy.mask); }

2.

在 setThreadPolicyMask()方法中,除了在java层的threadLocal中设置外,还需要在Native层也进行一个设置.  

private static voID setThreadPolicyMask(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); }

3.

首先分析java层的 setBlockGuardPolicy()方法.

如果policyMask==0,会返回一个默认policy,默认policy不进行任何设置和检测,policy对象存储在threadLocal变量中(每个线程保存一个policy的对象),首次运行该方法会生成一个默认policy(mMask=0)保存在threadLocal中,这里的policy对象是AndroIDBlockGuardPolicy类型.   

// Sets the policy in Dalvik/libcore (BlockGuard) private static voID setBlockGuardPolicy(final int policyMask) { if (policyMask == 0) { BlockGuard.setThreadPolicy(BlockGuard.LAX_POliCY); return; } final BlockGuard.Policy policy = BlockGuard.getThreadPolicy(); final AndroIDBlockGuardPolicy androIDPolicy; if (policy instanceof AndroIDBlockGuardPolicy) { androIDPolicy = (AndroIDBlockGuardPolicy) policy; } else { androIDPolicy = threadAndroIDPolicy.get(); BlockGuard.setThreadPolicy(androIDPolicy); } androIDPolicy.setPolicyMask(policyMask); }

4.

再看Native层的代码:

设置了policy

386voID IPCThreadState::setStrictModePolicy(int32_t policy)387{388 mStrictModePolicy = policy;389}

二.StrictMode如何检测问题.

1.

CloseGuard检测游标是否正常关闭:

当使用ContentResolver来查询数据库的时候,会返回一个CursorWrapperInner类型的Cursor对象.

mCursor = mResolver.query(mUri,null,null);

CloseGuard对CursorWrapperInner是否正常关闭的检测的逻辑在finalize()函数中,finalize()会在gc执行垃圾回收的时候被调用(垃圾回收使用了GcRoot算法)

如果没有执行CursorWrapperInner的close()函数,仅将CursorWrapperInner对象置为null,当主动触发gc的时候( Systemgc()),finalize()函数被调用,"Cursor finalized without prior close()"这段log被打印.但如果没有将CursorWrapperInner对象置为null,这时主动触发gc并不会引起 finalize()函数的执行,因为CursorWrapperInner对象被强引用,垃圾回收器在回收时不会考虑回收强引用对象,即使最后内存不足而崩溃.

经过测试程序的测试,发现"Cursor finalized without prior close()"这段log在 CursorWrapperInner对象置空并执行 System.gc()后是会打印出来的.

但是 CloseGuard中的 warnIfopen()函数始终没有执行

在 CursorWrapperInner的构造函数中,mCloseGuard执行 open()函数,在 open函数中allocationSite被赋值,而 ENABLED 变量是默认为true的,唯一改变它的setEnabled()方法在源码中也并没有被调用,所以应该是会在REPORTER中打印SystemLog的,但最后SystemLog并没有打印,具体原因分析不出来.       

@OverrIDe protected voID finalize() throws Throwable { try { if (mCloseGuard != null) {  mCloseGuard.warnIfopen(); } if (!mProvIDerReleased && mContentProvIDer != null) {  // Even though we are using CloseGuard,log this anyway so that  // application developers always see the message in the log.  Log.w(TAG,"Cursor finalized without prior close()");  ContentResolver.this.releaseProvIDer(mContentProvIDer); } } finally { super.finalize(); } } } public voID warnIfopen() { if (allocationSite == null || !ENABLED) { return; } String message =  ("A resource was acquired at attached stack trace but never released. "  + "See java.io.Closeable for information on avoIDing resource leaks."); REPORTER.report(message,allocationSite); } @OverrIDe public voID report (String message,Throwable allocationSite) { System.logW(message,allocationSite); } CursorWrapperInner(Cursor cursor,IContentProvIDer icp) { super(cursor); mContentProvIDer = icp; mCloseGuard.open("close"); }

2.

onsqliteObjectsLeaked()也是用来检测数据库游标有没有正常关闭,但这个函数检测的是通过sqliteDataBase. query()得到的sqliteCursor游标对象.

检测位置也是在 finalize()函数中.

 /** * Release the native resources,if they haven't been released yet. */ @OverrIDe protected voID finalize() { try { // if the cursor hasn't been closed yet,close it first if (mWindow != null) { if (mStackTrace != null) {  String sql = mquery.getsql();  int len = sql.length();  StrictMode.onsqliteObjectLeaked(  "Finalizing a Cursor that has not been deactivated or closed. " +  "database = " + mquery.getDatabase().getLabel() +  ",table = " + mEdittable +  ",query = " + sql.substring(0,(len > 1000) ? 1000 : len),mStackTrace); } close(); } } finally { super.finalize(); } }

流程如下图

三.StrictMode中使用到的桥接模式

桥接模式:所谓桥接模式就是将逻辑的抽象与实现分开的一种模式

总结

以上所述是小编给大家介绍的AndroID StrictMode运行流程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对编程小技巧网站的支持!

您可能感兴趣的文章:详解Android StrictMode严格模式的使用方法Android严苛模式StrictMode使用详解Android性能调优利器StrictMode应用分析 总结

以上是内存溢出为你收集整理的Android StrictMode运行流程(推荐)全部内容,希望文章能够帮你解决Android StrictMode运行流程(推荐)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1143112.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-31
下一篇 2022-05-31

发表评论

登录后才能评论

评论列表(0条)

保存