国产日韩欧美一区二区三区三州_亚洲少妇熟女av_久久久久亚洲av国产精品_波多野结衣网站一区二区_亚洲欧美色片在线91_国产亚洲精品精品国产优播av_日本一区二区三区波多野结衣 _久久国产av不卡

?

一種基于芯片仿真VCD波形格式的Java程序自動(dòng)調(diào)試方法

2019-08-02 05:09趙鴻昌

摘 要:為提高調(diào)試的效率,作者提出一種Java程序自動(dòng)調(diào)試方法?;贘DI技術(shù)實(shí)現(xiàn)了Java程序的自動(dòng)調(diào)試,設(shè)計(jì)了用戶代碼的單步進(jìn)入和Java庫代碼的單步跳出的切換調(diào)試策略,最終得到程序運(yùn)行過程中所有變量值的變化軌跡,并利用Linux腳本將其保存成芯片仿真領(lǐng)域波形數(shù)據(jù)翻轉(zhuǎn)的通用VCD存儲(chǔ)格式。開源VCD文件查看器所展示的效果說明這種Java程序自動(dòng)調(diào)試方法有助于學(xué)生理解程序運(yùn)行的全局過程,能激發(fā)學(xué)生提出細(xì)節(jié)問題,遠(yuǎn)勝于當(dāng)前純軟件的人工單步調(diào)試方法。此外,文章所述的調(diào)試方法作為綜合運(yùn)用軟硬件技術(shù)的教學(xué)案例,適合培養(yǎng)軟硬件綜合人才的多學(xué)科協(xié)同創(chuàng)新能力,對(duì)教育信息化軟件的內(nèi)涵提升提供了借鑒。

關(guān)鍵詞:Java程序;自動(dòng)調(diào)試;芯片仿真VCD格式;軟硬件協(xié)同創(chuàng)新

中圖分類號(hào):TP312 ? ? ? ? 文獻(xiàn)標(biāo)志碼:B ? ? ? ? ?文章編號(hào):1673-8454(2019)12-0091-06

一、引言

充分利用信息技術(shù)手段激發(fā)學(xué)生的創(chuàng)新熱情、提高各個(gè)階段的教學(xué)質(zhì)量和教學(xué)效率已成為國家教育事業(yè)發(fā)展“十三五”規(guī)劃的重點(diǎn)[1],因此,未來信息技術(shù)課程的教學(xué)質(zhì)量尤其重要,承載著國家教育信息化的愿景,直接決定了能否實(shí)現(xiàn)信息技術(shù)與教育過程的深度融合。作為經(jīng)典的信息技術(shù)課程, Java不僅僅是一門程序設(shè)計(jì)課程,更是當(dāng)今諸多實(shí)用軟硬件技術(shù)環(huán)境的代名詞。一方面,Java與Linux腳本相結(jié)合演化而來的Scala語言同時(shí)是大數(shù)據(jù)人工智能軟件Spark和開源處理器RISC-V的設(shè)計(jì)語言,代表了程序設(shè)計(jì)的發(fā)展方向。另一方面,Java技術(shù)生態(tài)圈中的Java虛擬機(jī)(Java Virtual Machine, JVM)提供了越來越多的先進(jìn)技術(shù),而這些先進(jìn)技術(shù)已經(jīng)很難在常規(guī)程序設(shè)計(jì)課程中教學(xué),問題的難度和廣度遠(yuǎn)超出了課堂容量。例如,Java調(diào)試接口(Java Debugging Interface, JDI)技術(shù)用于遠(yuǎn)程調(diào)試服務(wù)器的出錯(cuò)線程[2];JVM反射技術(shù)用以實(shí)現(xiàn)類的動(dòng)態(tài)加載和服務(wù)器軟件的容器內(nèi)熱部署;再如,實(shí)踐中需要十分綜合的軟件背景和硬件知識(shí),而不是孤立的編程語言課程或硬件電路設(shè)計(jì)課程,才能理解JVM反射應(yīng)用于開源RISC-V處理器生成環(huán)境的連線生成過程[3]。

