欧美一区二区三区老妇人-欧美做爰猛烈大尺度电-99久久夜色精品国产亚洲a-亚洲福利视频一区二区

Android高質(zhì)量開發(fā)之崩潰優(yōu)化

前言

成都創(chuàng)新互聯(lián)是專業(yè)的古雷港網(wǎng)站建設(shè)公司,古雷港接單;提供網(wǎng)站設(shè)計、成都網(wǎng)站制作,網(wǎng)頁設(shè)計,網(wǎng)站設(shè)計,建網(wǎng)站,PHP網(wǎng)站建設(shè)等專業(yè)做網(wǎng)站服務(wù);采用PHP框架,可快速的進(jìn)行古雷港網(wǎng)站開發(fā)網(wǎng)頁制作和功能擴(kuò)展;專業(yè)做搜索引擎喜愛的網(wǎng)站,專業(yè)的做網(wǎng)站團(tuán)隊,希望更多企業(yè)前來合作!

開發(fā)人員碰到 APP 崩潰(閃退)什么辦?不少人會說根據(jù) Log,找到閃退的代碼,捕獲異常,“消化”掉了所有 Java 崩潰。
至于程序是否會出現(xiàn)其他異常表現(xiàn),那是上帝要管的事情。

是的,這種方法對于緊急情況下不失為一種解決辦法,但閃退的真相是什么?
是否從根源上解決問題呢?

Android 高質(zhì)量開發(fā)之崩潰優(yōu)化
2335ef9c182d46e48155842a39212d54.jpg

一、崩潰

崩潰率是衡量一個應(yīng)用質(zhì)量高低的基本指標(biāo),那么,該怎樣客觀地衡量崩潰這個指標(biāo),以及又該如何看待和崩潰相關(guān)的穩(wěn)定性。

Android 的兩種崩潰:

  • Java 崩潰
  • Native 崩潰

簡單來說,Java 崩潰就是在 Java 代碼中,出現(xiàn)了未捕獲異常,導(dǎo)致程序異常退出。

那 Native 崩潰一般都是因為在 Native 代碼中訪問非法地址,也可能是地址對齊出現(xiàn)了問題,或者發(fā)生了程序主動 Abort,這些都會產(chǎn)生相應(yīng)的 Signal 信號,導(dǎo)致程序異常退出。

1.1 崩潰的收集

“崩潰”就是程序出現(xiàn)異常,而一個產(chǎn)品的崩潰率,跟我們?nèi)绾尾东@、處理這些異常有比較大的關(guān)系。

對于很多中小型公司來說,可以選擇一些第三方的服務(wù)。

目前各種平臺也是百花齊放,包括阿里的友盟、騰訊的Bugly、網(wǎng)易云捕、Google 的 Firebase 等等。要懂得借力!

1.2 ANR

崩潰率是不是就能完全等價于應(yīng)用的穩(wěn)定性呢?答案是肯定不行。處理了崩潰,我們還會經(jīng)常遇到 ANR(Application Not Responding,程序沒有響應(yīng))這個問題。

出現(xiàn) ANR 的時候,系統(tǒng)還會彈出對話框打斷用戶的操作,這是用戶非常不能忍受的。

ANR處理方法:

使用 FileObserver 監(jiān)聽 /data/anr/traces.txt 的變化。
非常不幸的是,很多高版本的 ROM,已經(jīng)沒有讀取這個文件的權(quán)限了。

這個時候你可能只能思考其他路徑,海外可以使用 Google Play 服務(wù),而國內(nèi)微信利用Hardcoder框架(HC 框架是一套獨立于安卓系統(tǒng)實現(xiàn)的通信框架,它讓 App 和廠商 ROM 能夠?qū)崟r“對話”了

目標(biāo)就是充分調(diào)度系統(tǒng)資源來提升 App 的運行速度和畫質(zhì),切實提高大家的手機(jī)使用體驗)向廠商獲取了更大的權(quán)限。
也可以將手機(jī) ROOT 掉,然后取得 traces.txt 文件。

1.3 應(yīng)用退出

