1. 程式人生 > >Android跨程序異常分析小結

Android跨程序異常分析小結

通常,我們編寫執行Android時,該程式若在一個程序中。若程式有缺陷,如空指標,將會產生空指標異常。 當異常發生時,其呼叫堆疊將會輸出到log中,通過檢視呼叫堆疊,很快可以找到問題的根源,從而解決問題。

但當我們使用Service,通過AIDL跨程序呼叫(或直接編寫Binder IPC的跨程序呼叫)時,需要使用Parcel跨程序傳遞資料。有時這種跨程序呼叫會產生異常,這時問題稍顯複雜一些。一個跨程序異常log示例如下:

07-17 16:28:53.969: V/DemoActivity3.MySessionListener(21000): onLeftSession.
07-17 16:28:54.019: D/dalvikvm(21000): GC_CONCURRENT freed 661K, 54% free 3108K/6727K, external 1657K/2137K, paused 3ms+2ms


07-17 16:28:55.769: I/DemoActivity3(21000): mLogoutButton clicked
07-17 16:28:55.779: D/AndroidRuntime(21000): Shutting down VM
07-17 16:28:55.779: W/dalvikvm(21000): threadid=1: thread exiting with uncaught exception (group=0×40015560)
07-17 16:28:55.789: E/AndroidRuntime(21000): FATAL EXCEPTION: main
07-17 16:28:55.789: E/AndroidRuntime(21000): java.lang.SecurityException

07-17 16:28:55.789: E/AndroidRuntime(21000): at android.os.Parcel.readException(Parcel.java:1322)
07-17 16:28:55.789: E/AndroidRuntime(21000): at android.os.Parcel.readException(Parcel.java:1276)
07-17 16:28:55.789: E/AndroidRuntime(21000): at com.redwolfsoft.xxx.sdk3.internal.ISessionService$Stub$Proxy.sendAction(ISessionService.java:320)

07-17 16:28:55.789: E/AndroidRuntime(21000): at com.redwolfsoft.xxx.sdk3.SessionManager.leaveSession(SessionManager.java:351)
07-17 16:28:55.789: E/AndroidRuntime(21000): at ccom.redwolfsoft.xxx.sdkdemo3.DemoActivity3$5.onClick(DemoActivity3.java:602)
07-17 16:28:55.789: E/AndroidRuntime(21000): at android.view.View.performClick(View.java:2485)
07-17 16:28:55.789: E/AndroidRuntime(21000): at android.view.View$PerformClick.run(View.java:9080)
07-17 16:28:55.789: E/AndroidRuntime(21000): at android.os.Handler.handleCallback(Handler.java:587)
07-17 16:28:55.789: E/AndroidRuntime(21000): at android.os.Handler.dispatchMessage(Handler.java:92)
07-17 16:28:55.789: E/AndroidRuntime(21000): at android.os.Looper.loop(Looper.java:130)
07-17 16:28:55.789: E/AndroidRuntime(21000): at android.app.ActivityThread.main(ActivityThread.java:3683)
07-17 16:28:55.789: E/AndroidRuntime(21000): at java.lang.reflect.Method.invokeNative(Native Method)
07-17 16:28:55.789: E/AndroidRuntime(21000): at java.lang.reflect.Method.invoke(Method.java:507)
07-17 16:28:55.789: E/AndroidRuntime(21000): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839)
07-17 16:28:55.789: E/AndroidRuntime(21000): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597)
07-17 16:28:55.789: E/AndroidRuntime(21000): at dalvik.system.NativeStart.main(Native Method)
07-17 16:29:10.069: D/dalvikvm(21009): GC_EXPLICIT freed 688K, 52% free 3013K/6151K, external 1625K/2137K, paused 52ms

通過檢視android.os.Parcel.readException原始碼實現,被呼叫側(Server側)的這些異常的編碼號code和異常描述資訊,在被Parcel讀取後,將在呼叫側丟擲對應型別的異常。

因此,這類因跨程序產生的異常,將被跨程序送到呼叫側(Client側)。也就是說,問題的根源來自Server側的程式碼,若被呼叫側遇到程式崩潰的異常,如NullointerExeption或SecurityException。
將在呼叫側產生一個異常,這個異常由Parcel讀取,在Client側被丟擲。

