《電子技術(shù)應(yīng)用》
您所在的位置:首頁 > 其他 > 業(yè)界動(dòng)態(tài) > Java字節(jié)碼編程語言設(shè)計(jì)及實(shí)現(xiàn)

Java字節(jié)碼編程語言設(shè)計(jì)及實(shí)現(xiàn)

2008-12-19
作者:黨石宇,廖湖聲

1. 引言
??? 眾所周知,Java語言依靠Java虛擬機(jī)對字節(jié)碼程序的支持,實(shí)現(xiàn)了跨平臺(tái)特征。作為一種中間語言,Java字節(jié)碼提供了匯編指令級(jí)的程序描述,能夠支持底層的程序代碼優(yōu)化" title="代碼優(yōu)化">代碼優(yōu)化。然而,目前的Java字節(jié)碼程序都是通過Java編譯系統(tǒng)" title="編譯系統(tǒng)">編譯系統(tǒng)生成的,人們?nèi)鄙僖环N直接利用Java字節(jié)碼進(jìn)行程序設(shè)計(jì)" title="程序設(shè)計(jì)">程序設(shè)計(jì)的工具。為此,本文提出一種Java字節(jié)碼編程語言" title="編程語言">編程語言,通過提供一個(gè)Java字節(jié)碼生成系統(tǒng),直接支持Java字節(jié)碼程序設(shè)計(jì)。系統(tǒng)實(shí)現(xiàn)中,選用了Apache組織中的開放源碼項(xiàng)目BCEL(Byte Code Engineering Library,字節(jié)碼工程庫)作為Java字節(jié)碼生成工具。
2.?Java字節(jié)碼編程語言設(shè)計(jì)
??? Java字節(jié)碼編程語言的提出,是為了產(chǎn)生優(yōu)化的字節(jié)碼程序,可用于對Java源程序的編譯系統(tǒng),以及各種程序變換和程序優(yōu)化系統(tǒng)。字節(jié)碼的表達(dá)和優(yōu)化能力都優(yōu)于Java程序,一些Java語言中無法實(shí)現(xiàn)的功能,利用字節(jié)碼可進(jìn)行描述,例如字節(jié)碼中可使用goto跳轉(zhuǎn)命令,而Java語言沒有這個(gè)功能。
??? Java字節(jié)碼編程語言文法的設(shè)計(jì),兼顧了Java語言規(guī)范文法與Java虛擬機(jī)的指令格式,采用二者相結(jié)合的形式。Java字節(jié)碼編程語言的程序結(jié)構(gòu)由一個(gè)或多個(gè)類組成,每個(gè)類中有一個(gè)或多個(gè)域,域分為變量域和方法域,方法中包含了具體的指令語句,指令語句根據(jù)虛擬機(jī)指令設(shè)計(jì)。下面具體列出部分文法。
??? 類定義文法沿用Java語言規(guī)范:

表1 類定義文法

Modifierà???? public | protected | private | static | abstract | final | native | synchronized | ?

??????????????????????????? transient | volatile | strictfp ?

ModifiersOptà????? { Modifier }?

ClassDeclarationàclass Identifier [extends Type] [implements TypeList] ClassBody?

InterfaceDeclarationà interface Identifier [extends TypeList] InterfaceBody?

ClassOrInterfaceDeclarationà ModifiersOpt (ClassDeclaration | InterfaceDeclaration)?

?

ClassBodyà{{ClassBodyDeclaration}}?

ClassBodyDeclarationà ; | [static] Block?? | ModifiersOpt? MemberDecl?

?

MemberDeclà?????? MethodOrFieldDecl?????? | void Identifier VoidMethodDeclaratorRest? |?

Identifier ConstructorDeclaratorRest??? |ClassOrInterfaceDeclaration|?

?