眾所周知,調(diào)試是精通程序設(shè)計(jì)的必要手段,但對(duì)于Java程序,不論經(jīng)典的jdb命令行調(diào)試工具還是Eclipse等圖形界面調(diào)試工具,都難以從宏觀整體上把握程序的運(yùn)行過程,很難直觀理解靜態(tài)的程序與動(dòng)態(tài)的進(jìn)程之間的關(guān)系??梢?,在這樣一個(gè)信息技術(shù)日新月異的時(shí)代,Java程序設(shè)計(jì)課程作為教育信息化戰(zhàn)場(chǎng)的排頭兵,亟待在Java調(diào)試方法上取得突破。理想的Java調(diào)試方法要與信息化教學(xué)工具合二為一,不僅要能多維度地啟發(fā)學(xué)生的思考與提問,實(shí)現(xiàn)學(xué)習(xí)、應(yīng)用與創(chuàng)新的密切結(jié)合從而成為素質(zhì)教育的平臺(tái),還要盡可能地將學(xué)習(xí)內(nèi)容拓展到軟硬件融合創(chuàng)新的層面,最終實(shí)現(xiàn)軟硬件綜合人才多學(xué)科協(xié)同創(chuàng)新能力的培養(yǎng),全面提升國家教育信息化從業(yè)人員的技術(shù)水平。

反觀硬件設(shè)計(jì)和芯片仿真領(lǐng)域,其中有很多成熟的電子設(shè)計(jì)自動(dòng)化工具可以借鑒,通過發(fā)掘軟件問題與硬件問題的相似性,往往可以用極低的投入整合出巧妙的軟件功能。例如,芯片仿真驗(yàn)證用到的System Verilog語言具有生成約束隨機(jī)激勵(lì)的功能,如果將硬件激勵(lì)的每一位與試題庫中的每道題目相對(duì)應(yīng),就能類比地解決約束隨機(jī)抽取題目的自動(dòng)組卷問題[4]。因此,以成熟的芯片仿真驗(yàn)證軟件為基礎(chǔ)作二次開發(fā)能有效地加速教育信息化軟件的快速原型化。本文基于芯片仿真領(lǐng)域的波形變化值存儲(chǔ)(Value Change Dump, VCD)格式保存Java程序執(zhí)行過程中的所有變量值的變化軌跡,并利用成熟的VCD查看軟件輔助分析程序執(zhí)行的過程。整個(gè)項(xiàng)目的實(shí)現(xiàn)過程十分巧妙,對(duì)于軟件的自動(dòng)化測(cè)試和硬件的查錯(cuò)兩方面均具有很強(qiáng)的參考價(jià)值。

二、Java程序自動(dòng)調(diào)試環(huán)境的要求

調(diào)試是精通程序設(shè)計(jì)的必由之路,更是從原理上理解數(shù)據(jù)結(jié)構(gòu)與算法的有力工具。縱觀當(dāng)前以jdb為代表的命令行調(diào)試工具和Eclipse等圖形界面調(diào)試工具,本質(zhì)上常用的調(diào)試方法主要分兩類:

一是日志記錄法。通過人工加入若干關(guān)鍵變量的打印語句,在程序運(yùn)行后分析日志中的變量變化情況以查找程序中的問題。如此就要插入大量的打印語句,對(duì)于多源碼項(xiàng)目顯然是一件費(fèi)力的工作,而且源碼的改動(dòng)也要再耗時(shí)編譯。

二是單步調(diào)試法,即利用調(diào)試工具加斷點(diǎn),然后在斷點(diǎn)處單步調(diào)試查看變量值的變化情況是否符合預(yù)期。盡管Eclipse、IntelliJ IDEA等工具已經(jīng)提供了圖形化的用戶調(diào)試界面,但是斷點(diǎn)的增刪仍需要手工設(shè)置,而且調(diào)試過程中默認(rèn)只顯示當(dāng)前運(yùn)行堆棧中的局部變量,想看到其他對(duì)象中的變量值也只能手工切換堆?;蚴止ぜ颖O(jiān)視器。此外,限于調(diào)試者的經(jīng)驗(yàn)和精力,單步調(diào)試時(shí)每個(gè)時(shí)刻無法關(guān)注所有變量的值的變化情況,常常需要手工記錄若干關(guān)鍵變量值的變化軌跡,調(diào)試中常常顧此失彼,調(diào)試手段上缺乏整體性的把握。