除了常見的崩潰,還有一些會導(dǎo)致應(yīng)用異常退出的情況,例如:

  • 主動自殺。Process.killProcess()、exit() 等
  • 崩潰。出現(xiàn)了 Java 或 Native 崩潰
  • 系統(tǒng)重啟。系統(tǒng)出現(xiàn)異常、斷電、用戶主動重啟等,我們可以通過比較應(yīng)用開機(jī)運行時間是否比之前記錄的值更小
  • 被系統(tǒng)殺死。被 low memory killer 殺掉、從系統(tǒng)的任務(wù)管理器中劃掉等
  • ANR

我們可以在應(yīng)用啟動的時候設(shè)定一個標(biāo)志,在主動自殺或崩潰后更新標(biāo)志,這樣下次啟動時通過檢測這個標(biāo)志就能確認(rèn)運行期間是否發(fā)生過異常退出。

對應(yīng)上面的五種退出場景,我們排除掉主動自殺和崩潰(崩潰會單獨的統(tǒng)計)這兩種場景,希望可以監(jiān)控到剩下三種的異常退出,理論上這個異常捕獲機(jī)制是可以達(dá)到 100% 覆蓋的。

通過這個異常退出的檢測,可以反映如 ANR、low memory killer、系統(tǒng)強殺、死機(jī)、斷電等其他無法正常捕獲到的問題。

當(dāng)然異常率會存在一些誤報,比如用戶從系統(tǒng)的任務(wù)管理器中劃掉應(yīng)用。對于線上的大數(shù)據(jù)來說,還是可以幫助我們發(fā)現(xiàn)代碼中的一些隱藏問題。

根據(jù)應(yīng)用的前后臺狀態(tài),我們可以把異常退出分為前臺異常退出和后臺異常退出。

“被系統(tǒng)殺死” 是后臺異常退出的主要原因,當(dāng)然我們會更關(guān)注前臺的異常退出的情況,這會跟 ANR、OOM 等異常情況有更大的關(guān)聯(lián)。

二、崩潰處理

我們每天工作也會遇到各種各樣的疑難問題,“崩潰”就是其中比較常見的一種問題。解決問題跟破案一樣需要經(jīng)驗,我們分析的問題越多越熟練,定位問題就會越快越準(zhǔn)。

當(dāng)然這里也有很多套路,比如對于 “案發(fā)現(xiàn)場” 我們應(yīng)該留意哪些信息?怎樣找到更多的 “證人” 和 “線索” ?

“偵查案件” 的一般流程是什么?對不同類型的 “案件” 分別應(yīng)該使用什么樣的調(diào)查方式?

要相信 “真相永遠(yuǎn)只有一個”,崩潰也并不可怕。

2.1 崩潰現(xiàn)場

崩潰現(xiàn)場是我們的“第一案發(fā)現(xiàn)場”,它保留著很多有價值的線索。現(xiàn)在可以挖掘到的信息越多,下一步分析的方向就越清晰,而不是去靠盲目猜測。


崩潰信息

從崩潰的基本信息,我們可以對崩潰有初步的判斷。進(jìn)程名、線程名。

崩潰的進(jìn)程是前臺進(jìn)程還是后臺進(jìn)程,崩潰是不是發(fā)生在 UI 線程。

崩潰堆棧和類型。崩潰是屬于 Java 崩潰、Native 崩潰,還是 ANR,對于不同類型的崩潰關(guān)注的點也不太一樣。

特別需要看崩潰堆棧的棧頂,看具體崩潰在系統(tǒng)的代碼,還是 APP 代碼里面。

關(guān)鍵字:FATAL

 FATAL EXCEPTION: main
 Process: com.cchip.csmart, PID: 27456
 java.lang.NullPointerException: Attempt to invoke virtual method 'void android.widget.TextView.setText(int)' on a null object reference
 at com.cchip.alicsmart.activity.SplashActivity$1.handleMessage(SplashActivity.java:67)
 at android.os.Handler.dispatchMessage(Handler.java:102)
 at android.os.Looper.loop(Looper.java:179)
 at android.app.ActivityThread.main(ActivityThread.java:5672)
 at java.lang.reflect.Method.invoke(Native Method)
 at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
 at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:674)

系統(tǒng)信息

系統(tǒng)的信息有時候會帶有一些關(guān)鍵的線索,對我們解決問題有非常大的幫助。

