基于Java Reflection自動逆向生成類間 方法關系圖的解析器

      網友投稿 987 2022-05-27

      0 引言

      在一個用Java語言開發的大型軟件系統中,一旦發生軟件的錯誤,往往會導致整個系統產生故障.只有

      找到故障發生的真正原因,才能從根本上排除故障.定位大型系統中的故障來源,需要耗費較多的時間和人

      力.如果能為系統建立起一個軟件錯誤傳遞圖,輔助分析和定位故障的來源,就能幫助操作員、系統分析員快

      速定位故障的來源,找到解決故障的辦法[1-2].

      Java作為一門面向對象的語言,其程序由類、類成員、方法和方法的參數等構成.類方法之間存在互相依

      賴、互相調用的關系.建立起一個類方法關系圖,并將其擴展成為軟件的錯誤傳遞圖,如果故障發生在軟件的

      某個模塊或類方法中,在傳遞圖上就會顯示故障的位置,結合一定的算法,就能找出故障產生的來源.建立類

      方法的關系圖,還需要分析出類方法的名稱、包含的參數、返回類型及方法之間的關系.

      1 逆向分析Java文件的現狀與實踐

      在有源代碼的情況下,要分析出類方法之間的關系,前提就是去閱讀和理解源代碼.現實中往往因商業

      機密得不到源代碼,比如只有Java類文件(.class的擴展名).這類文件經編譯器編譯過,用戶看不到源代碼,

      只能看到字節碼(byte code),即二進制代碼,難以理解,無從下手,必須另尋途徑.

      有一種辦法是通過逆向分析Java文件,得到類結構和信息,人們在這方面做過不少有益的嘗試.比如說

      第36卷 第5期廣東第二師范學院學報Vol.36 No.5

      2016年10月Journal of Guangdong University of Education Oct.2016

      有一種方法是在一個類中,通過識別類方法的行號,來找出該類及其方法[3].這種方法需要逐行讀取程序.

      還有一種是利用Javassist(Java Programming Assistant)工具來打開Java類文件,得到類包含的方法、

      構造函數等.Javassist是一個Java字節代碼類庫,允許編輯Java字節代碼,使Java程序在運行時能定義一

      個新類,當JVM(Java虛擬機)載入類文件時可以修改這個類文件.它提供了兩種類型的API供調用,一種是

      源代碼API,另外一種是字節碼API.利用源代碼API,無需懂得Java字節碼,就可編輯一個類文件,且源代

      碼API也是用Java語言來設計的,支持在源代碼窗口中插入字節碼,再經Javaassit在運行時編譯.字節碼

      API則允許用戶像使用其他編輯器一樣,來編輯一個類文件[4].這種方法通過打開類文件,從字節碼得出類

      方法,還可以編輯這個文件.

      類方法的定義語句和調用語句格式不同,類方法還存在有重載現象,需要區分出名字相同,但參數不同

      的方法.Java Reflection是Java自帶的類,允許使用一個類或對象,去分析另一個Java源程序或者.class文

      件,從而得到該程序或文件所包含的類名稱、方法和方法的參數,最終可得到整個類結構.Java Reflection提

      供了許多詳細的工具集來操作Java代碼,能提供Visual Basic用戶熟悉的那些工具.新的類可以在設計和運

      行時被加入,使用快速開發工具還可以動態查詢新增加類的容量[5].Java Reflection的API(Application

      圖1 實現思路

      Program Interface)存在于Java.lang.reflect類內.譬

      如,調用java.lang.reflect.Field,java.lang.reflect.

      Method,java.lang.reflect.Constructor[6],就能得到類

      成員、方法和構造函數.本文探討了如何使用Java

      Reflection設計逆向解析Java源程序或者.class文件

      的解析器,實現思路可分為以下三方面,如圖1所示:

      1)使用Java Reflection創建一個解析器程序,

      具備識別和分析Java源程序或者類(class)文件的功

      能,能搜索到類的構造函數、類方法名稱和定義、類方法的返回類型和作用范圍.

      2)導入一個Java樣例程序文件,分析文件的類結構.

      3)對搜索到的類及類方法信息,予以整理,并以特定格式的動態數組保存,為分析類方法之間的關系和

      生成類關系圖奠定基礎.

      2 用Java Reflection逆向分析Java程序文件的具體步驟

      Java Reflection存在于Java.lang.reflect類中,導入了這個類后,才能調用其中的代碼,步驟如圖2所示:

      圖2 逆向分析Java程序文件的具體步驟

      2.1 獲取類名稱

      分析一個Java文件(以.java或者.class為擴展名),先

      要分析該文件包含了哪些類.通過調用方法“Class.

      forName”可以得到.java或者.class文件中包含的類名

      稱[7],如以下代碼所示:

      /* CVSClass.java*/

      System.out.println(" 尋找類" +className);

      this.className=className;

      2.2 獲取類方法

      當找出Java文件中的類之后,調用getMethod()可以

      2016年第5期       薛 亮,等:基于Java Reflection自動逆向生成類間方法關系圖的解析器      · 9 3 ·

      得到類中全部的公有(public)方法,以及繼承(inherited)方法.如果調用getDeclaredMethods(),可以得到類

      中已聲明的公有和非公有方法,但不能得到從superclasses繼承來的方法.代碼中methodSet使用了

      HashSet(哈希集合),methodList存儲類型使用了ArrayList(數組類型)來存儲類方法信息,目的是為了對

      比兩種不同存儲類型的存取速度,在實際應用中只要選擇一個即可.以下是如何得到類中已聲明方法的部分

      代碼:

      /* CVSClass.java*/

      Method methods=cls.getDeclaredMethods();//得到所有已聲明的方法

      cvsMethodArray=new CVSMethod[methods.length];//初始化數組

      /* 找到的類方法名存放在methodSet和methodList中*/

      if(methods!=null){for(int i=0;i< methods.length;i++){

      cvsMethodArray[i]=new CVSMethod(methods[i],className);

      methodSet.add(new CVSMethod(methods[i],className));

      methodList.add(new CVSMethod(methods[i],className));}

      2.3 獲取構造函數

      為得到類中的構造函數,調用getDeclaredConstructors()方法可以得到構造函數的名字.面向對象編程

      中,構造函數有時可以被重載(Overloading),因此一個類可以包含不止一個構造函數.如以下代碼所示:

      /* CVSClass.java*/

      //創建數組來存儲構造函數的名字

      Constructor[]constructors=cls.getDeclaredConstructors();

      cvsConstructorArray=new CVSConstructor[constructors.length];

      if(constructors!=null){for(int i=0;i<constructors.length;i++){

      /*給constructorSet和cvsConstructorArray數組添加搜尋到的構造函數名稱*/

      constructorSet.add(new CVSConstructor(constructors[i]));

      cvsConstructorArray[i]=new CVSConstructor(constructors[i]);}

      2.4 獲取類方法的返回類型

      在Java中除了構造函數之外,每個類方法均有一個返回類型.返回類型可以是空值、整數型、字符串型、

      雙精度型等.調用method.getReturnType().getName()可以得到類方法返回類型的名稱,如以下所示:

      /* CVSMethod.java*/

      this.refMethod=refMethod;

      this.cvsMethodName=refMethod.getName();//得到類名稱

      this.cvsMethodReturnType=refMethod.getReturnType().getName();//得到返回類型

      this.className=className;

      2.5 獲取類方法的參數

      一個類方法通常帶有一個或多個參數的聲明.面向對象編程中,類方法允許被重載,即多個類方法可以

      有相同名字,但返回參數可以不一樣.逆向分析時,需要知道類方法的名字、參數名稱和數量,才能區別出哪

      些是重載的方法.讀取類方法的參數部分代碼如下:

      /* CVSMethod.java*/

      public CVSMethod(Method refMethod,String className){

      /* 創建methodParameterClasses類數據來存放參數的類型*/

      · 94· 廣東第二師范學院學報第36卷

      Class[]methodParameterClasses=refMethod.getParameterTypes();

      /* 把類方法的參數存儲進數組*/

      for(int i=0;i<methodParameterClasses.length;i++){

      cvsMethodParameterSet.add (CVSUtil.toShortName(methodParameterClasses[i].getName()));

      methodParameters.append(CVSUtil.toShortName(methodParameterClasses[i].getName()));}

      /* MethInfo.java

      /* MethodInfo類用于存取類方法的名稱、類型、起止行信息*/

      this.shortMethodName=CVSUtil.getShortMethodInfoName(methodName);/* 類方法名字*/

      this.methodNameArgu=CVSUtil.getMethodNameArgu(methodName);/*類方法參數聲明*/

      2.6 在類方法內讀取括號類型、所在行號,識別方法的定義行和作用域

      Java類方法的定義語句,由一對小括號“(”和“)”表示開始和結束.用一對花括號”{”和“}”表示一個類或

      方法的作用域開始和結束.通過識別這些成對括號的開始和結束的行號,就能知道哪些語句屬于類方法的定

      義語句,哪些語句屬于作用域語句,以及哪些語句才是類方法的內容.Bracket類定義了存儲括號類型和行

      號,CVSUtil類識別類方法定義和作用域,部分代碼如下所示:

      /* Bracket.java*/

      this.bracketType=bracketType;//存放括號類型

      this.lineNumber=lineNumber;//存放行號}

      public String getBracketType(){return bracketType;}//返回括號類型

      public int getLineNumber(){return lineNumber;}//返回行號

      /*CVSUtil.java*/

      /*判斷是否含類方法定義和作用域語句*/

      {//探測讀入的語句是否存在“(”,“)”,“{”,“}”,以及表示方法語句結束的符號“;”

      if((containMethodLines.indexOf(cvsMethod.toPartString())!= -1)

      && (containMethodLines.indexOf(" (" )!= -1)&& (containMethodLines.indexOf(" )" )!= -1)

      && ((containMethodLines.indexOf(" {" )!= -1)||(containMethodLines.indexOf(" ;" )!= -1)))......}

      2.7 尋找注釋語句

      注釋語句在程序運行時不會被編譯,Java語言用兩種注釋符號,一種是以“//”開始,另一種是“/*”和

      “*/”來表示注釋的部分.在逆向分析時,必須識別出這些注釋語句,并將其忽略掉.在Bracket.java代碼中,

      isCommentBracket方法使用字符串函數IndexOf來搜索注釋符號“//”,如下:

      readLineString.indexOf("//" );//在字符串中尋找”//”符號

      2.8 搜索類方法之間的關系

      在類中的一個方法內,往往需要調用其他的方法.類方法之間存在著相互調用和依賴的關系.在搜索一

      基于Java Reflection自動逆向生成類間 方法關系圖的解析器

      個類方法內的語句時,解析器并不知道具體在哪行代碼調用其他方法,所以需要讀取類方法內的每一行代

      碼,保證調用其他方法的語句不會被遺漏.在SechDep.java中,readline方法用于讀取行并找出方法之間的

      關系.MethArr數組儲存了類中所有聲明的方法.代碼請參照SechDep.Java文件.

      2.9 保存搜索到的類方法信息到數組

      當類方法的名稱、返回類型、參數、參數的數量以及類方法之間的關系被識別出來后,這些信息就可以儲

      2016年第5期       薛 亮,等:基于Java Reflection自動逆向生成類間方法關系圖的解析器      · 9 5 ·

      存在一定格式的數組中.在SechDep.java的readline方法中,定義了一個名為finalResult的數組存放這些信

      息.代碼請參照SechDep.Java文件.

      3 導入樣例文件進行測試

      導入一個樣例文件SafeExp.java,然后運行逆向分析解析器程序,搜索到類方法信息并存儲到數組中.

      類方法數組存儲的信息如表1所示.

      表1 搜索到SafeExp.java中所包含類方法的信息的存儲數組

      類名方法名方法返回類型類成員類型是否構造函數參數數量

      SafeExp SafeExp void public 是0

      SafeExp fun_A void private 否0

      SafeExp fun_B void public 否0

      SafeExp fun_C void public 否0

      SafeExp fun_D void public 否0

      SafeExp fun_E void public 否0

      SafeExp Main void public static 否1

      在存儲完類方法數組后,將存儲類方法之間相互調用的關系,用另一個名為“finalResult”的數組來存

      放,存儲信息如表2所示.

      表2 SafeExp.java中類方法之間的關系存儲在finalResult數組

      方法名稱調用的方法方法之間的關系

      main SafeExp main→SafeExp

      SafeExp fun_A,fun_E SafeExp→fun_A,SafeExp→fun_E

      Fun_A fun_B,fun_C,fun_D fun_A→fun_B,fun_A→fun_B,fun_A→fun_C

      Fun_B 無無

      Fun_C fun_D fun_C→fun_D

      Fun_D 無無

      Fun_E fun_B,fun_D fun_E→fun_B,fun_E→fun_D

      利用類方法和方法之間關系的數組,使用Java圖形編程,可生成類方法關系圖,如圖3中由節點和有向

      邊構成的圖形.

      4 結語

      對于Java源程序或者.class文件,使用Java Reflection設計逆向分析解析器程序,獲得類的名稱、方法

      名、方法參數、構造函數等信息,并搜索出每個類方法與其他方法之間的關系.然后,將這些信息用特定格式

      的數組存儲起來.該數組存儲的信息就可作為生成類方法關系圖所用.

      類方法關系圖可進一步擴展成為軟件錯誤傳遞圖,供操作員或系統分析員監測軟件運行的狀況,幫助

      · 96· 廣東第二師范學院學報第36卷

      圖3 分析SafeExp.java后生成的類

      方法關系圖

      他們在故障發生時,分析和確定故障產生的來源,及時

      采取相應措施.目前,對于大型的軟件系統,逆向分析類

      方法之間的關系還存在一定的困難,需要更多地研究、

      實踐和改進解析器程序.比如,當系統的文件內部結構

      (邏輯結構)非常復雜,存在各種不同類型的類(子類、抽

      象類、內部類等等)時,類方法之間互相調用的關系更加

      錯綜復雜,分析工作更為艱巨.

      文中使用Java Reflection進行逆向分析的解析器

      源代碼,限于篇幅無法詳盡列出,完整的代碼可通過訪

      問網盤鏈接“http://pan.baidu.com/s/1c1H7Ksg”下

      載.源代碼在JDK1.6和NetBeans中調試通過.

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:分布式文件系統FastDFS詳解
      下一篇:TOP級CG行業云渲染服務的演進之路
      相關文章
      亚洲一区影音先锋色资源| 亚洲а∨天堂久久精品| 亚洲av无码不卡私人影院| 亚洲综合精品伊人久久| 久久精品国产亚洲av麻豆图片| 亚洲精品不卡视频| 久久亚洲精品无码VA大香大香| 久久久久亚洲精品影视| 亚洲乱码中文字幕综合| 亚洲欧洲精品无码AV| 国产亚洲成av片在线观看 | 2022中文字字幕久亚洲| 亚洲第一永久AV网站久久精品男人的天堂AV| 亚洲最大的成人网| 亚洲久热无码av中文字幕| 亚洲日韩av无码中文| 亚洲午夜理论片在线观看| 亚洲人成网站在线播放2019 | 亚洲13又紧又嫩又水多| 亚洲天堂2017无码中文| 亚洲熟妇自偷自拍另欧美| 亚洲av无码av在线播放| 日韩在线视精品在亚洲| 亚洲国产香蕉人人爽成AV片久久 | 欧美激情综合亚洲一二区| 国产成人va亚洲电影| 亚洲国产精品无码久久九九| 亚洲情侣偷拍精品| 亚洲色爱图小说专区| 亚洲AV日韩AV高潮无码专区| 少妇中文字幕乱码亚洲影视| 亚洲国产综合在线| 在线aⅴ亚洲中文字幕| 亚洲av无码兔费综合| 亚洲乱码日产精品a级毛片久久| MM131亚洲国产美女久久 | 国产午夜亚洲精品午夜鲁丝片 | 国产精品亚洲精品| 亚洲a∨无码精品色午夜| 亚洲国产aⅴ综合网| 亚洲色婷婷综合久久|