本申請涉及軟件工程技術(shù)領(lǐng)域,特別涉及一種Java字節(jié)碼調(diào)試器及調(diào)試方法。
背景技術(shù):
Java語言已經(jīng)應(yīng)用到各種應(yīng)用程序的編程中,卡內(nèi)芯片系統(tǒng)由Java語言來編寫的智能卡又稱為Java卡,Java卡中包括由Java源代碼編譯后的Java字節(jié)碼和由C程序編寫的虛擬機(jī),虛擬機(jī)用來對Java字節(jié)碼進(jìn)行解析并執(zhí)行。
目前Java卡內(nèi)的系統(tǒng)程序均基于Java源代碼進(jìn)行調(diào)試,一般通過在eclipse開發(fā)平臺(tái)增加調(diào)試插件,并將調(diào)試插件連接到虛擬機(jī)來實(shí)現(xiàn),具體調(diào)試過程包括將Java源代碼編譯成Java字節(jié)碼和在虛擬機(jī)上運(yùn)行編譯后的Java字節(jié)碼兩個(gè)過程。
由于在上述對Java源代碼進(jìn)行調(diào)試的過程中,被封裝到Java卡芯片并在虛擬機(jī)上運(yùn)行的實(shí)際是Java字節(jié)碼,進(jìn)而使得上述基于Java源代碼的調(diào)試方法不能直觀并準(zhǔn)確地幫助工程師去定位運(yùn)行中間出現(xiàn)的異常問題,使得Java軟件工程師的調(diào)試效率比較低。
技術(shù)實(shí)現(xiàn)要素:
本發(fā)明的目的在于提高Java軟件工程師的調(diào)試效率,提供一種Java字節(jié)碼調(diào)試器及調(diào)試方法。
為達(dá)到上述目的,本發(fā)明的技術(shù)方案是提供一種Java字節(jié)碼調(diào)試器,包括符號(hào)庫模塊、緩存模塊、調(diào)試模塊、棧解析模塊和引用解析模塊,其中:
符號(hào)庫模塊,用于從Java源代碼文件中獲取符號(hào)信息,并存放符號(hào)信息;
緩存模塊,用于從Java字節(jié)碼文件中獲取符號(hào)信息和數(shù)據(jù)信息,并緩存符號(hào)信息和數(shù)據(jù)信息;
調(diào)試模塊,用于通過Keil通道與虛擬機(jī)連接,使得Java字節(jié)碼文件可在虛擬機(jī)上運(yùn)行并調(diào)試,其中,用戶直接在Java字節(jié)碼上設(shè)置斷點(diǎn),調(diào)試模塊將該斷點(diǎn)同步到Keil通道進(jìn)行調(diào)試,調(diào)試結(jié)束后,調(diào)試模塊通過Keil通道將運(yùn)行到斷點(diǎn)位置的虛擬機(jī)的存儲(chǔ)器中的Java棧提取出來發(fā)送到棧解析模塊;
棧解析模塊,用于接收運(yùn)行到斷點(diǎn)位置的虛擬機(jī)的存儲(chǔ)器中的Java棧,并對Java棧進(jìn)行解析,其中,解析結(jié)果包括執(zhí)行到斷點(diǎn)位置時(shí)應(yīng)用程序?qū)?yīng)的Java函數(shù)的調(diào)用關(guān)系、函數(shù)參數(shù)信息、函數(shù)局部變量值和地址信息中的至少一個(gè);
引用解析模塊,用于對執(zhí)行到斷點(diǎn)位置時(shí)Java字節(jié)碼對應(yīng)的Java引用進(jìn)行解析,其中,如果Java引用指向一個(gè)Java對象,根據(jù)Java對象的存儲(chǔ)方式和規(guī)則進(jìn)行解析,解析出這個(gè)Java對象所屬的Java類別及其對應(yīng)的狀態(tài)、擁有者和域值中的至少一個(gè);如果Java引用指向一個(gè)數(shù)組,則解析出這個(gè)數(shù)組元素的類型和所有元素的值。
可選地,所述Java字節(jié)碼調(diào)試器還包括靜態(tài)變量解析模塊,用于對Java代碼中的靜態(tài)變量進(jìn)行解析,并允許開發(fā)者在任意時(shí)刻選擇任意一個(gè)靜態(tài)變量進(jìn)行解析和查看。
本發(fā)明提供的Java字節(jié)碼調(diào)試器具有如上所述的結(jié)構(gòu),從而使得一方面,本發(fā)明提出的Java字節(jié)碼調(diào)試器利用Keil通道使得Java字節(jié)碼文件可以在虛擬機(jī)上運(yùn)行,實(shí)現(xiàn)了基于Java字節(jié)碼的調(diào)試功能;另一方面,本發(fā)明提出的Java字節(jié)碼調(diào)試器中的符號(hào)庫模塊和緩存模塊預(yù)先對Java字節(jié)碼文件和Java源代碼文件中的符號(hào)信息和數(shù)據(jù)信息做了計(jì)算和緩存,使得棧解析模塊和引用解析模塊能夠快速地解析出調(diào)試模塊返回的調(diào)試結(jié)果,可見,本發(fā)明提出的Java字節(jié)碼調(diào)試器能夠有效地提高軟件工程師的調(diào)試效率。
本發(fā)明還提供一種Java字節(jié)碼調(diào)試方法,該Java字節(jié)碼調(diào)試方法包括:
S1、從Java源代碼文件中提取字符信息,創(chuàng)建字符庫模塊;
S2、從Java字節(jié)碼文件中提取符號(hào)信息和數(shù)據(jù)值,建立緩存模塊;
S3、在Kei在Keil μVision集成開發(fā)環(huán)境中,配置Keil通道使其分別與Java字節(jié)碼調(diào)試器的調(diào)試模塊和虛擬機(jī)建立通信連接;
S4、用戶直接在Java字節(jié)碼上設(shè)置斷點(diǎn),該斷點(diǎn)被同步到Keil通道來執(zhí)行調(diào)試動(dòng)作;
S5、調(diào)試結(jié)束后,Keil通道將運(yùn)行到斷點(diǎn)位置的虛擬機(jī)的存儲(chǔ)器中對應(yīng)的Java棧整個(gè)提取出來發(fā)送到棧解析模塊;
S6、棧解析模塊接收執(zhí)行到斷點(diǎn)位置的虛擬機(jī)的存儲(chǔ)器中對應(yīng)的Java棧,通過訪問和加載緩存模塊中符號(hào)信息和數(shù)據(jù)信息來對Java棧進(jìn)行解析;
S7、引用解析模塊通過訪問和加載緩存模塊中符號(hào)信息和數(shù)據(jù)信息來對執(zhí)行到斷點(diǎn)位置的Java字節(jié)碼對應(yīng)的Java引用進(jìn)行解析;
S8、用戶通過步驟S6的解析結(jié)果和步驟S7的解析結(jié)果對執(zhí)行到當(dāng)前斷點(diǎn)的Java字節(jié)碼中的函數(shù)信息、變量信息及引用對象進(jìn)行查看。
具體地,所述Java字節(jié)碼調(diào)試方法中步驟S1以方法為單位對從Java源代碼文件中獲取的符號(hào)信息進(jìn)行組織,生成符號(hào)文件來創(chuàng)建字符庫模塊;其中,符號(hào)文件的文件名與Java字節(jié)碼文件中的方法全名相對應(yīng),符號(hào)文件的文件名依次包括包名、類名、方法名、參數(shù)編碼和返回值編碼;符號(hào)文件的內(nèi)容包括方法的源代碼起始行號(hào)、方法體的起始行號(hào)、方法體的終止行號(hào)、所有函數(shù)的參數(shù)信息和所有函數(shù)的局部變量信息。
可選地,所述Java字節(jié)碼調(diào)試方法中的步驟S2采用四級緩存的方式對從Java字節(jié)碼文件中提取符號(hào)信息和數(shù)據(jù)值進(jìn)行緩存,四級緩存從上到下依次為系統(tǒng)緩存、包緩存、類緩存和方法緩存。
可選地,所述Java字節(jié)碼調(diào)試方法中的步驟S4中至少包括單步執(zhí)行、跳進(jìn)執(zhí)行、跳出執(zhí)行和執(zhí)行到光標(biāo)處中的至少一個(gè)調(diào)試動(dòng)作。
可選地,所述Java字節(jié)碼調(diào)試方法的步驟S4和步驟S5中間還包括:Java 字節(jié)碼調(diào)試器對虛擬機(jī)中的存儲(chǔ)器進(jìn)行存儲(chǔ)訪問的步驟,該步驟中,通過將執(zhí)行存儲(chǔ)訪問任務(wù)所需要的函數(shù)信息和Keil通道信息以DLL文件統(tǒng)一到虛擬機(jī)代碼體系,再由Java字節(jié)碼調(diào)試器對其進(jìn)行調(diào)用來實(shí)現(xiàn);其中,DLL文件由GNU makefile平臺(tái)調(diào)用VC編譯器和鏈接器,對實(shí)現(xiàn)存儲(chǔ)訪問任務(wù)所需要的文件進(jìn)行編譯和鏈接來生成;實(shí)現(xiàn)存儲(chǔ)訪問任務(wù)所需要的文件包括:Keil工程中定義的除.c或.h文件中定義的宏之外的其他宏的.mak文件、Keil工程中定義的所有包含路徑的.mak文件、Keil工程中Java字節(jié)碼調(diào)試器需要的.c文件的.mak文件、屏蔽Keil工程中有而VC環(huán)境不支持的關(guān)鍵字的.h文件、定義對虛擬機(jī)中的存儲(chǔ)器進(jìn)行尋址和存儲(chǔ)訪問的.c文件、定義計(jì)算Java數(shù)組或Java對象大小的.c文件和定義所有被Java字節(jié)碼調(diào)試器調(diào)用的函數(shù)、全局變量或宏等的.c文件。
具體地,所述Java字節(jié)碼調(diào)試方法的步驟S6中的Java字節(jié)碼調(diào)試器對緩存模塊的訪問和加載過程包括:
當(dāng)用戶對系統(tǒng)緩存進(jìn)行首次訪問時(shí),加載并生成所有的包對象;
當(dāng)用戶對每個(gè)包緩存進(jìn)行首次訪問時(shí),加載該包中類庫的所有內(nèi)容,包括所有類的類信息和所有方法的方法信息;
當(dāng)用戶對每個(gè)類對象進(jìn)行首次訪問時(shí),由類組件從類庫獲取并生成該類對象所屬包內(nèi)的所有類對象;
當(dāng)用戶對每個(gè)方法對象進(jìn)行首次訪問時(shí),由方法組件從類庫獲取并生成該方法對象所屬包內(nèi)的所有方法對象。
可選地,所述Java字節(jié)碼調(diào)試方法還包括:用戶根據(jù)調(diào)試返回的信息在Java字節(jié)碼文件中進(jìn)行關(guān)鍵字搜索的步驟,以對導(dǎo)致程序運(yùn)行異常的函數(shù)參數(shù)或局部變量等信息進(jìn)行修改和確認(rèn),該步驟以包為單位進(jìn)行關(guān)鍵字的搜索任務(wù),當(dāng)需要對某個(gè)包中的方法進(jìn)行首次搜索時(shí),先掃描整個(gè)Java字節(jié)碼文件,將Java字節(jié)碼文件中與該包相關(guān)的信息提取到一個(gè)緩存中,再從該緩存對該包進(jìn)行搜索,搜索結(jié)果被顯示在列表框中,雙擊即可將光標(biāo)定位到Java字節(jié)碼文件中相應(yīng)的行。
可選地,所述Java字節(jié)碼調(diào)試方法還包括:在Java字節(jié)碼文件和Java源代碼文件之間進(jìn)行雙向定位的步驟。
本發(fā)明提供的Java字節(jié)碼調(diào)試方法應(yīng)用于具有如上結(jié)構(gòu)的Java字節(jié)碼調(diào)試器,用戶預(yù)先創(chuàng)建了符號(hào)庫模塊和緩存模塊,然后配置Keil通道使其分別與Java字節(jié)碼調(diào)試器的調(diào)試模塊和虛擬機(jī)建立通信連接,使得Java字節(jié)碼文件可以在虛擬機(jī)上運(yùn)行并調(diào)試,調(diào)試時(shí),用戶直接在Java字節(jié)碼上設(shè)置斷點(diǎn),將該斷點(diǎn)同步到Keil通道即可執(zhí)行調(diào)試動(dòng)作,調(diào)試結(jié)束后Keil通道將運(yùn)行到斷點(diǎn)位置的虛擬機(jī)的存儲(chǔ)器中的Java棧整個(gè)提取出來對Java棧進(jìn)行解析,進(jìn)一步地對Java引用對象進(jìn)行解析,然后通過解析結(jié)果對運(yùn)行到當(dāng)前斷點(diǎn)的調(diào)試返回的Java字節(jié)碼中的各種函數(shù)信息、變量信息及引用對象進(jìn)行方便地查看。如上所述,一方面,本發(fā)明提出的Java字節(jié)碼調(diào)試方法利用Keil平臺(tái)作為傳輸通道,使得Java字節(jié)碼文件可以在虛擬機(jī)上運(yùn)行,實(shí)現(xiàn)了基于Java字節(jié)碼的調(diào)試功能;另一方面,本發(fā)明提出的Java字節(jié)碼調(diào)試方法預(yù)先創(chuàng)建了符號(hào)庫模塊和緩存模塊,對Java字節(jié)碼文件和Java源代碼碼文件中的符號(hào)信息和數(shù)據(jù)信息做了計(jì)算和緩存,使得棧解析模塊和引用解析模塊能夠快速地解析出調(diào)試模塊返回的調(diào)試結(jié)果,可見,本發(fā)明提出的Java字節(jié)碼調(diào)試方法能夠有效地提高軟件工程師的調(diào)試效率。
附圖說明
為了更清楚地說明本申請實(shí)施例或現(xiàn)有技術(shù)中的技術(shù)方案,下面將對實(shí)施例或現(xiàn)有技術(shù)描述中所需要使用的附圖作簡單地介紹,顯而易見地,下面描述中的附圖僅僅是本申請中記載的一些實(shí)施例,對于本領(lǐng)域普通技術(shù)人員來講,還可以根據(jù)這些附圖獲得其他的附圖。
圖1是Java字節(jié)碼調(diào)試器的結(jié)構(gòu)圖;
圖2是緩存模塊存儲(chǔ)數(shù)據(jù)時(shí)采用的四級緩存結(jié)構(gòu)的示意圖;
圖3是Java字節(jié)碼調(diào)試方法的流程圖;
圖4使Java字節(jié)碼調(diào)試器對虛擬機(jī)中的存儲(chǔ)器進(jìn)行存儲(chǔ)訪問的示意圖。
附圖標(biāo)記說明:
1-Java字節(jié)碼調(diào)試器;2-符號(hào)庫模塊;3-緩存模塊;4-調(diào)試模塊;5-棧解析模塊;6-引用解析模塊;7-Java字節(jié)碼文件;8-Keil通道;9-虛擬機(jī);10-靜態(tài)變量解析模塊。
具體實(shí)施方式
下面將結(jié)合本發(fā)明實(shí)施例中的附圖,對本發(fā)明實(shí)施例中的技術(shù)方案進(jìn)行清楚、完整地描述,顯然,所描述的實(shí)施例是本發(fā)明一部分實(shí)施例,而不是全部的實(shí)施例?;诒景l(fā)明中的實(shí)施例,本領(lǐng)域普通技術(shù)人員在沒有做出創(chuàng)造性勞動(dòng)前提下所獲得的所有其他實(shí)施例,都屬于本發(fā)明保護(hù)的范圍。
本發(fā)明實(shí)施例提供一種Java字節(jié)碼調(diào)試器1,如圖1所示,Java字節(jié)碼調(diào)試器1包括符號(hào)庫模塊2、緩存模塊3、調(diào)試模塊4、棧解析模塊5和引用解析模塊6。
其中,符號(hào)庫模塊2用于從Java源代碼文件中獲取符號(hào)信息(symbol),并存放符號(hào)信息。
可選地,符號(hào)信息以Java method(方法)為單位進(jìn)行組織,文件名是method的全名稱,和Java字節(jié)碼文件7中的method全名相對應(yīng),依次包括package(包)名、class(類)名、method名、參數(shù)編碼和返回值編碼,示例性地,符號(hào)文件的內(nèi)容包含:method的源代碼起始行號(hào)(可能是注釋行)method body的起始行號(hào);method body的終止行號(hào);所有的函數(shù)參數(shù)信息:name(名稱),type(類型),…;所有的局部變量信息:name(名稱),type(類型),…。
緩存模塊3,用于從Java字節(jié)碼文件7中獲取符號(hào)信息和數(shù)據(jù)信息,并緩存符號(hào)信息和數(shù)據(jù)信息。
可選地,緩存模塊3共分為四級緩存(cache),如圖2所示,從上到下依次為系統(tǒng)緩存(System cache)、包緩存(package cache)、類緩存(class cache)和方法緩存(method cache)。示例性地,系統(tǒng)緩存的內(nèi)容包括所有 的包,每個(gè)包的內(nèi)容又包含該包的name、ID、包引用和CP(類庫)引用信息,類庫的作用是指定類運(yùn)行所依賴的其他類的路徑。示例性地,包緩存的內(nèi)容包括所有類庫和靜態(tài)變量,每個(gè)類庫的內(nèi)容又包含該包中所有類的類信息(Class Info)和所有方法的方法信息(Method Info),其中每個(gè)類的類信息又包含該類的全名稱、類庫索引(CP index)和是否是接口(interface)的標(biāo)志信息,每個(gè)方法信息又包含該方法的全名稱和類庫索引信息;靜態(tài)變量以包為單位進(jìn)行組織,每個(gè)靜態(tài)變量又包含該靜態(tài)變量的名稱、類型、長度(length)和位置(CS2)等信息。示例性地,類緩存的內(nèi)容包括是否是接口的標(biāo)志信息、類引用(class reference)、父類的類引用、類實(shí)例(class instance)的字節(jié)碼大小(in short,2bytes per unit)、類組件(Class component)在字節(jié)碼(BC)文件7中的行號(hào)和所有的類實(shí)例的域值(fields)信息,其中類實(shí)例的域值信息又包含該類實(shí)例的名稱、類型和在類實(shí)例中的位置信息(token),此外一個(gè)類中的類實(shí)例的域值信息中還包括了各級父類的類實(shí)例域值信息。示例性地,方法緩存的內(nèi)容包括方法實(shí)現(xiàn)字節(jié)碼在字節(jié)碼文件7中的開始行號(hào)、方法的4個(gè)元數(shù)據(jù)信息(flags,maxStack,nargs和maxLocals)、方法的位置信息(CS3)、方法位置信息(BAddr)和方法的字節(jié)碼大小(in bytes)等信息。
調(diào)試模塊4,用于通過Keil通道8與虛擬機(jī)9連接,使得Java字節(jié)碼文件7可在虛擬機(jī)9上運(yùn)行并調(diào)試,其中,用戶直接在Java字節(jié)碼上設(shè)置斷點(diǎn),調(diào)試模塊4將該斷點(diǎn)同步到Keil通道8進(jìn)行調(diào)試,調(diào)試結(jié)束后,調(diào)試模塊4通過Keil通道8將運(yùn)行到斷點(diǎn)位置的虛擬機(jī)9的存儲(chǔ)器中的Java棧提取出來發(fā)送到棧解析模塊5。
如圖1所示,Java字節(jié)碼調(diào)試器與Keil通道之間采用TCP協(xié)議(Transmission Control Protocol,傳輸控制協(xié)議)進(jìn)行通信,TCP協(xié)議是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議,由IETF的RFC 793定義,在簡化的計(jì)算機(jī)網(wǎng)絡(luò)OSI(Open System Interconnection,開放式系統(tǒng)互聯(lián)模型)中,它完成第四層傳輸層所指定的功能,在因特網(wǎng)協(xié)議族中,TCP 層是位于IP層之上,應(yīng)用層之下的中間層。
棧解析模塊5,用于接收運(yùn)行到斷點(diǎn)位置的虛擬機(jī)9的存儲(chǔ)器中的Java棧,并對Java棧進(jìn)行解析,其中,解析結(jié)果包括執(zhí)行到斷點(diǎn)位置時(shí)應(yīng)用程序?qū)?yīng)的Java函數(shù)的調(diào)用關(guān)系、函數(shù)參數(shù)信息、函數(shù)局部變量值和地址信息中的至少一個(gè),示例性地,函數(shù)參數(shù)名稱和類型、局部變量名稱和類型的解析均來自對符號(hào)庫文件的訪問。
引用解析模塊6,用于對執(zhí)行到斷點(diǎn)位置時(shí)Java字節(jié)碼對應(yīng)的Java引用進(jìn)行解析,其中,如果Java引用指向一個(gè)Java對象,根據(jù)Java對象的存儲(chǔ)方式和規(guī)則進(jìn)行解析,解析出這個(gè)Java對象所屬的Java類別及其對應(yīng)的狀態(tài)、擁有者和域值中的至少一個(gè);如果Java引用指向一個(gè)數(shù)組,則解析出這個(gè)數(shù)組元素的類型和所有元素的值。
可選地,Java字節(jié)碼調(diào)試器1還包括靜態(tài)變量解析模塊10,用于對Java字節(jié)碼中的靜態(tài)變量進(jìn)行解析,并允許開發(fā)者在任意時(shí)刻選擇任意一個(gè)靜態(tài)變量進(jìn)行解析和查看,其中,Java字節(jié)碼文件7中所有的靜態(tài)變量均以包的形式進(jìn)行組織,然后存儲(chǔ)在虛擬機(jī)9的存儲(chǔ)器中并且存儲(chǔ)地址固定。
本發(fā)明實(shí)施例提供的Java字節(jié)碼調(diào)試器1具有如上所述的結(jié)構(gòu),其中符號(hào)庫模塊2和緩存模塊3預(yù)先計(jì)算并緩存了大量信息,然后連接Keil通道8使得Java字節(jié)碼可以在虛擬機(jī)9上運(yùn)行并調(diào)試,用戶直接在Java字節(jié)碼上設(shè)置斷點(diǎn),將該斷點(diǎn)同步到Keil通道8即可進(jìn)行調(diào)試,調(diào)試結(jié)束后Keil通道8將運(yùn)行到斷點(diǎn)位置的虛擬機(jī)9的存儲(chǔ)器中對應(yīng)的Java棧整個(gè)提取出來進(jìn)行Java棧解析,進(jìn)一步地對Java引用對象進(jìn)行解析。如上所述,一方面,本發(fā)明提出的Java字節(jié)碼調(diào)試器1利用Keil通道8使得Java字節(jié)碼文件7可以在虛擬機(jī)9上運(yùn)行,實(shí)現(xiàn)了基于Java字節(jié)碼的調(diào)試功能;另一方面,本發(fā)明提出的Java字節(jié)碼調(diào)試器1中的符號(hào)庫模塊2和緩存模塊3預(yù)先對Java字節(jié)碼文件7和Java源代碼文件中的符號(hào)信息和數(shù)據(jù)信息做了計(jì)算和緩存,使得棧解析模塊5和引用解析模塊6能夠快速地解析出調(diào)試模塊4返回的調(diào)試結(jié)果,可見,本發(fā)明提出的Java字節(jié)碼調(diào)試器1能夠有效地提高軟件工程師 的調(diào)試效率。
本發(fā)明實(shí)施例還提供一種Java字節(jié)碼調(diào)試方法,如圖3所示,應(yīng)用于如上所述的Java字節(jié)碼調(diào)試器1,包括:
步驟S1、從Java源代碼文件中提取字符信息,創(chuàng)建字符庫模塊;
步驟S2、從Java字節(jié)碼文件中提取符號(hào)信息和數(shù)據(jù)值,建立緩存模塊;
步驟S3、在Keil μVision集成開發(fā)環(huán)境中,配置Keil通道使其分別與Java字節(jié)碼調(diào)試器的調(diào)試模塊和虛擬機(jī)建立通信連接;
步驟S4、用戶直接在Java字節(jié)碼上設(shè)置斷點(diǎn),該斷點(diǎn)被同步到Keil通道來執(zhí)行調(diào)試動(dòng)作;
步驟S5、調(diào)試結(jié)束后,Keil通道將運(yùn)行到斷點(diǎn)位置的虛擬機(jī)的存儲(chǔ)器中對應(yīng)的Java棧整個(gè)提取出來發(fā)送到棧解析模塊;
步驟S6、棧解析模塊接收執(zhí)行到斷點(diǎn)位置的虛擬機(jī)的存儲(chǔ)器中對應(yīng)的Java棧,通過訪問和加載緩存模塊來對Java棧進(jìn)行解析;
步驟S7、棧解析模塊接收執(zhí)行到斷點(diǎn)位置的虛擬機(jī)的存儲(chǔ)器中對應(yīng)的Java棧,通過訪問和加載緩存模塊中符號(hào)信息和數(shù)據(jù)信息來對Java棧進(jìn)行解析;
步驟S8、用戶通過步驟S6的解析結(jié)果和步驟S7的解析結(jié)果對執(zhí)行到當(dāng)前斷點(diǎn)的Java字節(jié)碼中的函數(shù)信息、變量信息及引用對象進(jìn)行查看。
進(jìn)一步地,在本發(fā)明實(shí)施例提出的Java字節(jié)碼調(diào)試方法的步驟S1之前的準(zhǔn)備工作包括:打開Java字節(jié)碼調(diào)試器1并新建一個(gè)工程,加載準(zhǔn)備調(diào)試的Java字節(jié)碼文件7,由于Java字節(jié)碼文件7數(shù)據(jù)量較大,為了不影響前臺(tái)的用戶操作,其加載過程放在了后臺(tái)進(jìn)行,加載的進(jìn)度和狀態(tài)等信息在狀態(tài)欄中進(jìn)行顯示,當(dāng)Java字節(jié)碼文件7正確加載后,所有的Java字節(jié)碼文件7的內(nèi)容以標(biāo)簽頁(tab page)的方式顯示在主窗口中,顯示時(shí),每個(gè)標(biāo)簽頁中預(yù)先填入1000行數(shù)據(jù),其它數(shù)據(jù)放到后臺(tái)進(jìn)行加載,在程序空閑(idle)時(shí)再進(jìn)行加載。
具體地,Java字節(jié)碼調(diào)試方法中步驟S1以方法(method)為單位對從 Java源代碼文件中獲取的符號(hào)信息進(jìn)行組織,生成符號(hào)文件來創(chuàng)建字符庫模塊;其中,符號(hào)文件的文件名是method的全名稱,和Java字節(jié)碼文件7中的method全名相對應(yīng),依次包括package(包)名、class(類)名、method名、參數(shù)編碼和返回值編碼,示例性地,符號(hào)文件的內(nèi)容包含:method的源代碼起始行號(hào)(可能是注釋行)method body的起始行號(hào);method body的終止行號(hào);所有的函數(shù)參數(shù)信息:name(名稱),type(類型),…;所有的局部變量信息:name(名稱),type(類型),…。由于字符庫模塊2包含了關(guān)于Java原代碼文件的詳細(xì)字符信息,從而為解析返回的調(diào)試碼的信息提供了路徑。
可選地,如圖2所示,Java字節(jié)碼調(diào)試方法中的步驟S2采用四級緩存的方式對從Java字節(jié)碼文件7中提取符號(hào)信息和數(shù)據(jù)值進(jìn)行緩存,四級緩存從上到下依次為系統(tǒng)緩存(System cache)、包緩存(package cache)、類緩存(class cache)和方法緩存(method cache)。示例性地,系統(tǒng)緩存的內(nèi)容包括所有的包,每個(gè)包的內(nèi)容又包含該包的name、ID、包引用和CP(類庫)引用信息,類庫的作用是指定類運(yùn)行所依賴的其他類的路徑。示例性地,包緩存的內(nèi)容包括所有類庫和靜態(tài)變量,每個(gè)類庫的內(nèi)容又包含該包中所有類的類信息(Class Info)和所有方法的方法信息(Method Info),其中每個(gè)類的類信息又包含該類的全名稱、類庫索引(CP index)和是否是接口(interface)的標(biāo)志信息,每個(gè)方法信息又包含該方法的全名稱和類庫索引信息;靜態(tài)變量以包為單位進(jìn)行組織,每個(gè)靜態(tài)變量又包含該靜態(tài)變量的名稱、類型、長度(length)和位置(CS2)等信息。示例性地,類緩存的內(nèi)容包括是否是接口的標(biāo)志信息、類引用(class reference)、父類的類引用、類實(shí)例(class instance)的字節(jié)碼大小(in short,2bytes per unit)、類組件(Class component)在字節(jié)碼(BC)文件7中的行號(hào)和所有的類實(shí)例的域值(fields)信息,其中類實(shí)例的域值信息又包含該類實(shí)例的名稱、類型和在類實(shí)例中的位置信息(token),此外一個(gè)類中的類實(shí)例的域值信息中還包括了各級父類的類實(shí)例域值信息。示例性地,方法緩存的內(nèi)容包括方法實(shí)現(xiàn)字節(jié)碼在字節(jié)碼文件7 中的開始行號(hào)、方法的4個(gè)元數(shù)據(jù)信息(flags,maxStack,nargs和maxLocals)、方法的位置信息(CS3)、方法位置信息(BAddr)和方法的字節(jié)碼大小(in bytes)等信息。本發(fā)明實(shí)施例中的緩存模塊3采用四級緩存的方式將Java字節(jié)碼文件7中包含的大量的符號(hào)信息、數(shù)據(jù)信息及其注釋進(jìn)行了合理地緩存布局,不僅使得程序開發(fā)者一目了然,而且優(yōu)化了對執(zhí)行調(diào)試后返回信息的解析過程,加快了解析速度。
可選地,Java字節(jié)碼調(diào)試方法中的步驟S4中至少包括單步執(zhí)行、跳進(jìn)執(zhí)行、跳出執(zhí)行和執(zhí)行到光標(biāo)處中的至少一個(gè)調(diào)試動(dòng)作,其中單步執(zhí)行(Step over)指不進(jìn)入到子函數(shù)的運(yùn)行方式;跳進(jìn)執(zhí)行(Step into)指進(jìn)入到子函數(shù)的運(yùn)行方式;跳出執(zhí)行(Step out)指從當(dāng)前子函數(shù)跳出的運(yùn)行方式;執(zhí)行到光標(biāo)處(Run to cursor)指運(yùn)行到當(dāng)前選擇的行,這樣本發(fā)明實(shí)施例提出的Java字節(jié)碼調(diào)試器1就可以直接在Java字節(jié)碼上按照通用的調(diào)試動(dòng)作進(jìn)行調(diào)試。
可選地,Java字節(jié)碼調(diào)試方法的步驟S4和步驟S5中間還包括:Java字節(jié)碼調(diào)試器1對虛擬機(jī)9中的存儲(chǔ)器進(jìn)行存儲(chǔ)訪問的步驟,如圖4所示,該步驟中,通過將執(zhí)行存儲(chǔ)訪問任務(wù)所需要的函數(shù)信息和Keil通道信息以DLL文件統(tǒng)一到虛擬機(jī)9代碼體系,再由Java字節(jié)碼調(diào)試器1對其進(jìn)行調(diào)用來實(shí)現(xiàn);其中,DLL文件由GNU makefile平臺(tái)調(diào)用VC編譯器和鏈接器,對實(shí)現(xiàn)存儲(chǔ)訪問任務(wù)所需要的文件進(jìn)行編譯和鏈接來生成;實(shí)現(xiàn)存儲(chǔ)訪問任務(wù)所需要的文件包括:Keil工程中定義的除.c或.h文件中定義的宏之外的其他宏的.mak文件、Keil工程中定義的所有包含路徑的.mak文件、Keil工程中Java字節(jié)碼調(diào)試器需要的.c文件的.mak文件、屏蔽Keil工程中有而VC環(huán)境不支持的關(guān)鍵字的.h文件、定義對虛擬機(jī)中的存儲(chǔ)器進(jìn)行尋址和存儲(chǔ)訪問的.c文件、定義計(jì)算Java數(shù)組或Java對象大小的.c文件和定義所有被Java字節(jié)碼調(diào)試器調(diào)用的函數(shù)、全局變量或宏等的.c文件。如上所述,本發(fā)明實(shí)施例提出的Java字節(jié)碼調(diào)試器1選取Keil工程中Java字節(jié)碼調(diào)試器1實(shí)現(xiàn)調(diào)試功能所需要的文件,將Keil平臺(tái)8作為傳輸通道,從而實(shí)現(xiàn)了對虛擬機(jī)9中存 儲(chǔ)器的存儲(chǔ)與訪問。
具體地,Java字節(jié)碼調(diào)試方法的步驟S6中的Java字節(jié)碼調(diào)試器1對緩存模塊3的訪問和加載過程包括:當(dāng)用戶對系統(tǒng)緩存進(jìn)行首次訪問時(shí),加載并生成所有的包對象;當(dāng)用戶對每個(gè)包緩存進(jìn)行首次訪問時(shí),加載該包中類庫的所有內(nèi)容,包括所有類的類信息和所有方法的方法信息;當(dāng)用戶對每個(gè)類對象進(jìn)行首次訪問時(shí),由類組件從類庫獲取并生成該類對象所屬包內(nèi)的所有類對象;當(dāng)用戶對每個(gè)方法對象進(jìn)行首次訪問時(shí),由方法組件從類庫獲取并生成該方法對象所屬包內(nèi)的所有方法對象,本發(fā)明實(shí)施例通過上述方法實(shí)現(xiàn)了Java字節(jié)碼調(diào)試器1對緩存模塊3的快速訪問和加載。
可選地,Java字節(jié)碼調(diào)試方法還包括:用戶根據(jù)調(diào)試返回的信息在Java字節(jié)碼文件7中進(jìn)行關(guān)鍵字搜索的步驟,以對導(dǎo)致程序運(yùn)行異常的函數(shù)參數(shù)或局部變量等信息進(jìn)行修改和確認(rèn),該步驟以包為單位進(jìn)行關(guān)鍵字的搜索任務(wù),當(dāng)需要對某個(gè)包中的方法進(jìn)行首次搜索時(shí),先掃描整個(gè)Java字節(jié)碼文件7,將Java字節(jié)碼文件7中與該包相關(guān)的信息提取到一個(gè)緩存中,再從該緩存對該包進(jìn)行搜索,搜索結(jié)果被顯示在列表框(listbox)中,雙擊即可將光標(biāo)定位到Java字節(jié)碼文件7中相應(yīng)的行,本發(fā)明實(shí)施例通過上述方法使得用戶可以快速地在Java字節(jié)碼文件7中進(jìn)行關(guān)鍵字搜索,以對導(dǎo)致程序運(yùn)行異常的函數(shù)參數(shù)或局部變量等信息進(jìn)行修改和確認(rèn)。
可選地,Java字節(jié)碼調(diào)試方法還包括在Java字節(jié)碼文件7和Java源代碼文件之間進(jìn)行雙向定位的步驟。Java字節(jié)碼文件7和Java源代碼文件可以以視窗的形式并列顯示,當(dāng)用戶選中任意一行Java字節(jié)碼時(shí),對照地,該行Java字節(jié)碼對應(yīng)的Java源代碼所在的行也被選中;反之,當(dāng)用戶選中任意一行Java源代碼時(shí),對照地,該行Java源代碼對應(yīng)的Java字節(jié)碼所在的行也被選中。
本發(fā)明提供的Java字節(jié)碼調(diào)試方法應(yīng)用于具有如上結(jié)構(gòu)的Java字節(jié)碼調(diào)試器1,用戶預(yù)先創(chuàng)建了符號(hào)庫模塊2和緩存模塊3,然后配置Keil通道8使其分別與Java字節(jié)碼調(diào)試器1的調(diào)試模塊4和虛擬機(jī)9建立通信連接,使 得Java字節(jié)碼文件7可以在虛擬機(jī)9上運(yùn)行并調(diào)試,調(diào)試時(shí),用戶直接在Java字節(jié)碼上設(shè)置斷點(diǎn),將該斷點(diǎn)同步到Keil通道8即可執(zhí)行調(diào)試動(dòng)作,調(diào)試結(jié)束后Keil通道8將運(yùn)行到斷點(diǎn)位置的虛擬機(jī)9的存儲(chǔ)器中的Java棧整個(gè)提取出來對Java棧進(jìn)行解析,進(jìn)一步地對Java引用對象進(jìn)行解析,然后通過解析結(jié)果對運(yùn)行到當(dāng)前斷點(diǎn)的調(diào)試返回的Java字節(jié)碼中的各種函數(shù)信息、變量信息及引用對象進(jìn)行方便地查看。如上所述,一方面,本發(fā)明提出的Java字節(jié)碼調(diào)試方法利用Keil平臺(tái)8作為傳輸通道,使得Java字節(jié)碼文件7可以在虛擬機(jī)9上運(yùn)行,實(shí)現(xiàn)了基于Java字節(jié)碼的調(diào)試功能;另一方面,本發(fā)明提出的Java字節(jié)碼調(diào)試方法預(yù)先創(chuàng)建了符號(hào)庫模塊2和緩存模塊3,對Java字節(jié)碼文件7和Java源代碼碼文件中的符號(hào)信息和數(shù)據(jù)信息做了計(jì)算和緩存,使得棧解析模塊5和引用解析模塊6能夠快速地解析出調(diào)試模塊返回的調(diào)試結(jié)果,可見,本發(fā)明提出的Java字節(jié)碼調(diào)試方法能夠有效地提高軟件工程師的調(diào)試效率。
盡管已描述了本申請的優(yōu)選實(shí)施例,但本領(lǐng)域內(nèi)的技術(shù)人員一旦得知了基本創(chuàng)造性概念,則可對這些實(shí)施例作出另外的變更和修改。所以,所附權(quán)利要求意欲解釋為包括優(yōu)選實(shí)施例以及落入本申請范圍的所有變更和修改。顯然,本領(lǐng)域的技術(shù)人員可以對本申請進(jìn)行各種改動(dòng)和變型而不脫離本申請的精神和范圍。這樣,倘若本申請的這些修改和變型屬于本申請權(quán)利要求及其等同技術(shù)的范圍之內(nèi),則本申請也意圖包含這些改動(dòng)和變型在內(nèi)。