Logcat。這里包括應(yīng)用、系統(tǒng)的運行日志。由于系統(tǒng)權(quán)限問題,獲取到的 Logcat 可能只包含與當(dāng)前 APP 相關(guān)的。

其中系統(tǒng)的 event logcat 會記錄 APP 運行的一些基本情況,記錄在文件 /system/etc/event-log-tags 中。

//system logcat:10-25 17:13:47.788 21430 21430 D dalvikvm: Trying to load lib ... 
//event logcat:10-25 17:13:47.788 21430 21430 I am_on_resume_called: 生命周期10-25 17:13:47.788 21430 21430 I am_low_memory: 系統(tǒng)內(nèi)存不足10-25 17:13:47.788 21430 21430 I am_destroy_activity: 銷毀 Activty10-25 17:13:47.888 21430 21430 I am_anr: ANR 以及原因10-25 17:13:47.888 21430 21430 I am_kill: APP 被殺以及原因

機(jī)型、系統(tǒng)、廠商、CPU、ABI、Linux 版本等。通過采集多達(dá)幾十個維度,這對尋找共性問題會很有幫助。


內(nèi)存信息

OOM、ANR、虛擬內(nèi)存耗盡等,很多崩潰都跟內(nèi)存有直接關(guān)系。

如果把用戶的手機(jī)內(nèi)存分為“2GB 以下”和“2GB 以上”兩個區(qū),就會發(fā)現(xiàn)“2GB 以下”用戶的崩潰率是“2GB 以上”用戶的幾倍。

系統(tǒng)剩余內(nèi)存。關(guān)于系統(tǒng)內(nèi)存狀態(tài),可以直接讀取文件 /proc/meminfo。

當(dāng)系統(tǒng)可用內(nèi)存很小(低于 MemTotal 的 10%)時,OOM、大量 GC、系統(tǒng)頻繁自殺拉起等問題都非常容易出現(xiàn)。

應(yīng)用使用內(nèi)存。包括 Java 內(nèi)存、RSS(Resident Set Size)、PSS(Proportional Set Size),我們可以得出應(yīng)用本身內(nèi)存的占用大小和分布。

PSS 和 RSS 通過 /proc/self/smap 計算,可以進(jìn)一步得到例如 apk、dex、so 等更加詳細(xì)的分類統(tǒng)計。

虛擬內(nèi)存。虛擬內(nèi)存可以通過 /proc/self/status 得到,通過 /proc/self/maps 文件可以得到具體的分布情況。

有時候我們一般不太重視虛擬內(nèi)存,但是很多類似 OOM、tgkill 等問題都是虛擬內(nèi)存不足導(dǎo)致的。

Name: com.xmamiga.name // 進(jìn)程名FDSize: 800 // 當(dāng)前進(jìn)程申請的文件句柄個數(shù)VmPeak: 3004628 kB // 當(dāng)前進(jìn)程的虛擬內(nèi)存峰值大小VmSize: 2997032 kB // 當(dāng)前進(jìn)程的虛擬內(nèi)存大小Threads: 600 // 當(dāng)前進(jìn)程包含的線程個數(shù)

一般來說,對于 32 位進(jìn)程,如果是 32 位的 CPU,虛擬內(nèi)存達(dá)到 3GB 就可能會引起內(nèi)存申請失敗的問題。如果是 64 位的 CPU,虛擬內(nèi)存一般在 3~4GB 之間。

當(dāng)然如果我們支持 64 位進(jìn)程,虛擬內(nèi)存就不會成為問題。

Google Play 要求 2019 年 8 月一定要支持 64 位,在國內(nèi)雖然支持 64 位的設(shè)備已經(jīng)在 90% 以上了,但是商店都不支持區(qū)分 CPU 架構(gòu)類型發(fā)布,普及起來需要更長的時間。


資源信息

有的時候會發(fā)現(xiàn)應(yīng)用堆內(nèi)存和設(shè)備內(nèi)存都非常充足,還是會出現(xiàn)內(nèi)存分配失敗的情況,這跟資源泄漏可能有比較大的關(guān)系。

文件句柄 fd。

文件句柄的限制可以通過 /proc/self/limits 獲得,一般單個進(jìn)程允許打開的最大文件句柄個數(shù)為 1024。