??? 方法體(MethodBody)設(shè)計(jì)為由塊(Block)組成,塊由多個(gè)塊語句(BlockStatements)組成,塊語句又分為局部變量聲明語句(LocalVariableDeclarationStatement)、類或接口定義語句(ClassOrInterfaceDeclaration)和指令語句(Instruction)。

??? 指令的設(shè)計(jì)則參考了Java虛擬機(jī)的指令格式,提供了虛擬機(jī)指令的所有功能,按功能可分為以下七類語句:

  • 裝載和存儲(chǔ)語句(Load_Store
  • 運(yùn)算語句(Arithmetic
  • 類型轉(zhuǎn)換語句(Type_ Conversion
  • 對象創(chuàng)建和操縱語句(Object_Create_Manipulation
  • 操作數(shù)棧管理語句(Operand_Stack_Management
  • 控制轉(zhuǎn)移語句(Control_Transfer
  • 方法調(diào)用" title="方法調(diào)用">方法調(diào)用和返回語句(Method_Invoke_Return)。

??? 相應(yīng)文法如下表:

????????????????????????????????????? 表2 方法及指令定義文法

MethodBodyà Block?

Blockà { BlockStatements }?

BlockStatementsà {BlockStatement}

BlockStatementà?? LocalVariableDeclarationStatement????? |?

ClassOrInterfaceDeclaration?????????????? |?

[Identifier:] Instruction;?

Instructionà? BlockStatement?????????????????????????? | Load_Store?????????????????????????????? |?

???????????????????? Arithmetic????????????????????????????????? | Type_ Conversion????????????????????? |?

Object_Create_Manipulation ????? | Operand_Stack_Management???? |?

Control_Transfer???????????????????????? | Method_Invoke_Return?

?

指令語句中方法調(diào)用和返回語句的文法如表3:

????????????????????????????????? 表3 方法調(diào)用和返回語句文法

MethodNameà Identifier?

RetTypeà Type?

ArgTypeà {[TypeList]}?

MethodInvokeKeyword à ?? invokevirtual????????????? | invokeinterface? |?

invokespecial????????????? | invokestatic ?

Method_Invoke_Returnà MethodInvokeKeyword (ClassName, MethodName, RetType, ArgType) |?

?ireturn | lreturn | freturn | dreturn | areturn | return?

??? 上表中,方法調(diào)用分為以下四種類型:

  • 調(diào)用對象的示例方法,調(diào)度對象的(虛)類型:invokevirtual
  • 調(diào)用由接口實(shí)現(xiàn)的方法:invokeinterface
  • 調(diào)用需要特殊處理的實(shí)例方法,即實(shí)例初始化方法、private方法或超類方法:invokespecial
  • 調(diào)用命名的類中的類(static)方法:invokestatic

3? Java字節(jié)碼生成系統(tǒng)功能及結(jié)構(gòu)?

??? Java字節(jié)碼生成系統(tǒng)的輸入為Java字節(jié)碼編程語言,輸出為Java字節(jié)碼文件。字節(jié)碼生成系統(tǒng)的功能是讀入Java字節(jié)碼編程語言程序,通過BCEL(字節(jié)碼工程庫)生成字節(jié)碼文件。

??? BCEL字節(jié)碼工程庫是一個(gè)工具包,用于對Java類文件的靜態(tài)分析,動(dòng)態(tài)創(chuàng)建或修改。開發(fā)人員能夠使用BCEL 庫在一個(gè)較高的抽象層次上實(shí)現(xiàn)所需的功能,而不用具體處理Java字節(jié)碼文件的內(nèi)部細(xì)節(jié)。BCEL完全用Java語言寫成,并遵守LGPL條款。

由于BCEL庫是針對Java的class文件格式和虛擬機(jī)指令集所設(shè)計(jì)的,直接應(yīng)用BCEL庫進(jìn)行Java字節(jié)碼文件的生成比較困難,需要了解較多的Java虛擬機(jī)方面的知識(shí)。本文提出的Java字節(jié)碼編程語言的文法與BCEL庫的字節(jié)碼生成接口相對應(yīng),易于應(yīng)用BCEL庫進(jìn)行編譯,完成字節(jié)碼生成。Java字節(jié)碼編程語言成為一座連接Java源程序和字節(jié)碼文件的橋梁,先將Java源程序編譯為中間代碼,再使用BCEL庫將中間代碼編譯為Java字節(jié)碼,生成class文件。

??? Java字節(jié)碼生成系統(tǒng)可分為詞法分析、語法分析和字節(jié)碼生成三個(gè)階段,其用例圖如下:

???????????????????? 圖1 Java字節(jié)碼生成系統(tǒng)的用例圖

??? 系統(tǒng)的數(shù)據(jù)流圖可表示為:

???? Java字節(jié)碼生成系統(tǒng)中,字節(jié)碼編程語言與BCEL庫中字節(jié)碼生成接口具有對應(yīng)關(guān)系,以方法調(diào)用為例,如下表:

表4 java字節(jié)碼編程語言與BCEL庫生成接口對應(yīng)關(guān)系

Java字節(jié)碼編程語言方法調(diào)用文法

BCEL庫生成接口

MethodNameà Identifier?

?

RetTypeà Type?

?

ArgTypeà {[TypeList]}?

?

MethodInvokeKeyword à ?? ?

invokevirtual?????????? | invokeinterface? |?

invokespecial?????????? | invokestatic ?

?

Method_Invoke_Returnà ?

MethodInvokeKeyword(ClassName, MethodName, RetType, ArgType)???? |?

ireturn | lreturn | freturn | dreturn ?? | areturn | return? ?

BCEL庫中類InstructionFactory的方法:?

public InvokeInstruction createInvoke

(String class_name, String name, Type ret_type,Type[] arg_types, short kind)

//kind對應(yīng)invokevirtual , invokeinterface?????? , invokespecial , invokestatic

public static

ReturnInstruction createReturn(Type type)

//type類型對應(yīng)關(guān)系:

T_ARRAY,T_OBJECTà areturn;

T_INT,T_SHORT,T_BOOLEAN,

T_CHAR,T_BYTEà ireturn;

T_FLOATà freturn;

T_DOUBLEà dreturn;

T_LONGà lreturn;

T_VOIDà return;

4?Java字節(jié)碼生成示例?

??? 下面通過生成階乘Java程序字節(jié)碼的介紹,說明Java字節(jié)碼生成系統(tǒng)功能。左邊是求階乘的Java源程序,右邊是相應(yīng)的字節(jié)碼編程語言代碼。

??? 階乘Java源程序 其中calculateFactorial方法的字節(jié)碼編程語言代碼??

?????????????????????????? 表5 階乘程序和相應(yīng)字節(jié)碼編程語言代碼

階乘Java源程序?

其中calculateFactorial方法的字節(jié)碼編程語言代碼?

public class Factorial?

{?

public int calculateFactorial(int x)?

{?

?????? if (x<0)?

?????? ? throw? new ?

IllegalArgumentException?

('x must be >=0');?

int ret=1;?

for(int i=1;i<=x;i++)?

?????? ? ret=ret*i;?

?????? return ret;?

}?

public static void main?

(String[] args)?

? {?

?????? Factorial f=new Factorial();?

int n=6;?

?????? System.out.println(?

f.calculateFactorial(n) );?

? }?

}?

public class Factorial?

{?

public int calculateFactorial(int x)?

? {? ?

iload? x;?

??? ifge “if1”;?

??? new “java.lang.IllegalArgumentException”;?

??? dup;?

??? ldc “x must be >=0”;?

??? invokespecial ('java.lang.IllegalArgumentException' ,?

'' ,?

void, ?

{'java.lang.String'});?

??? athrow;?

if1:? int ret;?

push 1;?

??? istore ret;?

??? int i;?

??? push 1;?

??? istore i;?

for_begin:??? iload? i;?

??? iload? x;?

??? if_icmpgt “if2”;?

??? iload? ret;?

??? iload? i;?

??? imul;?

??? istore? ret;?

??? iinc? i? 1;?

??? goto “for_begin”;?

if2:??? iload? ret;?

??? ireturn;?

}?

}?

??? 字節(jié)碼編程語言代碼編譯為BCEL庫調(diào)用,以階乘為例,以階乘為例,分別討論:

  • 類和方法聲明:?

????????????????????????????????? ? 表6 類和方法聲明轉(zhuǎn)換

字節(jié)碼編程語言代碼?

BCEL庫生成代碼?

public class Factorial

{

public int

?calculateFactorial(int x)

? {?

……

? }

}?

ClassGen cg =

new ClassGen( "Factorial", "java.lang.Object", "Factorial",

ACC_PUBLIC| ACC_SUPER, null );

ConstantPoolGen cp = cg.getConstantPool();

InstructionList il = new InstructionList();

MethodGen mg =

new MethodGen( ACC_PUBLIC, Type.INT ,

new Type[]{Type.INT},

??????????????????????????? new String[]{"x"} ,?????? "calculateFactorial",

??????????????????????????? "Factorial", il, cp );?

?

  • 方法調(diào)用:?

?????????????????????????????????? 表7 方法調(diào)用轉(zhuǎn)換

字節(jié)碼編程語言代碼?

BCEL庫生成代碼?

invokespecial (?

"java.lang.IllegalArgumentException" ,

"" ,

void,

{"java.lang.String"});

il.append( factory.createInvoke(

"java.lang.IllegalArgumentException",

? "",

? Type.VOID,

? new Type[]

{new ObjectType("java.lang.String")},

? INVOKESPECIAL ) );?

?

結(jié)束語?

使用Java字節(jié)碼編程語言來完成字節(jié)碼的生成,屏蔽了底層生成字節(jié)碼的具體方法,通過生成相應(yīng)虛擬機(jī)命令的擴(kuò)展形式,降低了字節(jié)碼生成的難度。

Java字節(jié)碼編程語言的應(yīng)用廣泛,可用于Java代碼優(yōu)化,如對Java源程序進(jìn)行部分求值優(yōu)化后,可對生成的滯留程序和例化程序編譯為中間語言的形式,在利用BCEL庫生成字節(jié)碼,完成進(jìn)一步的字節(jié)碼優(yōu)化。還可以對Java字節(jié)碼編程語言進(jìn)行優(yōu)化,去掉冗余的控制轉(zhuǎn)移和方法調(diào)用,進(jìn)而生成更緊湊的Java字節(jié)碼。

參考文獻(xiàn)?

[1] James Gosling,Bill Joy,Guy Steele,Gilad Bracha 《The Java Language Specification》 ADDISON-WESLEY? 2000

[2] Markus Dahm《Byte Code Engineering With the BCEL API》

Freie Universit?t Berlin Institut für Informatik, Technical Report B-17-98? http://inf.fuberlin.de/pub/BCEL/report.ps

[3] 玄偉劍等譯.《Java 虛擬機(jī)規(guī)范》.北京大學(xué)出版社,1997


本站內(nèi)容除特別聲明的原創(chuàng)文章之外,轉(zhuǎn)載內(nèi)容只為傳遞更多信息,并不代表本網(wǎng)站贊同其觀點(diǎn)。轉(zhuǎn)載的所有的文章、圖片、音/視頻文件等資料的版權(quán)歸版權(quán)所有權(quán)人所有。本站采用的非本站原創(chuàng)文章及圖片等內(nèi)容無法一一聯(lián)系確認(rèn)版權(quán)者。如涉及作品內(nèi)容、版權(quán)和其它問題,請及時(shí)通過電子郵件或電話通知我們,以便迅速采取適當(dāng)措施,避免給雙方造成不必要的經(jīng)濟(jì)損失。聯(lián)系電話:010-82306118;郵箱:aet@chinaaet.com。