本發(fā)明屬于Android平臺(tái)上應(yīng)用程序的靜態(tài)分析和內(nèi)部回調(diào)建模
技術(shù)領(lǐng)域:
,具體涉及一種基于回調(diào)函數(shù)建模自動(dòng)生成Android應(yīng)用回調(diào)序列的方法。
背景技術(shù):
:當(dāng)前移動(dòng)設(shè)備已經(jīng)成為人們生活必不可少的一部分。為了滿(mǎn)足人們?nèi)找嬖鲩L(zhǎng)的應(yīng)用需求,移動(dòng)設(shè)備上的應(yīng)用層出不窮。其中基于Android平臺(tái)的應(yīng)用數(shù)量巨大并且仍在持續(xù)增長(zhǎng),大量的Android平臺(tái)上的應(yīng)用被證明具有功能或安全性方面的問(wèn)題。因此,確保移動(dòng)應(yīng)用功能的正確性和使用的安全性越來(lái)越成為人們的關(guān)鍵需求。對(duì)Android應(yīng)用進(jìn)行安全檢查,靜態(tài)分析,需要將apk文件反編譯成介于java代碼和二進(jìn)制碼之間的smali代碼,并對(duì)smali代碼進(jìn)行靜態(tài)分析。區(qū)別于傳統(tǒng)的桌面應(yīng)用程序,Andorid系統(tǒng)具有事件驅(qū)動(dòng)的特性,雖然這個(gè)特性為其帶來(lái)諸多用戶(hù)體驗(yàn)的優(yōu)勢(shì),然而高度的交互性不可避免的增加了程序分析和測(cè)試的難度。因?yàn)锳ndroid平臺(tái)的事件驅(qū)動(dòng)特性,在對(duì)Android應(yīng)用進(jìn)行靜態(tài)分析基礎(chǔ)上創(chuàng)建相應(yīng)模型的方法比直接對(duì)源碼進(jìn)行分析要更具優(yōu)勢(shì)?;谀壳肮ぷ?,能夠總結(jié)以下兩個(gè)結(jié)論:1)回調(diào)函數(shù)序列,作為Android系統(tǒng)的一項(xiàng)主要特性,在分析和測(cè)試移動(dòng)應(yīng)用的過(guò)程中占據(jù)關(guān)鍵地位。以此為基礎(chǔ)的回調(diào)函數(shù)序列提取技術(shù)彌補(bǔ)了傳統(tǒng)程序分析方法的不足。與傳統(tǒng)方法不同,回調(diào)函數(shù)序列不再考慮程序的控制流或數(shù)據(jù)流,而是關(guān)注事件序列的發(fā)生和相關(guān)特征的更新處理。因此,回調(diào)函數(shù)序列能夠解決由事件不確定性引起的邏輯問(wèn)題,如事件異常,回調(diào)函數(shù)序列違法等,而這些問(wèn)題利用傳統(tǒng)的分析技術(shù)是難以解決的。2)現(xiàn)有的回調(diào)函數(shù)序列的處理工作僅僅是目標(biāo)導(dǎo)向。即針對(duì)特殊問(wèn)題構(gòu)建特定的回調(diào)序列,所生成的序列往往是粗粒度、不可移植且不完備的。片面構(gòu)建方法的缺陷主要表現(xiàn)在兩方面:一是沒(méi)有對(duì)生命周期回調(diào),GUI(GraphicUserInterface)回調(diào),系統(tǒng)驅(qū)動(dòng)回調(diào),組件間關(guān)系進(jìn)行統(tǒng)一構(gòu)建。其原因是難以找到一個(gè)統(tǒng)一的序列模式。例如,檢測(cè)一些控件的變化狀態(tài)必須要處理其在不同組件間的傳遞關(guān)系,控件的變化與組件間的傳遞動(dòng)作二者難以統(tǒng)一,一個(gè)不完備的模型序列使得分析的結(jié)果易于出錯(cuò)。二是不同類(lèi)型的邏輯缺陷往往存在于同一程序塊中。當(dāng)前的部分構(gòu)建方法無(wú)法利用一種通用的方法加以處理,從而嚴(yán)重限制了其實(shí)用性。另外,部分構(gòu)建也使得所構(gòu)建的序列模型難以運(yùn)用到其他場(chǎng)景。技術(shù)實(shí)現(xiàn)要素:本發(fā)明旨在使用靜態(tài)分析的方法,為Android平臺(tái)上的應(yīng)用建立一種統(tǒng)一的回調(diào)序列模型,即提供一種基于回調(diào)函數(shù)建模自動(dòng)生成Android應(yīng)用回調(diào)序列的方法。該方法考慮了生命周期回調(diào)函數(shù),GUI回調(diào)函數(shù)和系統(tǒng)驅(qū)動(dòng)回調(diào)函數(shù),它不僅對(duì)生命周期回調(diào)關(guān)系、注冊(cè)關(guān)系這兩種主要的應(yīng)用組件內(nèi)部的回調(diào)關(guān)系進(jìn)行統(tǒng)一抽象生成回調(diào)序列,更重要的是關(guān)注了不同類(lèi)型組件之間的跳轉(zhuǎn)回調(diào)關(guān)系,生成組件跳轉(zhuǎn)回調(diào)序列,從而提供完備的細(xì)粒度回調(diào)信息,便于分析各類(lèi)相關(guān)的時(shí)序?qū)傩?,比如?quán)限使用屬性等。本發(fā)明提供的基于回調(diào)函數(shù)建模自動(dòng)生成Android應(yīng)用回調(diào)序列的方法包含以下步驟:步驟1、搭建Android回調(diào)信息庫(kù);步驟2、以Android應(yīng)用的smali類(lèi)型源碼為輸入,進(jìn)行函數(shù)-回調(diào)映射預(yù)處理;步驟3、根據(jù)生命周期時(shí)序關(guān)系,生成生命周期回調(diào)序列;步驟4、識(shí)別注冊(cè)或釋放注冊(cè)動(dòng)作的關(guān)鍵連接點(diǎn),生成由注冊(cè)或釋放注冊(cè)引起的非生命周期回調(diào)序列;步驟5、識(shí)別Activity跳轉(zhuǎn)及Service跳轉(zhuǎn)動(dòng)作的關(guān)鍵連接點(diǎn),生成跳轉(zhuǎn)鏈接;步驟6、生成由Activity跳轉(zhuǎn)和Service跳轉(zhuǎn)引起的非生命周期回調(diào)序列。本發(fā)明的具體設(shè)計(jì)實(shí)現(xiàn)如下:1.搭建Android回調(diào)信息庫(kù)該庫(kù)記錄了該發(fā)明中用到的Android信息集合,待分析的Android應(yīng)用中包含的相關(guān)集合均為該庫(kù)中相應(yīng)集合的子集。依據(jù)Android平臺(tái)中回調(diào)函數(shù)庫(kù)的基礎(chǔ)信息,構(gòu)建Android回調(diào)信息庫(kù)中的以下集合:(1)白名單集:每個(gè)元素包含無(wú)用代碼所在的Android本地庫(kù)及其他依賴(lài)庫(kù)文件的名稱(chēng)及其他相關(guān)屬性。(2)注冊(cè)關(guān)系集:每個(gè)元素包含注冊(cè)關(guān)系的關(guān)鍵連接點(diǎn)及其他相關(guān)屬性。(3)釋放注冊(cè)關(guān)系集:每個(gè)元素包含釋放關(guān)系的關(guān)鍵連接點(diǎn)名稱(chēng)及其他相關(guān)屬性。(4)組件間跳轉(zhuǎn)函數(shù)集:每個(gè)元素包含Activity跳轉(zhuǎn)或Service跳轉(zhuǎn)的關(guān)鍵連接點(diǎn)名稱(chēng)及其他相關(guān)屬性。(5)回調(diào)函數(shù)集:每個(gè)元素包含回調(diào)函數(shù)名,回調(diào)函數(shù)類(lèi)型,所屬類(lèi)名及其他相關(guān)屬性。該庫(kù)可以根據(jù)需要擴(kuò)充,其中每個(gè)集合可根據(jù)需要添加或刪除元素,任一元素的屬性也可以根據(jù)需要更改。2.函數(shù)-回調(diào)映射預(yù)處理在Android回調(diào)信息庫(kù)的基礎(chǔ)上,要對(duì)輸入的Android應(yīng)用的smali代碼進(jìn)行函數(shù)回調(diào)映射預(yù)處理,獲取到回調(diào)函數(shù)集合callbackSet,非回調(diào)函數(shù)集合funSignedSet和反映每一對(duì)非回調(diào)函數(shù)與其相應(yīng)的回調(diào)入口的映射關(guān)系的函數(shù)-回調(diào)映射列表。初始化回調(diào)函數(shù)集callbackSet和開(kāi)發(fā)者自定義的非回調(diào)函數(shù)集funSignedSet為空集。過(guò)濾掉白名單下的所有無(wú)用代碼,對(duì)整個(gè)應(yīng)用的有效代碼中的所有函數(shù)進(jìn)行遍歷。每遍歷到一個(gè)函數(shù)定義,就標(biāo)記這個(gè)函數(shù)的前驅(qū)函數(shù)和后繼函數(shù),并對(duì)該函數(shù)進(jìn)行分類(lèi)標(biāo)記,分類(lèi)標(biāo)記方法是:查看該函數(shù)的名稱(chēng)是否出現(xiàn)在Android回調(diào)信息庫(kù)中回調(diào)函數(shù)集中,如果出現(xiàn),則為callbackSet添加新元素,包含函數(shù)名,所屬類(lèi)名,參數(shù)描述,前驅(qū)函數(shù),后繼函數(shù),所屬組件類(lèi)型,回調(diào)函數(shù)類(lèi)型七個(gè)屬性。組件類(lèi)型集合為{activity,service,receiver,other};回調(diào)函數(shù)類(lèi)型集合為{lifecycle,GUI,System-driven}分別表示生命周期回調(diào)函數(shù),用戶(hù)界面交互回調(diào)和系統(tǒng)驅(qū)動(dòng)回調(diào)。如果該函數(shù)名稱(chēng)未出現(xiàn)在Android回調(diào)信息庫(kù)總的回調(diào)函數(shù)集中,則為funSignedSet添加新元素包含函數(shù)名,所屬類(lèi)名,參數(shù)描述,前驅(qū)函數(shù),后繼函數(shù),所屬組件類(lèi)型六個(gè)屬性。基于這兩個(gè)集合,以每一個(gè)回調(diào)函數(shù)作為調(diào)用者,即前驅(qū)函數(shù),依次搜索被調(diào)用者,即后繼非回調(diào)函數(shù),并且迭代搜索后繼,直到?jīng)]有后繼的非回調(diào)函數(shù),在遍歷過(guò)程中,記錄該初始回調(diào)函數(shù)整個(gè)搜索調(diào)用順序來(lái)生成函數(shù)-回調(diào)映射列表中的一條記錄,該列表反映每一對(duì)非回調(diào)函數(shù)與其相應(yīng)的回調(diào)入口的映射關(guān)系;若該回調(diào)函數(shù)沒(méi)有后繼的非回調(diào)函數(shù),則不生成記錄。3.生成生命周期回調(diào)序列以組件類(lèi)型及組件源碼作為輸入,生成生命周期回調(diào)序列,生成過(guò)程涉及四個(gè)步驟:(1)對(duì)一組件C,在Android回調(diào)信息庫(kù)中找出組件類(lèi)型與C的類(lèi)型一樣的全部生命周期回調(diào)函數(shù),生成C的全生命周期回調(diào)集合C.lifecycle,為C.lifecycle添加三個(gè)并不是真實(shí)存在的輔助回調(diào)函數(shù)節(jié)點(diǎn)onActiveStart,onActiveEnd以及onTerminal,用于標(biāo)識(shí)組件的如下?tīng)顟B(tài):運(yùn)行開(kāi)始,運(yùn)行結(jié)束和銷(xiāo)毀結(jié)束,以此來(lái)顯式限定組件的活動(dòng)域以及跳轉(zhuǎn)時(shí)機(jī)。(2)生成C的對(duì)應(yīng)組件類(lèi)型的完備生命周期序列圖(ELG)。若C為activity,生成串行回調(diào)序列C.init->C.onCreate、C.onCreate->C.onStart、C.onStart->C.onResume、C.onPause->C.onResume、C.onPause->C.onStop、C.onStop->C.onDestroy、C.onStop->C.onCreate、C.onStop->C.onRestart、C.onRestart->C.onStart、C.onPause->C.onCreate、C.onResume->C.onActiveStart、C.onActiveEnd->C.onPause、C.onDestroy->C.onTerminal。若C為service且以onBind開(kāi)始,那么生成串行回調(diào)序列C.init->C.onCreate、C.onCreate->C.onBind、C.onBind->C.onActiveStart、C.onActiveEnd->C.onUnbind,C.onUnbind->C.onDestroy,C.onDestroy->C.onTerminal。若C為service且不以onBind開(kāi)始,那么生成串行回調(diào)序列C.init->C.onCreate、C.onCreate->C.onStartCommand、C.onStartCommand->C.onActiveStart、C.onActiveEnd->C.onDestroy、C.onDestroy->C.onTerminal。若C為receiver,生成串行回調(diào)序列C.onReceive->C.onActiveStart、C.onActiveEnd->C.onTerminal。(3)初始化被實(shí)現(xiàn)的生命周期回調(diào)集合lifeNodes為空,在函數(shù)-回調(diào)映射預(yù)處理得到的callbackSet集合中識(shí)別回調(diào)類(lèi)型為生命周期回調(diào)函數(shù)的元素,每出現(xiàn)一個(gè)生命周期回調(diào)函數(shù),就為lifeNodes添加一個(gè)新元素,最終添加上onActiveStart,onActiveEnd和onTerminal三個(gè)輔助節(jié)點(diǎn)得到組件C被實(shí)現(xiàn)的生命周期回調(diào)lifeNodes,以ELG中所有節(jié)點(diǎn)為全集,求lifeNodes的補(bǔ)集得到未被實(shí)現(xiàn)的生命周期回調(diào)函數(shù)隱藏節(jié)點(diǎn)集合hiddenNodes。(4)對(duì)每一個(gè)hiddenNodes集合中的元素hiddenNode,找到其父親節(jié)點(diǎn)hiddenNode.f和子節(jié)點(diǎn)hiddenNode.s,并生成串行序列hiddenNode.f->hiddenNode.s,將以hiddenNode作為出發(fā)節(jié)點(diǎn)和終止節(jié)點(diǎn)的所有序列刪除。最終得到組件C的生命周期串行回調(diào)序列。在對(duì)Android應(yīng)用分析建模過(guò)程中,需要對(duì)其所有組件均做以上四步操作。4.生成由注冊(cè)或釋放注冊(cè)引起的非生命周期回調(diào)序列生成由注冊(cè)或釋放注冊(cè)引起的非生命周期回調(diào)序列的生成過(guò)程涉及以下四個(gè)步驟:(1)識(shí)別注冊(cè)或釋放注冊(cè)動(dòng)作的關(guān)鍵連接點(diǎn),關(guān)鍵連接點(diǎn)為關(guān)鍵連接函數(shù)的調(diào)用語(yǔ)句。過(guò)濾掉白名單的無(wú)用代碼后,掃描Android應(yīng)用的smali源碼,對(duì)每一行源碼匹配Android回調(diào)信息庫(kù)注冊(cè)關(guān)系集中元素的關(guān)鍵連接點(diǎn)名,若匹配成功,則找到一個(gè)注冊(cè)或釋放注冊(cè)動(dòng)作的關(guān)鍵連接點(diǎn)。關(guān)鍵連接點(diǎn)名如:setOnClickListener,unregisterListener等。(2)對(duì)每一個(gè)關(guān)鍵連接點(diǎn)R,找到它的前驅(qū)回調(diào)函數(shù)invoker,并記錄其類(lèi)型,方法為:記錄關(guān)鍵連接點(diǎn)R被調(diào)用的函數(shù)即R的前驅(qū)函數(shù)R.p,若其為一個(gè)回調(diào)函數(shù),則invoker=R.p,停止;否則,R=R.p,利用函數(shù)-回調(diào)映射表,搜索R的前驅(qū)函數(shù)。(3)對(duì)每一個(gè)關(guān)鍵連接點(diǎn)R,找到它的后繼回調(diào)函數(shù)節(jié)點(diǎn)集invokees,方法為:識(shí)別關(guān)鍵連接函數(shù)的參數(shù),搜素參數(shù)的內(nèi)部類(lèi)實(shí)現(xiàn)源碼,找到內(nèi)部類(lèi)中定義的非生命周期回調(diào)函數(shù)即為invokees。(4)對(duì)invokees中每個(gè)元素invokee,若invoker類(lèi)型為生命周期回調(diào)lifecycle,那么生成串行回調(diào)序列onActiveStart->invokee->onActiveEnd,若invoker類(lèi)型為非生命周期回調(diào),那么生成串行回調(diào)序列invoker->invokee->onActiveEnd。5.生成跳轉(zhuǎn)鏈接生成跳轉(zhuǎn)鏈接的生成過(guò)程涉及以下三個(gè)步驟:(1)識(shí)別Activity跳轉(zhuǎn)動(dòng)作和Service跳轉(zhuǎn)動(dòng)作的關(guān)鍵連接點(diǎn)。過(guò)濾掉白名單的無(wú)用代碼后,掃描Android應(yīng)用的smali源碼(本次掃描與識(shí)別注冊(cè)或釋放注冊(cè)動(dòng)作的關(guān)鍵連接點(diǎn)的掃描為同一次),對(duì)每一行源碼匹配Android回調(diào)信息庫(kù)組件間跳轉(zhuǎn)函數(shù)集中元素的關(guān)鍵連接點(diǎn)名,若匹配成功,則找到一個(gè)Activity跳轉(zhuǎn)動(dòng)作或Service跳轉(zhuǎn)動(dòng)作的關(guān)鍵連接點(diǎn)。關(guān)鍵連接點(diǎn)名如:startActivity,startService,stopService等。(2)對(duì)每一個(gè)關(guān)鍵連接點(diǎn),搜索關(guān)鍵連接點(diǎn)的前驅(qū)回調(diào)invoker,并搜索關(guān)鍵連接點(diǎn)的后繼組件。搜索后繼組件方法為:將關(guān)鍵連接點(diǎn)的前驅(qū)回調(diào)invoker的函數(shù)實(shí)現(xiàn)作為關(guān)鍵代碼段,對(duì)關(guān)鍵代碼段的每行代碼,若存在“const-class”關(guān)鍵字,則“L”字符及之后的字符串構(gòu)成后繼組件名;若存在“const-string”和“setClassName”關(guān)鍵字,則后繼組件名為“””字符之后到倒數(shù)第二個(gè)字符所構(gòu)成的字符串。以上匹配是為了識(shí)別使用intent實(shí)現(xiàn)組件跳轉(zhuǎn)的不同方式。比如下面這行源碼:Const-classv2,Lcom/example/ury/OtherActivity解析出的后繼組件名為“Lcom/example/ury/OtherActivity”。之后通過(guò)后繼組件名來(lái)獲取整個(gè)后繼組件B。(3)為“startActivity”關(guān)鍵連接點(diǎn)生成connection_activity類(lèi)型鏈接,為“startService”關(guān)鍵連接點(diǎn)生成connection_service類(lèi)型鏈接,為“stopService”關(guān)鍵連接點(diǎn)生成connection_stop_service類(lèi)型鏈接。每個(gè)鏈接包含關(guān)鍵連接點(diǎn)名、鏈接類(lèi)型、關(guān)鍵連接點(diǎn)前驅(qū)回調(diào)invoker、連接點(diǎn)所在組件(前驅(qū)組件A)及類(lèi)型、轉(zhuǎn)到的目的組件(后繼組件B)及類(lèi)型七個(gè)屬性,其中鏈接類(lèi)型集合為{connection_activity,connection_service,connection_stop_service}。6.生成由Activity跳轉(zhuǎn)和Service跳轉(zhuǎn)引起的非生命周期回調(diào)序列以跳轉(zhuǎn)鏈接為基礎(chǔ),為connection_activity類(lèi)型的跳轉(zhuǎn)鏈接生成A.onActiveEnd->B.init和B.onTerminal->A.onActiveStart的串行回調(diào)序列。因?yàn)樵贏ndroid平臺(tái)上,組件activicy跳轉(zhuǎn)到另一個(gè)activity,那么后面的Activity會(huì)完全覆蓋前一個(gè),所以Activity間的跳轉(zhuǎn)只能生成串行回調(diào)序列,而組件activicy跳轉(zhuǎn)到另一個(gè)service,兩個(gè)組件是同時(shí)運(yùn)行的,service運(yùn)行在后臺(tái),因而為connection_service類(lèi)型鏈接生成A.invoker->B.init的并行回調(diào)序列;為connection_stop_service類(lèi)型鏈接生成B.onTerminal->A.的并行回調(diào)序列。本發(fā)明的優(yōu)點(diǎn)和積極效果:本發(fā)明方法考慮了生命周期回調(diào)函數(shù),GUI回調(diào)函數(shù)和系統(tǒng)驅(qū)動(dòng)回調(diào)函數(shù),它不僅對(duì)生命周期回調(diào)關(guān)系、注冊(cè)關(guān)系這兩種主要的應(yīng)用組件內(nèi)部的回調(diào)關(guān)系進(jìn)行統(tǒng)一抽象生成回調(diào)序列,還關(guān)注了不同類(lèi)型組件之間的跳轉(zhuǎn)回調(diào)關(guān)系,生成組件跳轉(zhuǎn)回調(diào)序列,從而為Android平臺(tái)上的應(yīng)用建立了一種統(tǒng)一的回調(diào)序列模型,提供完備的細(xì)粒度回調(diào)信息。在該統(tǒng)一的回調(diào)序列模型的基礎(chǔ)上,能夠發(fā)展出很多應(yīng)用,比如進(jìn)行漏洞檢測(cè),發(fā)現(xiàn)回調(diào)陷阱,use-after-free邏輯缺陷等?!靖綀D說(shuō)明】圖1為一個(gè)activity組件的java事例源碼。圖2為生成的activity組件的完備生命周期回調(diào)序列圖。圖3為生成的減去未實(shí)現(xiàn)生命周期回調(diào)函數(shù)的生命周期回調(diào)序列圖。圖4為生成注冊(cè)關(guān)系引起的非生命周期回調(diào)序列后的模型圖。圖5為生成activity跳轉(zhuǎn)關(guān)系引起的非生命周期回調(diào)序列后的模型圖。圖6為基于回調(diào)函數(shù)建模自動(dòng)生成Android應(yīng)用回調(diào)序列方法的總體流程圖?!揪唧w實(shí)施方式】根據(jù)本發(fā)明方法,實(shí)現(xiàn)對(duì)圖1的java源碼自動(dòng)生成統(tǒng)一回調(diào)序列。本發(fā)明首先搭建出Android回調(diào)信息庫(kù),構(gòu)建白名單集,注冊(cè)關(guān)系集,釋放注冊(cè)關(guān)系集,組件間跳轉(zhuǎn)函數(shù)集,回調(diào)函數(shù)集。對(duì)圖1所示源碼進(jìn)行函數(shù)-回調(diào)映射預(yù)處理。初始化回調(diào)函數(shù)集callbackSet和開(kāi)發(fā)者自定義的非回調(diào)函數(shù)集funSignedSet為空集。對(duì)圖1的源碼進(jìn)行掃描,每掃描到一個(gè)函數(shù)定義,就標(biāo)記這個(gè)函數(shù)的前驅(qū)函數(shù)和后繼函數(shù),并對(duì)該函數(shù)進(jìn)行分類(lèi)標(biāo)記,分類(lèi)標(biāo)記方法是:查看該函數(shù)的名稱(chēng)是否出現(xiàn)在Android回調(diào)信息庫(kù)中回調(diào)函數(shù)集中,如果出現(xiàn),則為callbackSet添加新元素,包含函數(shù)名,所屬類(lèi)名,參數(shù)描述,前驅(qū)函數(shù),后繼函數(shù),所屬組件類(lèi)型,回調(diào)函數(shù)類(lèi)型七個(gè)屬性。如果該函數(shù)名稱(chēng)未出現(xiàn)在Android回調(diào)信息庫(kù)中的回調(diào)函數(shù)集中,則為funSignedSet添加新元素包含函數(shù)名,所屬類(lèi)名,參數(shù)描述,前驅(qū)函數(shù),后繼函數(shù),所屬組件類(lèi)型六個(gè)屬性?;谶@兩個(gè)集合,以每一個(gè)回調(diào)函數(shù)作為調(diào)用者,依次搜索被調(diào)用后繼非回調(diào)函數(shù),并且迭代搜索后繼,直到?jīng)]有后繼的非回調(diào)函數(shù),在遍歷過(guò)程中,記錄該初始回調(diào)函數(shù)整個(gè)搜索調(diào)用順序來(lái)生成函數(shù)-回調(diào)映射列表中的一條記錄;若該回調(diào)函數(shù)沒(méi)有后繼的非回調(diào)函數(shù),則不生成記錄。由于僅有回調(diào)函數(shù)ShareMyPosition.onResume存在非回調(diào)后繼ShareMyPosition.performLocation并且ShareMyPosition.performLocation沒(méi)有非回調(diào)后繼函數(shù),因而函數(shù)-回調(diào)映射列表僅存在一條記錄。最終獲取到的回調(diào)函數(shù)集callbackSet、非回調(diào)函數(shù)集funSignedSet及函數(shù)-回調(diào)映射列表分別如表1、表2、表3所示。表1回調(diào)函數(shù)集callbackSet表2非回調(diào)函數(shù)集funSignedSet表3函數(shù)-回調(diào)映射表回調(diào)函數(shù)入口后繼非回調(diào)序列ShareMyPosition.onResumeShareMyPosition.performLocation->null之后生成完備的生命周期序列圖,如圖2。初始化被實(shí)現(xiàn)的生命周期回調(diào)集合lifeNodes為空,在函數(shù)-回調(diào)映射預(yù)處理得到的callbackSet集合中識(shí)別回調(diào)類(lèi)型為“l(fā)ifecycle”的元素,每出現(xiàn)一個(gè)生命周期回調(diào)函數(shù),就為lifeNodes添加一個(gè)新元素,最終添加上onActiveStart,onActiveEnd和onTerminal三個(gè)輔助節(jié)點(diǎn)得到組件C被實(shí)現(xiàn)的生命周期回調(diào)lifeNodes,在callbackSet中匹配回調(diào)函數(shù)類(lèi)型為“l(fā)ifecycle”的元素,得到實(shí)現(xiàn)的生命周期回調(diào)集合lifeNodes為{ShareMyPosition.init,ShareMyPosition.onCreate,ShareMyPosition.onResume,ShareMyPosition.onPause,ShareMyPosition.onActiveStart,ShareMyPosition.onActiveEnd,ShareMyPosition.onTerminal}。初始化hiddenNodes集合為ELG中全部節(jié)點(diǎn)集合,對(duì)hiddenNodes的每個(gè)元素hiddenNode,若該元素在lifeNodes集合中,則在hiddenNodes集合中刪除該元素,最終得到未被實(shí)現(xiàn)的生命周期回調(diào)函數(shù)隱藏節(jié)點(diǎn)集合hiddenNodes為{ShareMyPosition.onStart,ShareMyPosition.onRestart,ShareMyPosition.onStop,ShareMyPosition.onDestory}。對(duì)一個(gè)hiddenNode節(jié)點(diǎn)ShareMyPosition.onStart,找到其父親節(jié)點(diǎn)為ShareMyPosition.onCreate和子節(jié)點(diǎn)ShareMyPosition.onResume,并生成串行序列ShareMyPosition.onCreate->ShareMyPosition.onResume,并將序列ShareMyPosition.onCreate->ShareMyPosition.onStart和ShareMyPosition.onStart->ShareMyPosition.onResume刪除。同樣對(duì)hiddenNodes中的其他元素做類(lèi)似操作,得到如圖3的序列圖。然后識(shí)別注冊(cè)或釋放注冊(cè)動(dòng)作的關(guān)鍵連接點(diǎn),生成由注冊(cè)或釋放注冊(cè)引起的非生命周期回調(diào)序列。掃描源碼尋找與Android回調(diào)信息庫(kù)中注冊(cè)關(guān)系集和釋放注冊(cè)關(guān)系集的元素相匹配的語(yǔ)句,若匹配,則為一個(gè)注冊(cè)或釋放注冊(cè)動(dòng)作的關(guān)鍵連接點(diǎn)。找到的四個(gè)注冊(cè)動(dòng)作的關(guān)鍵連接點(diǎn)為{locationManager.requestLocationUpdates,AlertDialog.setNeutralButton,AlertDialog.setPositiveButton,AlertDialog.setNegativeButton},沒(méi)有找到釋放注冊(cè)動(dòng)作的關(guān)鍵連接點(diǎn)。以連接點(diǎn)locationManager.requestLocationUpdates為例,該連接點(diǎn)被函數(shù)ShareMyPosition.performLocation函數(shù)調(diào)用,即該連接點(diǎn)的前驅(qū)函數(shù)為ShareMyPosition.performLocation,由于ShareMyPosition.performLocation為非回調(diào)函數(shù),那么通過(guò)函數(shù)-回調(diào)映射列表找到它的前驅(qū)函數(shù)為ShareMyPosition.onResume,該函數(shù)為一個(gè)回調(diào)函數(shù),停止搜索。那么locationManager.requestLocationUpdates的前驅(qū)回調(diào)為ShareMyPosition.onResume。尋找其后繼回調(diào)為ShareMyPosition.onLocationChanged。因?yàn)樵撉膀?qū)回調(diào)是一個(gè)生命周期回調(diào),所以該注冊(cè)關(guān)系為lifecycle->non-lifecycle,對(duì)應(yīng)生成ShareMyPosition.onActiveStart->ShareMyPosition.onLocationChanged->ShareMyPosition.onActiveEnd串行序列。對(duì)其他三個(gè)注冊(cè)動(dòng)作關(guān)鍵連接點(diǎn)做類(lèi)似操作,得到如圖4的序列圖。識(shí)別Activity跳轉(zhuǎn)及Service跳轉(zhuǎn)動(dòng)作的關(guān)鍵連接點(diǎn),生成跳轉(zhuǎn)鏈接。掃描源碼尋找與Android回調(diào)信息庫(kù)中組件間跳轉(zhuǎn)函數(shù)集的元素相匹配的語(yǔ)句,若匹配,則為一個(gè)組件間跳轉(zhuǎn)動(dòng)作的關(guān)鍵連接點(diǎn)。找到的兩個(gè)跳轉(zhuǎn)動(dòng)作關(guān)鍵連接點(diǎn)為{startActivity(option),startActivity(share)}。對(duì)關(guān)鍵連接點(diǎn)生成跳轉(zhuǎn)鏈接如表4。表4跳轉(zhuǎn)鏈接表關(guān)鍵連接點(diǎn)名startActivity(option)startActivity(share)鏈接類(lèi)型connection_activityconnection_activityinvokeronClick(NeutralButton)onClick(PositiveButton)所在組件AShareMyPositionShareMyPositionA的類(lèi)型activityactivity目的組件BoptionshareB的類(lèi)型activityactivity最后為每個(gè)跳轉(zhuǎn)鏈接生成由Activity跳轉(zhuǎn)引起的非生命周期回調(diào)序列。對(duì)鏈接startActivity(option),由于該鏈接類(lèi)型為connection_activity,因此生成串行回調(diào)序列ShareMyPosition.onActiveEnd->option.init和option.onTerminal->ShareMyPosition.onActiveStart。同理對(duì)另一鏈接生成類(lèi)似序列,最終完整的回調(diào)序列模型圖如圖5,整個(gè)算法結(jié)束。當(dāng)前第1頁(yè)1 2 3