調(diào)試實(shí)踐中通常綜合使用上述兩種方法。先用日志記錄法查看程序的整體運(yùn)行情況,再分析出可疑的出錯(cuò)位置,然后在可疑位置上設(shè)置斷點(diǎn)并用單步調(diào)試法查看相關(guān)變量值的變化軌跡。對(duì)于稍微復(fù)雜的調(diào)試過程,一旦人工操作有疏忽從而越過了可疑的出錯(cuò)位置,就只能再重新調(diào)試找到可疑的出錯(cuò)位置,這是因?yàn)閖db工具缺少gdb工具的checkpoint保存回退功能??梢姡琂ava程序的調(diào)試效率往往比較低下,對(duì)程序的整體運(yùn)行情況也缺乏宏觀上的把握,因此,理想的Java程序調(diào)試器要能記錄所有變量值的變化軌跡,并且能簡(jiǎn)潔直觀地顯示,還要盡量降低手工的工作量,理想情況是Java程序一經(jīng)運(yùn)行完畢立即顯示出所有變量值的變化軌跡。此外,理想的Java程序調(diào)試器還要能盡量拓展出硬件設(shè)計(jì)相關(guān)的知識(shí),從而對(duì)于軟件課程來說得以展示出軟硬件知識(shí)足夠豐富的細(xì)節(jié)場(chǎng)景,以激發(fā)出學(xué)生千差萬別的問題和自主探究的熱情。

三、技術(shù)方案與可行性分析

本文在上述背景下提出了Java程序自動(dòng)調(diào)試方法,能利用芯片仿真驗(yàn)證領(lǐng)域的波形展示工具顯示出所有變量值的變化軌跡。整個(gè)技術(shù)方案分兩步,首先基于JDI技術(shù)設(shè)計(jì)自動(dòng)斷點(diǎn)調(diào)試策略,然后打印出所有變量的即時(shí)值,免除了所有手工的調(diào)試操作。其次,通過分析芯片仿真驗(yàn)證領(lǐng)域的VCD波形格式與軟件變量值變化的聯(lián)系與異同,確立了用VCD文件保存軟件變量值的可行性。

1.JDI技術(shù)

因?yàn)镴ava程序運(yùn)行在JVM之上,所以JVM擁有程序運(yùn)行過程中的所有控制權(quán)限。本質(zhì)上,各種Java程序的調(diào)試工具都是利用JDI向JVM發(fā)送命令,從而控制程序的整體運(yùn)行過程,包括設(shè)置斷點(diǎn)、查看斷點(diǎn)處的變量值等等。

一般地,發(fā)出JDI調(diào)試命令的Java程序稱作控制程序,調(diào)試時(shí)的作用完全類似Eclipse工具。控制程序中使用JDI提供的事件管理器EventRequestManager,能控制行斷點(diǎn)BreakpointEvent及單步斷點(diǎn)StepEvent的啟停,通過偵聽JVM的事件隊(duì)列EventQueue可以實(shí)現(xiàn)斷點(diǎn)的處理函數(shù),即相當(dāng)于設(shè)定了斷點(diǎn)調(diào)試策略。最終,被控制Java程序便在控制程序的指揮下自動(dòng)地執(zhí)行了多次斷點(diǎn)處理函數(shù),實(shí)現(xiàn)了自動(dòng)調(diào)試。

2.VCD文件格式

VCD文件格式是芯片仿真軟件的標(biāo)準(zhǔn)波形數(shù)據(jù)存儲(chǔ)格式[5],開源的波形展示軟件GTKWave和商業(yè)的Cadence SimVision軟件均可支持。VCD文件格式組織形式十分簡(jiǎn)單,包括時(shí)間單位定義、連線定義和連線變值三個(gè)區(qū)域,形式如下:

1 $timescale

2 ?1 ps

3 $end

4 $scope module zdut $end

5 $var wire 4 zdut.goodSort.arr_0_ ?zdut.goodSort.arr_0_ $end

6 $var wire 4 zdut.goodSort.arr_1_ ?zdut.goodSort.arr_1_ $end

7 $var wire 4 zdut.goodSort.arr_2_ ?zdut.goodSort.arr_2_ $end

8 $var wire 4 zdut.main.arr_0_ ?zdut.main.arr_0_ $end

9 $var wire 4 zdut.main.arr_0_ ?zdut.main.arr_1_ $end

10 $var wire 4 zdut.main.arr_0_ ?zdut.main.arr_2_ $end

11 $upscope $end

12 #1

13 b100 zdut.main.arr_0_

14 b011 zdut.main.arr_1_

15 b111 zdut.main.arr_2_

16 #2

17 b100 zdut.main.arr_0_

18 b111 zdut.main.arr_1_

19 b011 zdut.main.arr_2_

