本發(fā)明涉及一種基于AST的Java代碼SSA單路徑的生成方法。
背景技術(shù):
程序靜態(tài)分析(Program Static Analysis)是在不運(yùn)行程序的前提下進(jìn)行的代碼分析工作,隨著越來(lái)越多的代碼被上傳到開源代碼庫(kù)中,大多數(shù)代碼不可以直接運(yùn)行,我們要對(duì)這些開源代碼進(jìn)行分析理解,就需要借助靜態(tài)分析技術(shù)。靜態(tài)分析技術(shù)中經(jīng)常會(huì)涉及到符號(hào)執(zhí)行(Symbolic Execution),抽象語(yǔ)法樹(Abstract Syntax Tree,AST)分析,控制流分析(Control Flow Analysis)等,借鑒這些靜態(tài)分析技術(shù)的思想,我們旨在提供一種Java代碼靜態(tài)單賦值(Static Single Assignment,SSA)格式的單路徑的生成方法支持Java代碼靜態(tài)分析方面的工作,研究者可以在該工具的基礎(chǔ)上進(jìn)行Java代碼的分析,降低了直接從代碼文本進(jìn)行分析的復(fù)雜性。
JDT(Java Development Tools)是Eclipse提供的一組用于實(shí)現(xiàn)Java IDE的工具,核心是AST,利用JDT提供的AST訪問(wèn)API,我們可以將Java代碼轉(zhuǎn)化成AST,遍歷AST樹節(jié)點(diǎn),修改AST樹結(jié)構(gòu)并將修改寫回到源代碼。
技術(shù)實(shí)現(xiàn)要素:
針對(duì)現(xiàn)有技術(shù)中存在的問(wèn)題,本發(fā)明目的是,提供一種Java代碼SSA格式的單路徑的生成方法支持Java代碼靜態(tài)分析方面的工作,研究者可以在該工具的基礎(chǔ)上進(jìn)行Java代碼的分析,降低了直接從代碼文本進(jìn)行分析的復(fù)雜性。
本發(fā)明是通過(guò)以下的技術(shù)方案實(shí)現(xiàn)的:一種基于AST的Java代碼SSA單路徑的生成方法,包括步驟:
步驟10:輸入存放.java文件的src目錄的路徑;
步驟11:使用ASTParser獲得Java代碼的AST;
步驟12:使用ASTVisitor處理所有的MethodDeclaration,將每一個(gè)方法都拆分成若干條單路徑代碼;
步驟13:使用JDT AST修改單路徑代碼的AST,將單路徑轉(zhuǎn)化為SSA的格式;
步驟14:將SSA格式的單路徑封裝成符合Java語(yǔ)法規(guī)范的Java類,存放在path目錄下,作為輸出。
其中步驟10所輸入的Java工程源代碼具有如下的目錄結(jié)構(gòu):
TestCase類的包名為testcase,有test和test2兩個(gè)方法,經(jīng)過(guò)步驟14之后,最終的輸出結(jié)果如下,其中每一個(gè)類中均包含若干條path_no方法,其參數(shù)和返回值均與路徑所在方法相同,no為路徑編號(hào):
在步驟12中,使用ASTVisitor處理所有的MethodDeclaration,將每一個(gè)方法都拆分成若干條單路徑代碼的過(guò)程包括:
步驟20:獲得MethodDeclaration的Body語(yǔ)句塊Block
步驟21:依次處理Block中的每一條Statement,將條件分支語(yǔ)句如IfStatement,WhileStatement,F(xiàn)orStatement等拆分成一組平行的分支
步驟22:在不同組的平行分支各選一條分支進(jìn)行組合,得到一條單路徑
步驟23:窮舉所有的分支間的組合情況,得到所有的單路徑
步驟21涉及到對(duì)Block的遞歸處理,最終得到相應(yīng)的中間結(jié)構(gòu),中間結(jié)構(gòu)采用多叉樹表示程序的控制流,便于進(jìn)行路徑抽取。步驟22能夠?qū)χ虚g結(jié)構(gòu)的不同層級(jí)間兄弟節(jié)點(diǎn)進(jìn)行排列組合,得到其中的一條單路徑。
在步驟13中,將單路徑轉(zhuǎn)化為SSA的格式的過(guò)程包括:
步驟30:使用ASTParser獲得單路徑代碼的AST;
步驟31:使用ASTVisitor遍歷AST,收集變量的聲明、引用、賦值;
步驟32:使用ASTRewrite刪掉AST所有關(guān)于變量聲明的ASTNode;
步驟33:每當(dāng)變量被賦值,就為該變量賦予一個(gè)新的變量名(對(duì)應(yīng)AST中的SimpleName節(jié)點(diǎn)),使之成為一個(gè)新變量,該次賦值之后到下一次賦值之前對(duì)變量的引用均用新的變量名替換,在程序的開頭添加新變量的聲明;
步驟34:將上述修改操作寫回到源代碼。
本發(fā)明有益效果:這是一個(gè)源代碼層面的借助于JDT AST提取Java代碼中的單路徑然后將其轉(zhuǎn)化為SSA格式的靜態(tài)分析輔助工具,利用這種工具,Java程序被簡(jiǎn)化成了一條條SSA格式的單路徑代碼,從而降低了直接從源代碼進(jìn)行分析的復(fù)雜性。
附圖說(shuō)明
圖1本發(fā)明實(shí)施例的Java代碼轉(zhuǎn)化為SSA單路徑示意圖。
圖2本發(fā)明實(shí)施例的輸入目錄結(jié)構(gòu)示意圖。
圖3本發(fā)明實(shí)施例的輸出目錄結(jié)構(gòu)示意圖。
圖4本發(fā)明實(shí)施例的處理?xiàng)l件分支語(yǔ)句獲得單路徑示意圖。
圖5本發(fā)明實(shí)施例的單路徑代碼轉(zhuǎn)換為SSA格式示意圖。
具體實(shí)施方式
以下結(jié)合附圖和具體實(shí)施例對(duì)本發(fā)明作進(jìn)一步詳細(xì)說(shuō)明。
本發(fā)明方法工作流程如圖1-圖5所示。
圖1所示為本方法實(shí)施的整體結(jié)構(gòu)和工作原理。本方法的目的是提供一個(gè)源代碼層面的借助于JDT AST提取Java代碼中的單路徑然后將其轉(zhuǎn)化為SSA格式的靜態(tài)分析輔助工具,利用這種工具,Java程序被簡(jiǎn)化成了一條條SSA格式的單路徑代碼,從而降低了直接從源代碼進(jìn)行分析的復(fù)雜性。
本實(shí)施例的基于AST的Java代碼SSA單路徑的生成方法,包括如下步驟:
步驟10:輸入存放.java文件的src目錄的路徑;
步驟11:使用ASTParser獲得Java代碼的AST;
步驟12:使用ASTVisitor處理所有的MethodDeclaration,將每一個(gè)方法都拆分成若干條單路徑代碼;
步驟13:使用JDT AST修改單路徑代碼的AST,將單路徑轉(zhuǎn)化為SSA的格式;
步驟14:將SSA格式的單路徑封裝成符合Java語(yǔ)法規(guī)范的Java類,存放在path目錄下,作為輸出。
圖2表示的是步驟10所輸入的Java工程源代碼所在src目錄的目錄結(jié)構(gòu)。
TestCase類的包名為testcase,有test和test2兩個(gè)方法,經(jīng)過(guò)步驟14之后,最終的輸出結(jié)果如下(圖3表示的是經(jīng)過(guò)步驟14之后,存放單路徑代碼的path目錄所具有的目錄結(jié)構(gòu)),其中每一個(gè)類中均包含若干條path_no方法,其參數(shù)和返回值均與路徑所在方法相同,no為路徑編號(hào):
圖4表示的是在步驟12中將每一個(gè)方法都拆分成若干條單路徑時(shí)對(duì)條件分支語(yǔ)句的處理示意圖,使用ASTVisitor處理所有的MethodDeclaration,將每一個(gè)方法都拆分成若干條單路徑代碼的過(guò)程包括:
步驟20:獲得MethodDeclaration的Body語(yǔ)句塊Block;
步驟21:依次處理Block中的每一條Statement,將條件分支語(yǔ)句如IfStatement,WhileStatement,F(xiàn)orStatement等拆分成一組平行的分支;
步驟22:在不同組的平行分支各選一條分支進(jìn)行組合,得到一條單路徑;
步驟23:窮舉所有的分支間的組合情況,得到所有的單路徑。
以下面的代碼為例,作為步驟20要處理的函數(shù)體:
步驟21會(huì)涉及到對(duì)Block的遞歸處理,最終得到如下所示的中間結(jié)構(gòu):
步驟22可以得到其中一條單路徑,一共有六條這樣的單路徑:
int i;
System.out.println(″=======″);
i=5;
System.out.println(i);
int j=i,z=4;
j=3;
if(j==5);
j++;
if(j==3);
System.out.println(j);
z=i+j;
if(z==4);
System.out.println(z);
return;。
圖5表示的是在步驟13中,將單路徑轉(zhuǎn)化為SSA格式的處理示意圖,執(zhí)行的過(guò)程包括:
步驟30:使用ASTParser獲得單路徑代碼的AST;
步驟31:使用ASTVisitor遍歷AST,收集變量的聲明、引用、賦值;
步驟32:使用ASTRewrite刪掉AST所有關(guān)于變量聲明的ASTNode;
步驟33:每當(dāng)變量被賦值,就為該變量賦予一個(gè)新的變量名(對(duì)應(yīng)AST中的SimpleName節(jié)點(diǎn)),使之成為一個(gè)新變量,該次賦值之后到下一次賦值之前對(duì)變量的引用均用新的變量名替換,在程序的開頭添加新變量的聲明;
步驟34:將上述修改操作寫回到源代碼。
下面給出一個(gè)轉(zhuǎn)換前后對(duì)比的例子:
以上所述,僅為本發(fā)明的較佳實(shí)施例而已,并非對(duì)本發(fā)明作任何形式上的限制,雖然本發(fā)明已以較佳實(shí)施例揭露如上,然而并非用以限定本發(fā)明,任何熟悉本專業(yè)的技術(shù)人員,在不脫離本發(fā)明技術(shù)方案范圍內(nèi),當(dāng)可利用上述揭示的技術(shù)內(nèi)容作出些許更改或修飾為等同變化的等效例,則仍屬于本發(fā)明技術(shù)方案的保護(hù)范圍內(nèi)。