這種只輸出調用側的呼叫堆疊,如何去分析並解決它呢?由於沒有輸出被呼叫側的堆疊,所以問題根源不那麼明顯。

根據筆者經驗,若是自己直接編寫的Binder IPC子類(沒有使用AIDL的形式),則首先檢查呼叫側的IXXX.Stub.Proxy中的通過Parcel引數寫入是否正確,然後再檢查IXXX.Stub中的switch-case分支中Parcel讀取時,讀取的順序以及引數型別是否正確。

在確認無誤後,再仔細檢查被呼叫側IXXX.Stub的子類實現的各函式的程式碼,如空指標(值為null並在未賦值時使用其成員);若是上述示例中的安全異常SecurityException,則需檢查未使用new分配記憶體即直接使用,或釋放後仍在使用,類似於C++中對無效記憶體的訪問。尤其是被呼叫的Server側有類的例項物件的變數,它們將是被重點懷疑的物件,通過這些例項物件變數使用成員變數值或成員函式的程式碼,最有可能是問題的根源,這時就要檢查類的例項是否初始化,是否分配了記憶體,其生命週期如何(何時被建立,何時被銷燬)。通過分析檢查程式碼,應該就可以很快找到問題的根源。

另外一種不是輕快好省的方式是,可以將這種跨程序程式碼移植到一個程序中,保證模擬出出問題時的場景,讓程式輸出崩潰時的呼叫堆疊。

相關推薦

Android程序異常分析小結