其中,以$timescale標(biāo)明的前三行區(qū)域設(shè)置時(shí)間單位是1ps,即每一步變化的歷時(shí),此數(shù)值對(duì)于軟件調(diào)試來說可任意設(shè)置,因?yàn)檐浖魂P(guān)心所有變量的值有改動(dòng)的單步操作,至于這一“步”歷時(shí)1ps或是1ns均無關(guān)緊要。

由$scope和$upscope之間標(biāo)明的區(qū)域則給出連線的定義,形式為:

$var wire 位寬 短名 長(zhǎng)名 $end

其中,位寬決定了該連線所存儲(chǔ)的變量的取值范圍,例如4位即表示無符號(hào)數(shù)只能取0到15之間。連線的名字分長(zhǎng)短的原因是VCD旨在減少文件尺寸,芯片仿真時(shí)動(dòng)輒若干GB的波形文件要在連線變值區(qū)域中用短名取代完整名,當(dāng)然存儲(chǔ)量不關(guān)鍵的場(chǎng)合長(zhǎng)名與短名可以相同,短名甚至亦可長(zhǎng)于長(zhǎng)名。連線的名字可以包含“[]”之外的特殊符號(hào),例如可以用點(diǎn)號(hào)表示類中的函數(shù)或是函數(shù)中的局部變量這種歸屬關(guān)系,第5行到第7行就定義了類zdut中的函數(shù)goodSort()中的局部數(shù)組變量arr[0]到arr[2]。

連線變值區(qū)域又分成若干子區(qū)域,每個(gè)子區(qū)域?qū)?yīng)一個(gè)時(shí)刻所有變量的值的改動(dòng)情況,例如第12行和第16行開始的4行分別表示時(shí)刻1ps和2ps時(shí)變量zdut.main.arr_1_等的值有變動(dòng)。對(duì)于值沒有變化的連線可寫可不寫,例如第17行就是冗余的,VCD文件格式能大幅度減少存儲(chǔ)量的原因即在于只記錄了變化的波形值。

3.技術(shù)可行性分析

VCD格式中的$scope和$upscope支持多層嵌套,以反映硬件設(shè)計(jì)中的模塊與子模塊的包含關(guān)系。但對(duì)應(yīng)到軟件的類和函數(shù)的情況時(shí),這種硬件的包含關(guān)系便不再關(guān)鍵,完全可以組織成打平成一層的$scope和$upscope形式,只要從變量名上區(qū)分變量的從屬關(guān)系即可,例如使用“類名.函數(shù)名.變量名”的格式。經(jīng)上述分析可見,如果把程序中的函數(shù)和類當(dāng)作硬件設(shè)計(jì)中的模塊,把函數(shù)和類中的變量當(dāng)作硬件設(shè)計(jì)中最基礎(chǔ)的連線變量,那么將所有軟件變量值的變化軌跡記錄到VCD文件中是完全可行的。而且如此的優(yōu)點(diǎn)是可以使用芯片仿真領(lǐng)域成熟的波形展示軟件,當(dāng)程序一次運(yùn)行后便能全方位地分析它的運(yùn)行過程。

四、技術(shù)實(shí)現(xiàn)與細(xì)節(jié)問題

Java程序的自動(dòng)調(diào)試包括兩個(gè)組件,控制程序和被控制程序??刂瞥绦蛟O(shè)定自動(dòng)調(diào)試的策略,令被控制程序在指定的斷點(diǎn)處執(zhí)行相應(yīng)的斷點(diǎn)處理函數(shù),打印出變量的值,而被控制程序則是一般的Java程序。兩者的運(yùn)行順序也有嚴(yán)格的時(shí)序關(guān)系,因此涉及到一定的運(yùn)行技巧,而變量的值保存為VCD文件的過程也需要Linux腳本的技巧。

1.被控制程序

被控制程序的核心代碼如下,其中main函數(shù)中的變量arr以值傳遞和引用傳遞的方式分別執(zhí)行了一次冒泡排序。又為了展示由波形查錯(cuò)的直觀性,badSort()函數(shù)設(shè)計(jì)中人為加了一個(gè)bug:即數(shù)值1無法排序。

