本申請涉及移動終端技術領域,特別涉及一種提取程序無響應發生時函數棧的提取方法和裝置。
背景技術:
通常,在Android(安卓)系統中,如果應用程序有一段時間響應不靈敏,系統會向用戶顯示一個對話框,這個對話框被稱作應用程序無響應(Application Not Responding,簡稱ANR)對話框,用戶可以選擇該對話框上的“等待”按鈕而讓程序繼續運行,也可以選擇該對話框上的“強制關閉”按鈕來中斷程序的運行。因此,在每次出現ANR的情況時,用戶都要對應用程序無響應對話框進行處理,從而造成用戶的體驗感變差。
為了提升用戶體驗,設計流暢合理的應用程序成為必要。開發人員在開發應用程序時,需要通過抓取應用程序無響應來完善該應用程序。相關技術中,抓取應用程序無響應(即ANR)的方法主要是:可先抓取出移動終端(如手機等)上/data/anr目錄下的traces.txt文件(即應用程序錯誤信息反饋文件),之后,通過人工分析該文件里面的函數棧信息,找出屬于某個應用程序的ANR。
但是存在的問題是,上述抓取ANR的方法,流程比較復雜,并且整個抓取過程主要都是通過人工來操作,增加了開發人員的工作量,增加了人工成本,且效率低。
技術實現要素:
本申請的目的旨在至少在一定程度上解決上述的技術問題之一。
為此,本申請的第一個目的在于提出了一種提取程序無響應發生時函數棧的提取方法。該方法通過跨線程之間的交互來實現程序無響應發生時主線程中函數棧的提取,整個提取過程完全自動化,無需人工參與,降低了開發人員的工作量,降低了人工成本,提高了效率。
本申請的第二個目的在于提出了一種提取程序無響應發生時函數棧的提取裝置。
為達上述目的,根據本申請第一方面的實施例提出了一種提取程序無響應發生時函數棧的提取方法,包括以下步驟:建立子線程,并通過所述子線程建立第一變量和第二變量,其中,所述第二變量等于所述第一變量;所述子線程發送任務至主線程,其中,所述任務 用于在被所述主線程執行時修改所述第一變量;所述子線程在預設時間之后判斷所述第一變量和第二變量是否相等;以及如果所述第一變量和第二變量相等,則所述子線程判斷所述任務未被所述主線程執行而導致程序無響應,并提取所述主線程當前的函數棧。
本申請實施例的提取程序無響應發生時函數棧的提取方法,可建立子線程,并通過子線程發送任務至主線程,并在預設時間后子線程判斷任務有無被主線程執行,如果判斷出上述任務沒有被主線程執行則提取上述主線程當前的函數棧,即通過跨線程之間的交互來實現程序無響應發生時主線程中函數棧的提取,整個提取過程完全自動化,無需人工參與,降低了開發人員的工作量,降低了人工成本,提高了效率,并且通過將提取到的函數棧提交到移動后臺,方便了開發人員發現并解決問題。
為達上述目的,根據本申請的第二方面的實施例提出了一種提取程序無響應發生時函數棧的提取裝置,包括:建立模塊,用于建立子線程,并通過所述子線程建立第一變量和第二變量,其中,所述第二變量等于所述第一變量;子線程控制模塊,其中,所述子線程控制模塊包括:任務發送子模塊,用于發送任務至主線程,其中,所述任務用于在被所述主線程執行時修改所述第一變量;判斷子模塊,用于在預設時間之后判斷所述第一變量和第二變量是否相等;以及提取子模塊,用于在所述第一變量和第二變量相等時,判斷所述任務未被所述主線程執行而導致程序無響應,并提取所述主線程當前的函數棧。
本申請實施例的提取程序無響應發生時函數棧的提取裝置,可通過建立模塊建立子線程,并通過子線程控制模塊中的任務發送子模塊發送任務至主線程,并在預設時間后判斷子模塊判斷任務有無被主線程執行,如果判斷出上述任務沒有被主線程執行則通過提取子模塊提取上述主線程當前的函數棧,即通過跨線程之間的交互來實現程序無響應發生時主線程中函數棧的提取,整個提取過程完全自動化,無需人工參與,降低了開發人員的工作量,降低了人工成本,提高了效率,并且通過將提取到的函數棧提交到移動后臺,方便了開發人員發現并解決問題。
本申請附加的方面和優點將在下面的描述中部分給出,部分將從下面的描述中變得明顯,或通過本申請的實踐了解到。
附圖說明
本申請的上述和/或附加的方面和優點從結合下面附圖對實施例的描述中將變得明顯和容易理解,其中:
圖1是根據本申請一個實施例的提取程序無響應發生時函數棧的提取方法的流程圖;
圖2是根據本申請一個具體實施例的提取程序無響應發生時函數棧的提取方法的示例圖;
圖3是根據本申請另一個具體實施例的提取程序無響應發生時函數棧的提取方法的流程圖;
圖4是根據本申請一個實施例的提取程序無響應發生時函數棧的提取裝置的結構框圖;以及
圖5是根據本申請另一個實施例的提取程序無響應發生時函數棧的提取裝置的結構框圖。
具體實施方式
下面詳細描述本申請的實施例,所述實施例的示例在附圖中示出,其中自始至終相同或類似的標號表示相同或類似的元件或具有相同或類似功能的元件。下面通過參考附圖描述的實施例是示例性的,旨在用于解釋本申請,而不能理解為對本申請的限制。
下面參考附圖描述本申請實施例的提取程序無響應發生時函數棧的提取方法和裝置。
圖1是根據本申請一個實施例的提取程序無響應發生時函數棧的提取方法的流程圖。需要說明的是,本申請實施例的提取程序無響應發生時函數棧的提取方法適用于具有Android操作系統的移動終端,該移動終端可以是手機、平板電腦、個人數字助理等硬件設備。此外,上述程序可以是安裝在移動終端上的應用程序,為了方便描述,后續實施例中將以測試應用程序進行描述。
如圖1所示,該提取程序無響應發生時函數棧的提取方法,包括以下步驟:
S110,建立子線程,并通過子線程建立第一變量和第二變量,其中,第二變量等于第一變量。
具體地,在本申請的一個實施例中,假設本申請實施例的提取方法應用于具有Android操作系統的移動終端上,當測試應用程序第一次啟動時,移動終端可針對該測試應用程序建立一個對應的子線程,并且通過該子線程建立第一變量index和第二變量lastIndex,并將第二變量lastIndex等于第一變量index。例如,可將第一變量index賦初始值,然后將第二變量lastIndex的值等于第一變量index的初始值。
優選地,為了保證第一變量index在多線程訪問時不被其他線程影響,在本申請的一個實施例中,在通過子線程建立第一變量之后,還可將該第一變量的屬性設置為不穩定變量屬性值Volatile,以便于接下來對第一變量的修改。需要說明的是,通過將第一變量屬性值設置為Volatile,可以保證第一變量在多線程訪問時不被其他線程所影響,Volatile是一個類型修飾符,它用來修飾被不同線程訪問和修改的變量,在本申請的實施例中,將第一變量的屬性值設置為Volatile相當于告訴系統這個變量可能會被意想不到的改變,這樣系統的編譯器就不會去假設這個變量的值,也就是說,系統的優化器在用到這個變量時 必須每次都小心地重新讀取這個變量的值,可以理解通過將第一變量的屬性值設置為Volatile,可以保證第一變量的值能準確反映應用程序的線程有無被主線程執行,也就是說只要檢測到第一變量值變化,就代表對應的子線程被主線程執行,同時,只要第一變量值沒有發生變化,就代表對應的子線程沒有被主線程執行。
S120,子線程發送任務至主線程,其中,上述任務用于在被主線程執行時修改第一變量。
可以理解,該主線程可以是在測試應用程序啟動時,Android操作系統會啟動一個該測試應用程序對應的線程,該主線程主要負責處理該測試應用程序中與UI(User Interface,用戶界面)相關的事件,例如,用戶的按鍵事件、用戶接觸屏幕的事件以及屏幕繪圖事件等,并將相關的事件分發到對應的組件進行處理。
具體地,在建立測試應用程序對應的子線程之后,該子線程可通過post方法發送任務至該測試應用程序對應的主線程,該任務可用于在被主線程執行時修改第一變量,該任務可理解為一串代碼的集合。
其中,在本申請的實施例中,任務在被主線程執行時使得第一變量加1之后取余。具體地,主線程在執行該任務時,該任務可根據自身代碼集合對第一變量的值進行修改,即每當被主線程執行時會將第一變量的值加1之后取余,例如,可將第一變量的值加1之后與常量10進行取余,并將該取余得到的余數賦給第一變量。可以理解,這里取余是為了保持第一變量的值始終處于一定范圍內(即處于比較小的數),如0-9的范圍內,這樣使得任務在執行時不會發生溢出,避免了因溢出導致第一變量被重置從而導致接下來判斷不準確的情況發生。
例如,子線程可通過post方法發送一個任務Runnable,在該任務Runnable中定義了一些代碼集合,可用于在被主線程執行時對第一變量index加1之后與常量10進行取余,并將余數賦給第一變量index,即index=(index+1)%10。其中,上述的post方法指的是一種向目的服務器發送更新請求,并附有請求實體的一種方法,比如用來上傳文件、將表格的結果提交給數據處理過程等,在本申請的實施例中,post方法可用來將子線程發送的任務發送到主線程。
需要說明的是,如果主線程執行子線程發送的任務,那么上述任務就會對第一變量進行修改,可以理解第一變量如果被修改那么就代表主線程執行了子線程發送的任務。
還需要說明的是,在本申請的一個實施例中,上述任務在被主線程執行時,還可用于控制子線程休眠預設時間。其中,在本申請的實施例中,由于在默認情況下,Android操作系統中Activity的最長執行時間一般為5s,所以可將預設時間設定為5s。可以理解,還可根據實際測試應用程序的情況而設定該預設時間的值。也就是說,任務在被主線程執行 時,在修改第一變量的同時,還可控制子線程sleep5秒,以為該任務能夠被主線程執行提供一定的時間。
S130,子線程在預設時間之后判斷第一變量和第二變量是否相等。
具體地,在控制子線程休眠預設時間之后,子線程可判斷此時的第一變量的值和第二變量的值是否相等。
S140,如果第一變量和第二變量相等,則子線程判斷任務未被主線程執行而導致程序無響應,并提取主線程當前的函數棧。
具體地,如果在子線程休眠預設時間后,子線程判斷此時的第一變量和第二變量相等,則可判斷子線程發送給主線程的任務未被主線程執行而導致程序無響應,這樣可以判定主線程肯定是被某個函數阻塞住而沒有執行上述任務,這時可提取主線程當前的函數棧。
優選地,在提取主線程當前的函數棧之后,可將該函數棧上傳至服務器端并記錄下來,以供開發人員發現并解決問題。
舉例而言,如圖2所示,當測試應用程序啟動時,移動終端可建立一個該測試應用程序對應的子線程,并通過子線程建立第一變量index,其中將第一變量index設置為volatile屬性,并建立第二變量lastIndex,使得第二變量lastIndex等于第一變量index。之后,子線程可通過post方法發送一個任務Runnable到該測試應用程序的主線程中,其中,在Runnable中,可以讓index+1取余,即index=(index+1)%10,同時控制子線程sleep5秒。在子線程sleep5秒之后,子線程可判斷第二變量lastIndex和第一變量index是否相等,如果相等,則說明post到主線程的Runnable并沒有被主線程執行,這樣可以判斷主線程可能是被某個函數阻塞住了而沒有被執行,這時候可以捕獲出主線程當前的函數棧并將其上傳到服務端后臺記錄下來。
本申請實施例的提取程序無響應發生時函數棧的提取方法,可建立子線程,并通過子線程發送任務至主線程,并在預設時間后子線程判斷任務有無被主線程執行,如果判斷出上述任務沒有被主線程執行則提取上述主線程當前的函數棧,即通過跨線程之間的交互來實現程序無響應發生時主線程中函數棧的提取,整個提取過程完全自動化,無需人工參與,降低了開發人員的工作量,降低了人工成本,提高了效率,并且通過將提取到的函數棧提交到移動后臺,方便了開發人員發現并解決問題。
圖3是根據本申請一個具體實施例的提取程序無響應發生時函數棧的提取方法的流程圖。
如圖3所示,本申請實施例的提取程序無響應發生時函數棧的提取方法,包括:
S310,建立子線程,并通過子線程建立第一變量和第二變量,其中,第二變量等于第一變量。
S320,子線程發送任務至主線程,其中,上述任務用于在被主線程執行時修改第一變量。
S330,子線程在預設時間之后判斷第一變量和第二變量是否相等。
S340,如果第一變量和第二變量相等,則子線程判斷任務未被主線程執行而導致程序無響應,并提取主線程當前的函數棧。
S350,如果第一變量和第二變量不相等,則子線程判斷任務已被主線程執行。
具體而言,在本申請的實施例中,如果子線程判斷出第一變量和第二變量不相等,子線程判斷任務已經被主線程執行。即在子線程發送給主線程任務后,主線程在執行該任務時,可通過該任務使得第一變量加1之后與常量10取余,并將余數賦給第一變量,從而使得第一變量發生了變化,子線程在休眠預設時間之后,判斷此時的第一變量和第二變量不相等,從而判斷出任務已經被主線程執行。
本申請實施例的提取程序無響應發生時函數棧的提取方法,子線程在預設時間后判斷第一變量和第二變量不相等時,判斷任務已被主線程執行,從而實現了對程序有無響應的快速判斷,方便了開發人員對應用程序運行情況的了解。
為了實現上述實施例,本申請還提出了一種提取程序無響應發生時函數棧的提取裝置。
圖4是根據本申請一個實施例的提取程序無響應發生時函數棧的提取裝置的結構框圖。需要說明的是,本申請實施例的提取程序無響應發生時函數棧的提取裝置適用于具有Android操作系統的移動終端,該移動終端可以是手機、平板電腦、個人數字助理等硬件設備。
如圖4所示,該提取程序無響應發生時函數棧的提取裝置,包括:建立模塊410和子線程控制模塊420。
具體地,建立模塊410可用于建立子線程,并通過子線程建立第一變量和第二變量,其中,第二變量等于第一變量。
更具體地,在本申請的一個實施例中,假設本申請實施例的提取裝置應用于具有Android操作系統的移動終端上,當測試應用程序啟動時,建立模塊410可針對該測試應用程序建立一個對應的子線程,并且通過該子線程建立第一變量index和第二變量lastIndex,并將第二變量lastIndex等于第一變量index。例如,可將第一變量index賦初始值,然后將第二變量lastIndex的值等于第一變量index的初始值。
在本申請的實施例中,如圖4所示,子線程控制模塊420可包括:任務發送子模塊421、判斷子模塊422和提取子模塊423。
具體地,任務發送子模塊421可用于發送任務至主線程,其中,上述任務用于在被主線程執行時修改第一變量。
可以理解,該主線程可以是在測試應用程序啟動時,Android操作系統會啟動一個該測試應用程序對應的線程,該主線程主要負責處理該測試應用程序中與UI(User Interface,用戶界面)相關的事件,例如,用戶的按鍵事件、用戶接觸屏幕的事件以及屏幕繪圖事件等,并將相關的事件分發到對應的組件進行處理。
更具體地,在建立模塊410建立測試應用程序對應的子線程之后,任務發送子模塊421可通過post方法發送任務至該測試應用程序對應的主線程,該任務可用于在被主線程執行時修改第一變量,該任務可理解為一串代碼的集合。其中,在本申請的實施例中,任務在被主線程執行時使得第一變量加1之后取余。具體地,主線程在執行該任務時,該任務可根據自身代碼集合對第一變量的值進行修改,即每當被主線程執行時會將第一變量的值加1之后取余,例如,可將第一變量的值加1之后與常量10進行取余,并將該取余得到的余數賦給第一變量。可以理解,這里取余是為了保持第一變量的值始終處于一定范圍內(即處于比較小的數),如0-9的范圍內,這樣使得任務在執行時不會發生溢出,避免了因溢出導致第一變量被重置從而導致接下來判斷不準確的情況發生。
例如,任務發送子模塊421可通過post方法發送一個任務Runnable,在該任務Runnable中定義了一些代碼集合,可用于在被主線程執行時對第一變量index加1之后與常量10進行取余,并將余數賦給第一變量index,即index=(index+1)%10。其中,上述的post方法指的是一種向目的服務器發送更新請求,并附有請求實體的一種方法,比如用來上傳文件、將表格的結果提交給數據處理過程等,在本申請的實施例中,post方法可用來將子線程發送的任務發送到主線程。需要說明的是,如果主線程執行任務發送子模塊421發送的任務,那么上述任務就會對第一變量進行修改,可以理解第一變量如果被修改那么就代表主線程執行了任務發送子模塊421發送的任務。
還需要說明的是,在本申請的一個實施例中,上述任務在被主線程執行時,還可用于控制子線程休眠預設時間。其中,在本申請的實施例中,由于在默認情況下,Android操作系統中Activity的最長執行時間一般為5s,所以可將預設時間設定為5s。可以理解,還可根據實際測試應用程序的情況而設定該預設時間的值。也就是說,任務在被主線程執行時,在修改第一變量的同時,還可控制子線程sleep5秒,以為該任務能夠被主線程執行提供一定的時間。
判斷子模塊422可用于在預設時間之后判斷第一變量和第二變量是否相等。
更具體地,在任務控制子線程休眠預設時間之后,判斷子模塊422可判斷此時的第一變量和第二變量的值是否相等。
可以理解,在本申請的實施例中,判斷子模塊422還可用于在第一變量和第二變量不相等時,判斷任務已被主線程執行。具體而言,判斷子模塊422在判斷出第一變量和第二 變量不相等時,可判斷任務已經被主線程執行。即在任務發送子模塊421發送給主線程任務后,主線程在執行該任務時,可通過該任務使得第一變量加1之后與常量10取余,并將余數賦給第一變量,從而使得第一變量發生了變化,子線程在休眠預設時間之后,判斷子模塊422判斷此時的第一變量和第二變量不相等,從而判斷出任務已經被主線程執行。由此,實現了對程序有無響應的快速判斷,方便了開發人員對應用程序運行情況的了解。
提取子模塊423可用于在第一變量和第二變量相等時,判斷任務未被主線程執行而導致程序無響應,并提取主線程當前的函數棧。
更具體地,如果在子線程休眠預設時間后,判斷子模塊422判斷此時的第一變量和第二變量相等,則可判斷子線程發送給主線程的任務未被主線程執行而導致程序無響應,這樣可以判定主線程肯定是被某個函數阻塞住而沒有執行上述任務,這時提取子模塊423可提取主線程當前的函數棧。
優選地,提取子模塊423在提取主線程當前的函數棧之后,可將該函數棧上傳至服務器端并記錄下來,以供開發人員發現并解決問題。
為了保證第一變量index在多線程訪問時不被其他線程影響,優選地,在本申請的一個實施例中,如圖5所示,在建立模塊410通過子線程建立第一變量之后,該提取裝置還包括設置模塊430,設置模塊430可將該第一變量的屬性設置為不穩定變量屬性值Volatile,以便于上述任務發送子模塊421發送的任務被主線程執行時對第一變量的修改。需要說明的是,通過設置模塊430將第一變量屬性值設置為Volatile,可以保證第一變量在多線程訪問時不被其他線程所影響,Volatile是一個類型修飾符,它用來修飾被不同線程訪問和修改的變量,在本申請的實施例中,將第一變量的屬性值設置為Volatile相當于告訴系統這個變量可能會被意想不到的改變,這樣系統的編譯器就不會去假設這個變量的值,也就是說,系統的優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,可以理解通過將第一變量的屬性值設置為Volatile,可以保證第一變量的值能準確反映應用程序的線程有無被主線程執行,也就是說只要檢測到第一變量值變化,就代表對應的子線程被主線程執行,同時,只要第一變量值沒有發生變化,就代表對應的子線程沒有被主線程執行。本申請實施例的提取程序無響應發生時函數棧的提取裝置,可通過建立模塊建立子線程,并通過子線程控制模塊中的任務發送子模塊發送任務至主線程,并在預設時間后判斷子模塊判斷任務有無被主線程執行,如果判斷出上述任務沒有被主線程執行則通過提取子模塊提取上述主線程當前的函數棧,即通過跨線程之間的交互來實現程序無響應發生時主線程中函數棧的提取,整個提取過程完全自動化,無需人工參與,降低了開發人員的工作量,降低了人工成本,提高了效率,并且通過將提取到的函數棧提交到移動后臺,方便了開發人員發現并解決問題。
在本申請的描述中,需要理解的是,術語“第一”、“第二”僅用于描述目的,而不能理解為指示或暗示相對重要性或者隱含指明所指示的技術特征的數量。由此,限定有“第一”、“第二”的特征可以明示或者隱含地包括至少一個該特征。在本申請的描述中,“多個”的含義是至少兩個,例如兩個,三個等,除非另有明確具體的限定。
在本說明書的描述中,參考術語“一個實施例”、“一些實施例”、“示例”、“具體示例”、或“一些示例”等的描述意指結合該實施例或示例描述的具體特征、結構、材料或者特點包含于本申請的至少一個實施例或示例中。在本說明書中,對上述術語的示意性表述不必須針對的是相同的實施例或示例。而且,描述的具體特征、結構、材料或者特點可以在任一個或多個實施例或示例中以合適的方式結合。此外,在不相互矛盾的情況下,本領域的技術人員可以將本說明書中描述的不同實施例或示例以及不同實施例或示例的特征進行結合和組合。
流程圖中或在此以其他方式描述的任何過程或方法描述可以被理解為,表示包括一個或更多個用于實現特定邏輯功能或過程的步驟的可執行指令的代碼的模塊、片段或部分,并且本申請的優選實施方式的范圍包括另外的實現,其中可以不按所示出或討論的順序,包括根據所涉及的功能按基本同時的方式或按相反的順序,來執行功能,這應被本申請的實施例所屬技術領域的技術人員所理解。
應當理解,本申請的各部分可以用硬件、軟件、固件或它們的組合來實現。在上述實施方式中,多個步驟或方法可以用存儲在存儲器中且由合適的指令執行系統執行的軟件或固件來實現。例如,如果用硬件來實現,和在另一實施方式中一樣,可用本領域公知的下列技術中的任一項或他們的組合來實現:具有用于對數據信號實現邏輯功能的邏輯門電路的離散邏輯電路,具有合適的組合邏輯門電路的專用集成電路,可編程門陣列(PGA),現場可編程門陣列(FPGA)等。
本技術領域的普通技術人員可以理解實現上述實施例方法攜帶的全部或部分步驟是可以通過程序來指令相關的硬件完成,所述的程序可以存儲于一種計算機可讀存儲介質中,該程序在執行時,包括方法實施例的步驟之一或其組合。
此外,在本申請各個實施例中的各功能單元可以集成在一個處理模塊中,也可以是各個單元單獨物理存在,也可以兩個或兩個以上單元集成在一個模塊中。上述集成的模塊既可以采用硬件的形式實現,也可以采用軟件功能模塊的形式實現。所述集成的模塊如果以軟件功能模塊的形式實現并作為獨立的產品銷售或使用時,也可以存儲在一個計算機可讀取存儲介質中。
上述提到的存儲介質可以是只讀存儲器,磁盤或光盤等。盡管上面已經示出和描述了 本申請的實施例,可以理解的是,上述實施例是示例性的,不能理解為對本申請的限制,本領域的普通技術人員在本申請的范圍內可以對上述實施例進行變化、修改、替換和變型。