什么是严格模式
严格模式是android在API9后引入的检测影响app运行顺畅性的机制,例如,众所周知,主线不允许网络操作的规则是一种严格的模式规则。
名为strictmode.java的类设置了许多detect标志位,如DETECT_NETWORK,并设置了许多penalty标志位,如PENALTY_NETWORK 检测标志位确定严格模式是否检测到此内容,penalty标志位是
严格模式类的一个作用是管理这些标志位,并且可以通过setThreadPolicy )方法来设置Policy变量的掩码值。
然后,POLICY变量传递给BlockGuard,BlockGuard在Dalvik虚拟机上运行,以统一管理所有异常操作。
安卓官方文档中的严格模式说明
严格模式是一种开发工具,通过引入它可以发现和修复开发中出现的问题。
应用程序主路线经常发生与UI相关的操作和动画。 严格模式允许主线程检测硬盘和与网络相关的操作。 从主线程中删除硬盘读写和网络相关操作,可以提高APP的流畅度和响应速度。 另外,为了提高app的响应性,也可以在发生ANR时阻止弹出的诊断程序。
值得注意的是,尽管android设备的许多硬盘类型是闪存存储器,但在这种存储介质上构建的文件系统的并发性仍然非常有限。 从速度上看,RAM一定更快。
在大多数情况下,硬盘读写操作非常快,但后台进程可能会执行非常大的I/O操作,这将大大降低app的响应速度。
一. setThreadPolicy ()进程
严格模式如何启动严格模式,如严格模式类文档中所述
*公共void oncreate
*if(developer_mode ) {
*严格模式. setthreadpolicy (new { @ linkthreadpolicy.builderstrictmode.thread policy.builder } ) ) ) )。
* .detectDiskReads () )
* .detectDiskWrites () )
*.detectnetwork(/or.detectall ) ) for all detectable problems
* .penaltyLog () )。
* .build ();
*严格模式. setvmpolicy (new (@ linkvmpolicy.builderstrictmode.VM policy.builder ) ) )
* .detectLeakedSqlLiteObjects ()
* .detectLeakedClosableObjects (
* .penaltyLog () )。
* .penaltyDeath () )。
* .build ();
* }
* super.onCreate (;
1.
setThreadPolicy ) )函数后,调用setThreadPolicyMask ) )方法。
公共服务语音策略(finalthreadpolicypolicy ) {
setthreadpolicymask (policy.mask;
}
2.
在setThreadPolicyMask ()方法中,除了java层threadLocal之外,还需要设定为Native层.
私有策略掩码(finalint策略掩码) {
//inadditiontothejava-level thread-localindalvik ' s
//BlockGuard,wealsoneedtokeepanativethread-localin
//binderinordertopropagatethevalueacrossbindercalls,
//evenacrossnative-only processes.thetwoarekeptin
//syncviathecallbacktoonstrictmodepolicychange,below。
setblockguardpolicy;
//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, 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运行流程,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!