1 public class zdut {

2 public static void main(String[] args) {

3 ? ?Thread.sleep(3000);

4 ? ?int[] arr={4,3,7,2,11,1};

5 ? ?for(int num:arrOutNonClone) print(num+ " ");

6 ? ?int[] arrOutClone = goodSort(arr.clone());

7 ? ?for(int num:arrOutClone) print(num+ " ");

8 ? ?int[] arrOutNonClone = badSort(arr);

9 ? ?for(int num:arrOutNonClone) print(num+ " ");

10 }

11 public static int[] goodSort(int[] arr) {

12 ? ?boolean needSwap;

13 ? ?int tmp;

14 ? ?for(int i=0;i

15 ? ? ?for(int j=0;j

16 ? ? ?{ needSwap = arr[j] > arr[j+1];

17 ? ? ? ?if(needSwap){

18 ? ? ? ? ?tmp=arr[j];

19 ? ? ? ? ?arr[j]=arr[j+1];

20 ? ? ? ? ?arr[j+1]=tmp;

21 ? ? ? ?}

22 ? ? ?}

23 ? ? ?}

24 ? ?}

25 ? ?return arr;

26 ?}

27 public static int[] badSort(int[] arr) {

函數(shù)體與goodSort()相同,除第17行改作: if(needSwap && (1!=arr[j+1])){

28 }

值得一提的是,代碼中第3行的延遲3秒是出于實(shí)際運(yùn)行的考慮。因?yàn)楸豢刂瞥绦虮仨氁扔诳刂瞥绦蜻\(yùn)行,否則JDI接口找不到zdut類,從而無法加斷點(diǎn)即無法接管被控制程序的運(yùn)行;另一方面,被控制程序執(zhí)行的時(shí)間一般很短,為保證在控制程序運(yùn)行前仍未運(yùn)行結(jié)束,就必須人為地加入適當(dāng)?shù)难舆t,具體數(shù)值以方便調(diào)試為原則。

2.控制程序與調(diào)試策略

控制程序的代碼軟件較多,核心功能是設(shè)定調(diào)試策略。通常情況下很少關(guān)心Java庫代碼的執(zhí)行過程,因此可設(shè)定用戶代碼的調(diào)試方式為單步進(jìn)入,而Java庫代碼采用單步跳出的切換調(diào)試策略,相關(guān)偽代碼摘錄如下:

public static void main(String[] args) {

連接被控制程序;

在類zdut的第4行加BreakpointRequest類型的斷點(diǎn);

循環(huán)調(diào)用execute()函數(shù)處理JVM的事件eventQueue;

}

private static void execute(Event event) {

if (event ?instanceof ?BreakpointEvent)

在當(dāng)前線程上設(shè)置STEP_INTO 類型的斷點(diǎn)

else if (event ?instanceof ?StepEvent) {

打印“Step hit:”

打印當(dāng)前堆棧StackFrame.visibleVariables()中的所有變量值

if(event.location().sourcePath()).indexOf("sun/") == -1 &&

event.location().sourcePath()).indexOf("java/") == -1)

在當(dāng)前線程上設(shè)置STEP_INTO 類型的斷點(diǎn)

打印“now to STEP_INTO”

else

在當(dāng)前線程上設(shè)置STEP_OUT 類型的斷點(diǎn)

打印“now to STEP_OUT”

else ;

}

3.編譯與運(yùn)行技巧

被控制程序編譯時(shí)要設(shè)置javac -g選項(xiàng),確保生成局部變量的調(diào)試信息,而控制程序編譯時(shí)的路徑還要包含JDK目錄下的tools.jar文件。運(yùn)行時(shí),被控制程序要先于控制程序,并以服務(wù)的形式運(yùn)行:java -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 ?zdut。如此,被控制程序就處于等待JDI命令的狀態(tài),當(dāng)然如果沒有控制程序發(fā)來JDI命令,被控制程序就正常執(zhí)行直到結(jié)束。根據(jù)被控制程序中延遲3秒的設(shè)計(jì)可知,控制程序必須在被控制程序啟動(dòng)后的3秒內(nèi)發(fā)出第一個(gè)JDI調(diào)試命令。

4.Linux腳本與VCD文件生成

在被控制程序單步運(yùn)行的過程中,控制程序打印出的日志文件摘錄如下:

Step hit:

in Method: java.lang.StringBuilder.toString()

now to STEP_OUT

Step hit:

in Method: zdut.main(java.lang.String[])

zdut.main(java.lang.String[]).arr[0]: 2

zdut.main(java.lang.String[]).arr[1]: 3

zdut.main(java.lang.String[]).arr[2]: 4

zdut.main(java.lang.String[]).arr[3]: 7

zdut.main(java.lang.String[]).arr[4]: 11

zdut.main(java.lang.String[]).arr[5]: 1

zdut.main(java.lang.String[]).arrOutClone[0]: 1

zdut.main(java.lang.String[]).arrOutClone[1]: 2

