什么是 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运行流程(推荐)所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)