国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統(tǒng) > Android > 正文

Android StrictMode運(yùn)行流程(推薦)

2019-10-22 18:17:12
字體:
供稿:網(wǎng)友

什么是 StrictMode(嚴(yán)苛模式)

android/302857.html">strictmode是android在 API9后引入的檢測影響app運(yùn)行流暢性的一種機(jī)制,例如我們都知道的主線程中不允許有網(wǎng)絡(luò)操作這條規(guī)則就是嚴(yán)苛模式規(guī)則的一種.

strictmode.java 這個類中設(shè)定了許多detect標(biāo)志位例如 DETECT_NETWORK ,還有許多 penalty標(biāo)志位例如 PENALTY_NETWORK , DETECT標(biāo)志位決定strictmode是否要對這項內(nèi)容進(jìn)行檢測,PENALTY標(biāo)志位決定了在這項內(nèi)容發(fā)生時是否要拋出異常(相當(dāng)于一種懲罰機(jī)制,PENALTY的意思就是懲罰).

StrictMode 類的作用之一就是對這些標(biāo)志位進(jìn)行管理,通過 setThreadPolicy() 方法可以設(shè)定 Policy 變量中的mask值.

之后會將 POLICY 變量傳入 BlockGuard 中,BlockGuard 運(yùn)行在 Dalvik虛擬機(jī)中,對所有的異常操作進(jìn)行統(tǒng)一的管理.

Android官方文檔中對于strict mode 給出的解釋

strictmode 是一種開發(fā)工具,引入它可以使你發(fā)現(xiàn)在開發(fā)過程中產(chǎn)生的問題,并修復(fù)它們.

在 application main thread中常有UI相關(guān)的操作和動畫發(fā)生,strictmode可以在主線程中檢測硬盤和網(wǎng)絡(luò)相關(guān)的操作.將硬盤讀寫操作和網(wǎng)絡(luò)相關(guān)操作挪出主線程可以使你的app更加流暢和具有響應(yīng)性.同時為了使app更加響應(yīng)性,你可以屏蔽ANR發(fā)生時彈出的dialog.

需要注意的是,盡管android設(shè)備的硬盤類型大多為 flash memory,建立在這種存儲介質(zhì)上的文件系統(tǒng)的并發(fā)性仍然是非常有限的(速度上肯定是RAM比較快).

大部分情況下,硬盤的讀寫操作都是非常快的,但在某些情況下,后臺進(jìn)程中會運(yùn)行耗費(fèi)很大的I/O操作,在這種情況下,app的響應(yīng)速度會下降很多.

一.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.

在執(zhí)行了 setThreadPolicy()函數(shù)后會調(diào)用 setThreadPolicyMask()方法.

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

2.

在 setThreadPolicyMask()方法中,除了在java層的threadLocal中設(shè)置外,還需要在Native層也進(jìn)行一個設(shè)置.  

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,會返回一個默認(rèn)policy,默認(rèn)policy不進(jìn)行任何設(shè)置和檢測,policy對象存儲在threadLocal變量中(每個線程保存一個policy的對象),首次運(yùn)行該方法會生成一個默認(rèn)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層的代碼:

設(shè)置了policy

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

二.StrictMode如何檢測問題.

1.

CloseGuard檢測游標(biāo)是否正常關(guān)閉:

當(dāng)使用ContentResolver來查詢數(shù)據(jù)庫的時候,會返回一個CursorWrapperInner類型的Cursor對象.

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

CloseGuard對CursorWrapperInner是否正常關(guān)閉的檢測的邏輯在finalize()函數(shù)中,finalize()會在gc執(zhí)行垃圾回收的時候被調(diào)用(垃圾回收使用了GcRoot算法)

如果沒有執(zhí)行CursorWrapperInner的close()函數(shù),僅將CursorWrapperInner對象置為null,當(dāng)主動觸發(fā)gc的時候( Systemgc()),finalize()函數(shù)被調(diào)用 ,"Cursor finalized without prior close()"這段log被打印.但如果沒有將CursorWrapperInner對象置為null,這時主動觸發(fā)gc并不會引起 finalize()函數(shù)的執(zhí)行,因為CursorWrapperInner對象被強(qiáng)引用,垃圾回收器在回收時不會考慮回收強(qiáng)引用對象,即使最后內(nèi)存不足而崩潰.

經(jīng)過測試程序的測試,發(fā)現(xiàn)"Cursor finalized without prior close()"這段log在 CursorWrapperInner對象置空并執(zhí)行 System.gc()后是會打印出來的.

但是 CloseGuard中的 warnIfOpen()函數(shù)始終沒有執(zhí)行

在 CursorWrapperInner的構(gòu)造函數(shù)中,mCloseGuard執(zhí)行 open()函數(shù),在 open函數(shù)中allocationSite被賦值,而 ENABLED 變量是默認(rèn)為true的,唯一改變它的setEnabled()方法在源碼中也并沒有被調(diào)用,所以應(yīng)該是會在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()也是用來檢測數(shù)據(jù)庫游標(biāo)有沒有正常關(guān)閉,但這個函數(shù)檢測的是通過SqliteDataBase. query()得到的SqliteCursor游標(biāo)對象.

檢測位置也是在 finalize()函數(shù)中.

 /** * 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,運(yùn)行流程,android

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

橋接模式:所謂橋接模式就是將邏輯的抽象與實現(xiàn)分開的一種模式

總結(jié)

以上所述是小編給大家介紹的Android StrictMode運(yùn)行流程,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對VEVB武林網(wǎng)網(wǎng)站的支持!


注:相關(guān)教程知識閱讀請移步到Android開發(fā)頻道。
發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 天门市| 河池市| 灌南县| 新丰县| 公安县| 宽甸| 岑溪市| 定州市| 祁门县| 甘谷县| 金川县| 宜宾县| 那坡县| 天门市| 定陶县| 武川县| 宽甸| 禹城市| 若羌县| 四川省| 奈曼旗| 凌源市| 那坡县| 卢氏县| 四平市| 汪清县| 沾化县| 龙江县| 丰宁| 夹江县| 鱼台县| 和田市| 洛扎县| 万盛区| 扎囊县| 绩溪县| 德格县| 静乐县| 图木舒克市| 临清市| 张家港市|