zdut.main(java.lang.String[]).arrOutClone[2]: 3

zdut.main(java.lang.String[]).arrOutClone[3]: 4

zdut.main(java.lang.String[]).arrOutClone[4]: 7

zdut.main(java.lang.String[]).arrOutClone[5]: 11

now to STEP_INTO

對(duì)比此日志文件格式與VCD文件格式中的時(shí)間單位定義、連線定義和連線變值三個(gè)區(qū)域,可見日志文件轉(zhuǎn)成VCD文件只涉及兩個(gè)關(guān)鍵步驟,即連線定義區(qū)域的生成和連線變值區(qū)域的生成。完整的Linux腳本如下,其中連線定義的生成包括三步:取出所有有變值的行、連線名去重和生成$var格式的連線,依次見第5、6、8 行。

1 echo "\$timescale"

2 echo " 1 ps"

3 echo "\$end"

4 echo "\$scope module zdut \$end"

5 cat 1.log | grep ^zdut | sed 's/:.*//g' ?\

6 ? | sort | uniq \

7 ? | sed 's/(.*)//g' | grep "\." \

8 ? | sed 's/^\(.*\)/$var wire 4 \1 \1 $end/g'

9 echo "\$upscope \$end"

10

11 cat 1.log | sed 's/ true/ 1/g' | sed 's/ false/ 0/g' \

12 ? ? ? ? | grep "^zdut\|now to" \

13 ? ? ? ? | awk -F ": " ?'{ printf("%s", zD2B($2));} ?print " "$1 }' \

14 ? ? ? ? | sed 's/.*now to.*/#www/g' | sed 's/(.*)//g' \

15 ? ? ? ? | awk -v RS="www" '{n+=1;printf $0n}'

連線變值區(qū)域的生成則包括四步:取出所有含有變值的行以及含有“now to”的行(第12行腳本),變量值由10進(jìn)制數(shù)值化為2進(jìn)制(第13行腳本),且邏輯型變量true/false化為1/0(第11行腳本)。而含有“now to”的行則使用awk遞增替換為“#1”“#2”“#3”的形式(第14、15行腳本)以記錄VCD文件中的時(shí)刻變化。

五、結(jié)果展示

用開源軟件GTKWave打開VCD波形文件,被控制程序中所有變量值的變化軌跡圖展示于圖1。由圖1可見,程序執(zhí)行的全過程中所有變量的變化情況一目了然,這是傳統(tǒng)的軟件調(diào)試工具jdb或Eclipse等所不具備的。相比傳統(tǒng)調(diào)試工具,圖1更能有效激發(fā)學(xué)生的自主發(fā)現(xiàn)、提問與學(xué)習(xí)的熱情,能生動(dòng)地化解傳統(tǒng)Java程序的教學(xué)難點(diǎn)。

1.程序執(zhí)行整體過程的理解

VCD文件格式規(guī)定未賦值變量的初始值顯示作“x”或“xxx”,因此圖1中波形展示的程序變量的賦值順序?yàn)閙ain().arr、goodSort().arr、main().arrOutClone、badSort().arr、main().arrOutNonClone,與Java程序的設(shè)計(jì)完全吻合。學(xué)生由此很容易建立起程序與進(jìn)程兩個(gè)概念動(dòng)靜態(tài)的直觀印象,為深入理解軟件的工作機(jī)理打下良好的基礎(chǔ)。而且,由goodSort()函數(shù)中的數(shù)據(jù)波形的變化規(guī)律,能直觀地看到數(shù)值“1”和“2”向上逐級(jí)跳躍,形象地展示了冒泡排序算法的原理,而badSort()函數(shù)中的排序算法存在一個(gè)bug,數(shù)值“1”未按期望向上逐級(jí)跳躍,數(shù)據(jù)波形亦展示得很清晰。

2.細(xì)節(jié)問題的自主發(fā)現(xiàn)

按值傳遞或是按引用傳遞是Java函數(shù)調(diào)用時(shí)實(shí)參的教學(xué)難點(diǎn),學(xué)生一般難以從書本上獲得直觀的認(rèn)識(shí),而圖1中的波形不但形象地展示出二者的不同,而且還能揭示出更一般的原理。例如,goodSort()函數(shù)的實(shí)參使用了值傳遞,因此161ps時(shí)刻其返回值改變了主函數(shù)中的變量main().arrOutClone,但傳入的參數(shù)main().arr并未改變,相比之下,badSort()函數(shù)使用了引用傳遞的方式,所以它的返回值同時(shí)改變了主函數(shù)中的變量main().arrOutNonClone和傳入變量main().arr。