但是如果文件句柄超過 800 個就比較危險,需要將所有的 fd 以及對應(yīng)的文件名輸出到日志中,進(jìn)一步排查是否出現(xiàn)了有文件或者線程的泄漏。

opened files count 812:0 -> /dev/null1 -> /dev/log/main4 
2 -> /dev/binder3 -> /data/data/com.xmamiga.sample/files/test.config
...

線程數(shù)。當(dāng)前線程數(shù)大小可以通過上面的 status 文件得到,一個線程可能就占 2MB 的虛擬內(nèi)存,過多的線程會對虛擬內(nèi)存和文件句柄帶來壓力。

根據(jù)我的經(jīng)驗來說,如果線程數(shù)超過 400 個就比較危險。

需要將所有的線程 id 以及對應(yīng)的線程名輸出到日志中,進(jìn)一步排查是否出現(xiàn)了線程相關(guān)的問題。

 threads count 412:
 1820 com.xmamiga.crashsdk
 1844 ReferenceQueueD
 1869 FinalizerDaemon
 ...

JNI。使用 JNI 時,如果不注意很容易出現(xiàn)引用失效、引用爆表等一些崩潰。


應(yīng)用信息

除了系統(tǒng),其實我們的應(yīng)用更懂自己,可以留下很多相關(guān)的信息。崩潰場景。

崩潰發(fā)生在哪個 Activity 或 Fragment,發(fā)生在哪個業(yè)務(wù)中; 關(guān)鍵操作路徑,不同于開發(fā)過程詳細(xì)的打點日志,我們可以記錄關(guān)鍵的用戶操作路徑,這對我們復(fù)現(xiàn)崩潰會有比較大的幫助。其他自定義信息。

不同的應(yīng)用關(guān)心的重點可能不太一樣。

2.2 崩潰分析

有了這么多現(xiàn)場信息之后,就可以開始真正的“破案”之旅了。

絕大部分的 “案件” 只要肯花功夫,最后都能真相大白。不要畏懼問題,經(jīng)過耐心和細(xì)心地分析,總能敏銳地發(fā)現(xiàn)一些異常或關(guān)鍵點,并且還要敢于懷疑和驗證。


第一步:確定重點

確認(rèn)和分析重點,關(guān)鍵在于終過日志中找到重要的信息,對問題有一個大致判斷。一般來說,我建議在確定重點這一步可以關(guān)注以下幾點。

  • 確認(rèn)嚴(yán)重程度。解決崩潰也要看性價比,我們優(yōu)先解決 Top 崩潰或者對業(yè)務(wù)有重大影響
  • 例如主要功能的崩潰。不要花幾天去解決了一個邊角的崩潰,有可能下個版本就把功能刪除了。
  • 崩潰基本信息。確定崩潰的類型以及異常描述,對崩潰有大致的判斷。
  • 一般來說,大部分的簡單崩潰經(jīng)過這一步已經(jīng)可以得到結(jié)論。

Java 崩潰。Java 崩潰類型比較明顯,比如 NullPointerException 是空指針,OutOfMemoryError 是資源不足,這個時候需要去進(jìn)一步查看日志中的 “內(nèi)存信息”和“資源信息”。

Native 崩潰。需要觀察 signal、code、fault addr 等內(nèi)容,以及崩潰時 Java 的堆棧。

關(guān)于各 signal 含義的介紹,你可以查看崩潰信號介紹。

比較常見的是有 SIGSEGV 和 SIGABRT,前者一般是由于空指針、非法指針造成,后者主要因為 ANR 和調(diào)用 abort() 退出所導(dǎo)致。

ANR。先看看主線程的堆棧,是否是因為鎖等待導(dǎo)致。

接著看看 ANR 日志中 iowait、CPU、GC、system server 等信息,進(jìn)一步確定是 I/O 問題,或是 CPU 競爭問題,還是由于大量 GC 導(dǎo)致卡死。


第二步:查找共性

如果使用了上面的方法還是不能有效定位問題,我們可以嘗試查找這類崩潰有沒有什么共性。

找到了共性,也就可以進(jìn)一步找到差異,離解決問題也就更進(jìn)一步。