通常,我們編寫執行Android時,該程式若在一個程序中。若程式有缺陷,如空指標,將會產生空指標異常。 當異常發生時,其呼叫堆疊將會輸出到log中,通過檢視呼叫堆疊,很快可以找到問題的根源,從而解決問題。 但當我們使用Service,通過AIDL跨程序呼叫(或直接編寫B

Android程序通訊Binder原理分析(二)

文章目錄 1 Binder原始碼分析 1.1 Service的註冊流程 1.2 Service的獲取流程 1.3 Service的使用流程 1 Binder原始碼分析 1.1 Service的註冊流程  

Android程序通訊Binder原理分析(一)

文章目錄 1. Linux程序基礎 1.1 程序隔離 1.2 使用者空間/核心空間 1.3 核心模組/驅動 1.4 圖解 2. 為什麼要使用Binder 2.1 安全方面 2.2 效能方面(一

Android程序通訊:binder機制原理

個人閱讀收穫 通過binder驅動我們可以減少一次io操作,從而減少了我們程序通訊的花費的資源,加快了程序間通訊的速度。我們使用到了Linux的mmap()操作,從而實現了程序間的接收快取區與程序的空間區的對映,從而少了一次io操作。我們的客戶端會發送資訊通過我們io操作講

Android程序喚醒APP,啟動指定頁面

1 自定義啟動協議。 AndroidManifest.xml中配置通過喚起啟動的頁面。 <!--喚醒app--> <activity android:name=".SecondActivity" andro

Android 程序通訊(一)

Android 跨程序通訊 Android 本身提供一四種方式進行實現跨程序通訊,他們也分別是Android的四大元件.分別是:Activity,Content Provider,Broadcast和Service. Activity實現跨程序通訊 以Activity方式實現

【朝花夕拾】效能優化篇之(八)AIDL與Android程序通訊

        一、Linux程序間通訊   1、程序隔離         在作業系統中,程序與程序間的記憶體和資料都是不共享的。兩個程序就好像大海中相互獨立的兩個島嶼,各自生活在互相平行的兩個世界中,互不干擾,各

Android 程序雙向通訊(Messenger與AIDL)詳解

今天這篇文章主要講一下Messenger與AIDL的區別、優缺點以及各自的使用方法。 Messenger與AIDL的異同 一、Messenger與AIDL相同點 1.都與IPC的呼叫有關; 2.Messenger 是一種輕量級的

Android程序通訊AIDL詳解(附原始碼)

概述 AIDL:Android Interface Definition Language,即Android介面定義語言,記住,它是一門語言,設計它的目的就是為了實現跨程序通訊,我們知道Android的每一個程序都執行在獨立的記憶體中,程序之間程式碼是不能愉快

Android程序通訊的四種方式

 由於android系統中應用程式之間不能共享記憶體。因此,在不同應用程式之間互動資料(跨程序通訊)就稍微麻煩一些。在android SDK中提供了4種用於跨程序通訊的方式。這4種方式正好對應於android系統中4種應用程式元件:Activity、Content

Android進階——Android程序通訊機制之Binder、IBinder、Parcel、AIDL

前言 Binder機制是Android系統提供的跨程序通訊機制,這篇文章開始會從Linux相關的基礎概念知識開始介紹,從基礎概念知識中引出Binder機制,歸納Binder機制與Linux系統的跨程序機制的優缺點,接著分析Binder的通訊模型和原理,而Bin

HermesEventBus-餓了麼開源的Android程序事件分發框架

由於Android不同程序之前不能相互通訊,所以當開發過程中遇到跨程序通訊的時候,常用的方案就是AIDL(Android Interface Definition Language)通過它我們可以定義程序間的通訊介面,但是當應用中出現大量跨程序通訊的時候,比如你

【朝花夕拾】Android效能篇之(七)Android程序通訊

前言        Android系統的執行由大量相互獨立的程序相互協助來完成的,所以Android程序間通訊問題,是做好Android開發高階工程師必須要跨過的一道坎,也是面試時經常被問及到的知識點。但是,我們是否真的清楚,Android中都有哪些方式實現跨程序通訊

Android程序通訊,深入淺出AIDL

今日科技快訊 昨日,美團點評宣佈完成新一輪40億美元融資,投後估值300億美元。此次融資由騰訊領投,引入了新的戰略投資方The Priceline Group以及其他國內外知名機構。此輪融資後,美團點評將在人工智慧、無人配送等前沿技術研發上加大投入,進一步推動現代服務業升級。 作者簡介 明天就

【朝花夕拾】一篇文章搞懂Android程序通訊

前言        只要是面試中高階工程師崗位,Android跨程序通訊就是最受面試官青睞的知識點。Android系統的執行由大量相互獨立的程序相互協助來完成的,所以Android程序間通訊問題,是做好Android開發高階工程師必須要跨過的一道坎。如果您還對這方面的

Android 程序啟動Activity黑屏(白屏)的三種解決方案

當Android跨程序啟動Activity時,過程介面很黑屏(白屏)短暫時間(幾百毫秒?)。當然從桌面Lunacher啟動一個App時也會出現相同情況,那是因為App冷啟動也屬於跨程序啟動Activity。為什麼沒會出現這種情況呢?真正元凶就是Android建立

Android Init程序原始碼分析

Init 程序原始碼分析 基於Linux核心的android系統,在核心啟動完成後將建立一個Init使用者程序,實現了核心空間到使用者空間的轉變。在Android 啟動過程介紹一文中介紹了Android系統的各個啟動階段,init程序啟動後會讀取init.rc配置檔案,通

Android開發】Android程序通訊(AIDL)官方文件及官方Demo講解

第一章、 關於Android跨程序的思考 先來回顧一下作業系統中的一些概念。  同一個程序中可以有多個執行緒,執行緒間通訊可以直接取得地址。因為Java程式的記憶體分配在連續的地址空間。  預設一個Java程式會開啟一個程序,執行在JVM中。但

Android程序資料共享——ContentProvider詳解

一、ContentProvider介紹 作為android四大元件之一,ContentProvider可能是四大元件中我們用到最少的。 它作為跨程序資料共享來使用,而我們開發app的時候,基本上是獨立的,不會與其他的app發生資料間的通訊。 但如果兩個或者多個app需要共享

Android uevent程序原始碼分析

在Android Init程序原始碼分析中講到init程序會依次執行被加入到待執行佇列action_queue中的Action,在init.rc中我們有這麼一段配置: [plain] view plaincopyprint? 11 on early-init  12     # Set init