至此,細(xì)心的學(xué)生還會(huì)發(fā)現(xiàn)變量main().arrOutNonClone和main().arr的數(shù)據(jù)批量改變的時(shí)刻不同,分別是303ps和302ps。兩者相差1ps實(shí)則反映出Java程序運(yùn)行環(huán)境中對(duì)傳入?yún)?shù)的鎖定規(guī)則和堆棧中的局部變量返回的處理細(xì)節(jié),而這些細(xì)節(jié)知識(shí)只有通過學(xué)生自主發(fā)現(xiàn)才能激發(fā)其學(xué)習(xí)的興趣,才能自然地深入Java程序的編譯原理和JVM運(yùn)行時(shí)環(huán)境的相關(guān)知識(shí)。必須要指出,傳統(tǒng)的純軟件調(diào)試工具很難展示出這些細(xì)節(jié)知識(shí),而基于VCD波形的調(diào)試手段記錄了每個(gè)軟件變量每次值的變化情況,提供了全方位的數(shù)據(jù)變化信息,給學(xué)生挖掘程序執(zhí)行過程中的細(xì)節(jié)問題提供了平臺(tái)。此外,Gtkwave軟件提供了上百個(gè)菜單功能項(xiàng),本身即是軟件專業(yè)的學(xué)生拓展硬件知識(shí)的探索環(huán)境。

3.波形對(duì)比功能與自動(dòng)查錯(cuò)

在軟件開發(fā)與測(cè)試過程中,為了保證設(shè)計(jì)的正確性,通常由兩個(gè)或多個(gè)設(shè)計(jì)者獨(dú)立設(shè)計(jì)復(fù)雜的軟件模塊,然后插入大量的打印語句以實(shí)現(xiàn)運(yùn)行后的輸出變量或中間變量異同的自動(dòng)比較,工作過程耗時(shí)費(fèi)力。用VCD波形文件自動(dòng)展示所有變量值的變化軌跡十分適合作自動(dòng)對(duì)比,商用VCD波形展示軟件Cadence SimVision提供了波形比較功能[6],通過自動(dòng)對(duì)比關(guān)鍵的控制信號(hào)goodSort().needSwap、goodSort().tmp和badSort().needSwap、badSort().tmp的異同很容易發(fā)現(xiàn)程序的bug所在。這種來源于硬件仿真的調(diào)試技巧是傳統(tǒng)軟件調(diào)試領(lǐng)域從未觸及的,能開闊眼界且拓展思維,于軟件專業(yè)和硬件專業(yè)的教學(xué)均互補(bǔ)互益,更是培養(yǎng)學(xué)生軟件與硬件多學(xué)科協(xié)同創(chuàng)新能力的切入點(diǎn)。

4.條件斷點(diǎn)與創(chuàng)造力培養(yǎng)

條件斷點(diǎn)是調(diào)試中的有力手段,而jdb工具沒有提供原生的條件斷點(diǎn)支持,只能人為加入判斷代碼以實(shí)現(xiàn)條件斷點(diǎn)的調(diào)試功能,工作過程費(fèi)力且調(diào)試效率相對(duì)低下。相比之下,VCD展示軟件大多數(shù)都能提供波形的搜索功能,直接由給定條件定位到波形時(shí)刻,一次運(yùn)行后可以靜態(tài)地、多維度、多時(shí)刻分析變量值的各種變化情況。此外,VCD文件格式的開放性允許用戶定制Linux腳本以實(shí)現(xiàn)復(fù)雜條件的組合,大大提高了調(diào)試查錯(cuò)的效率,學(xué)習(xí)使用過程中如果遇到更復(fù)雜的條件斷點(diǎn),還會(huì)激發(fā)能力更強(qiáng)的學(xué)生修改開源軟件GTKWave的熱情??梢哉f,用VCD波形格式記錄變量值的變化軌跡為各個(gè)層次的學(xué)生提供了發(fā)現(xiàn)問題、解決問題以及施展創(chuàng)造力的平臺(tái)。

六、結(jié)束語

信息技術(shù)的綜合運(yùn)用是未來教育信息化研究與應(yīng)用的方向,只有軟件技術(shù)和硬件技術(shù)相貫通,才能在底層問題上尋找相似性,才能促進(jìn)學(xué)生多學(xué)科協(xié)同創(chuàng)新能力的培養(yǎng)。這方面加州大學(xué)伯克利分校同時(shí)用Scala語言開發(fā)開源大數(shù)據(jù)處理軟件Spark和開源RISC-V系列處理器便是一個(gè)有力的佐證。