機(jī)型、系統(tǒng)、ROM、廠商、ABI,這些采集到的系統(tǒng)信息都可以作為維度聚合,共性問題例如是不是只出現(xiàn)在 x86 的手機(jī),是不是只有三星這款機(jī)型,是不是只在 Android 8.0 的系統(tǒng)上。

應(yīng)用信息也可以作為維度來聚合,比如正在打開的鏈接、正在播放的視頻、國家、地區(qū)等。

找到了共性,可以對你下一步復(fù)現(xiàn)問題有更明確的指引。


第三步:嘗試復(fù)現(xiàn)

如果我們已經(jīng)大概知道了崩潰的原因,為了進(jìn)一步確認(rèn)更多信息,就需要嘗試復(fù)現(xiàn)崩潰。

如果我們對崩潰完全沒有頭緒,也希望通過用戶操作路徑來嘗試重現(xiàn),然后再去分析崩潰原因。

“只要能本地復(fù)現(xiàn),我就能解”,相信這是很多開發(fā)跟測試說過的話。

有這樣的底氣主要是因為在穩(wěn)定的復(fù)現(xiàn)路徑上面,我們可以采用增加日志或使用 Debugger、GDB 等各種各樣的手段或工具做進(jìn)一步分析。

我們可能會遇到了各種各樣的奇葩問題。

比如某個廠商改了底層實現(xiàn)、新的 Android 系統(tǒng)實現(xiàn)有所更改,都需要去 Google、翻源碼,有時候還需要去摳廠商的 ROM 或手動刷 ROM。

很多疑難問題需要我們耐得住寂寞,反復(fù)猜測、反復(fù)發(fā)灰度、反復(fù)驗證。

–但這種問題還是要看問題的嚴(yán)重程序,不可撿了芝麻丟了西瓜。

2.3 系統(tǒng)崩潰

系統(tǒng)崩潰常常令我們感到非常無助,它可能是某個 Android 版本的 Bug,也可能是某個廠商修改 ROM 導(dǎo)致。這種情況下的崩潰堆棧可能完全沒有我們自己的代碼,很難直接定位問題。能做的有:

  • 查找可能的原因。通過上面的共性歸類,我們先看看是某個系統(tǒng)版本的問題,還是某個廠商特定 ROM 的問題。
  • 雖然崩潰日志可能沒有我們自己的代碼,但通過操作路徑和日志,可以找到一些懷疑的點。
  • 嘗試規(guī)避。查看可疑的代碼調(diào)用,是否使用了不恰當(dāng)?shù)?API,是否可以更換其他的實現(xiàn)方式規(guī)避。
  • Hook 解決。這里分為 Java Hook 和 Native Hook。它可能只出現(xiàn)在 Android 7.0 的系統(tǒng)中,參考 Android 8.0 的做法,直接 catch 住這個異常。
  • 如果做到了上面說的這些,以上大部分的崩潰應(yīng)該都能解決或者規(guī)避,大部分的系統(tǒng)崩潰也是如此。
  • 當(dāng)然總有一些疑難問題需要依賴到用戶的真實環(huán)境,這些需要具備類似動態(tài)跟蹤和調(diào)試的能力。

三、總結(jié)

崩潰攻防是一個長期的過程,我們盡可能地提前預(yù)防崩潰的發(fā)生,將它消滅在萌芽階段。

作為技術(shù)人員,我們不應(yīng)該盲目追求崩潰率這一個數(shù)字,應(yīng)該以用戶體驗為先,如果強行去掩蓋一些問題往往更加適得其反。

我們不應(yīng)該隨意使用 try catch 去隱藏真正的問題,要從源頭入手,了解崩潰的本質(zhì)原因,保證后面的運行流程。

在解決崩潰的過程,也要做到由點到面,不能只針對這個崩潰去解決,而應(yīng)該要考慮這一類崩潰怎么解決和預(yù)防。

當(dāng)前名稱:Android高質(zhì)量開發(fā)之崩潰優(yōu)化
文章路徑:http://chinadenli.net/article8/jpsdop.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站營銷做網(wǎng)站響應(yīng)式網(wǎng)站電子商務(wù)網(wǎng)站改版用戶體驗

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都網(wǎng)站建設(shè)公司