本文基于與純軟件不相關(guān)的、芯片仿真驗(yàn)證用到的VCD波形格式保存Java程序自動(dòng)調(diào)試過程中軟件變量的值的變化情況,整個(gè)項(xiàng)目的實(shí)現(xiàn)過程巧妙,是一個(gè)綜合運(yùn)用軟件硬件技術(shù)開發(fā)的教學(xué)案例,對(duì)于軟件的自動(dòng)化測(cè)試和硬件的查錯(cuò)均具有很強(qiáng)的參考價(jià)值。所用到的實(shí)現(xiàn)技巧在信息化教育教學(xué)領(lǐng)域具有很強(qiáng)的實(shí)用性及推廣價(jià)值,利于軟硬件綜合人才多學(xué)科協(xié)同創(chuàng)新能力的培養(yǎng)。

本文所述的調(diào)試方法尚有幾點(diǎn)不足:一是凡是涉及到Java反射機(jī)制的程序還需要深入研究其JDI自動(dòng)調(diào)試方法,尤其是基于Java編譯器的Scala程序,其類型擦除操作涉及Java編譯原理和JVM運(yùn)行時(shí)環(huán)境的機(jī)制,變量值的獲取方法有待研究,斷點(diǎn)策略上也要涉及STEP_INTO、STEP_OUT、STEP_OVER及STEP_MIN這幾種方式的切換以實(shí)現(xiàn)更復(fù)雜的JVM進(jìn)程控制技術(shù)。二是有符號(hào)數(shù)、浮點(diǎn)數(shù)以及復(fù)雜數(shù)據(jù)結(jié)構(gòu)在VCD文件中的存儲(chǔ)格式尚不完善,很可能需要修改GTKWave的源碼才能正確展示。最后,如果能將大數(shù)據(jù)展示軟件如ECharts、MATLAB/Simulink中的Stateflow 圖以及組態(tài)軟件中真值表和流程圖與VCD文件相結(jié)合,會(huì)得到樣式更多、形式更生動(dòng)的大型程序如AVS2視頻編碼程序等運(yùn)行過程中變量值的變化情況,也將涉及更多學(xué)科知識(shí)的學(xué)習(xí)、應(yīng)用與創(chuàng)新融合,為實(shí)現(xiàn)未來編程語言高效率高質(zhì)量的素質(zhì)教育提供更多的實(shí)踐研究成果。

參考文獻(xiàn):

[1]國發(fā)[2017]4號(hào).國務(wù)院關(guān)于印發(fā)國家教育事業(yè)發(fā)展“十三五”規(guī)劃的通知[Z].

[2]錢毅,蔡小川.使用Java Debug Interface(JDI)調(diào)試多線程應(yīng)用程序:開發(fā)定制的多線程分析器[EB/OL]. https://www.ibm.com/developerworks/cn/java/j-lo-jdi/index.html.

[3]Krste Asanovi c' ,Rimas Avizienis,Jonathan Bachrach,et al.The Rocket Chip Generator[R].California(Berkeley):University of California,2016.

[4]趙鴻昌.基于芯片仿真驗(yàn)證軟件實(shí)現(xiàn)的一種試題庫與試卷[J].中國教育信息化,2018(14):89-92.

[5]Lambert M. Surhone, Mariam T. Tennoe, Susan F. Value Change Dump[M]. Mauritius:Betascript Publishing,2010.

[6]Cadence Design Systems.SimVision User Guide 8.2版本[R].California(San Jose):Cadence Design Systems,2009.

(編輯:魯利瑞)

冀州市| 龙岩市| 湘阴县| 四会市| 安阳市| 徐州市| 稷山县| 瑞丽市| 新干县| 天气| 马鞍山市| 兴仁县| 丹凤县| 肥城市| 马关县| 囊谦县| 图们市| 郴州市| 浦县| 平顶山市| 泰安市| 南昌市| 浙江省| 西乌珠穆沁旗| 曲靖市| 长武县| 金沙县| 壤塘县| 荔浦县| 枣阳市| 苏州市| 盈江县| 齐齐哈尔市| 壶关县| 谷城县| 报价| 怀远县| 沅陵县| 宜阳县| 双牌县| 封丘县|