《电子技术应用》
您所在的位置:首页 > 其他 > 业界动态 > Java字节码编程语言设计及实现

Java字节码编程语言设计及实现

2008-12-19
作者:党石宇,廖湖声

1. 引言
    众所周知,Java语言依靠Java虚拟机对字节码程序的支持,实现了跨平台特征。作为一种中间语言,Java字节码提供了汇编指令级的程序描述,能够支持底层的程序代码优化" title="代码优化">代码优化。然而,目前的Java字节码程序都是通过Java编译系统" title="编译系统">编译系统生成的,人们缺少一种直接利用Java字节码进行程序设计" title="程序设计">程序设计的工具。为此,本文提出一种Java字节码编程语言" title="编程语言">编程语言,通过提供一个Java字节码生成系统,直接支持Java字节码程序设计。系统实现中,选用了Apache组织中的开放源码项目BCEL(Byte Code Engineering Library,字节码工程库)作为Java字节码生成工具。
2. Java字节码编程语言设计
    Java字节码编程语言的提出,是为了产生优化的字节码程序,可用于对Java源程序的编译系统,以及各种程序变换和程序优化系统。字节码的表达和优化能力都优于Java程序,一些Java语言中无法实现的功能,利用字节码可进行描述,例如字节码中可使用goto跳转命令,而Java语言没有这个功能。
    Java字节码编程语言文法的设计,兼顾了Java语言规范文法与Java虚拟机的指令格式,采用二者相结合的形式。Java字节码编程语言的程序结构由一个或多个类组成,每个类中有一个或多个域,域分为变量域和方法域,方法中包含了具体的指令语句,指令语句根据虚拟机指令设计。下面具体列出部分文法。
    类定义文法沿用Java语言规范:

表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)设计为由块(Block)组成,块由多个块语句(BlockStatements)组成,块语句又分为局部变量声明语句(LocalVariableDeclarationStatement)、类或接口定义语句(ClassOrInterfaceDeclaration)和指令语句(Instruction)。

    指令的设计则参考了Java虚拟机的指令格式,提供了虚拟机指令的所有功能,按功能可分为以下七类语句:

  • 装载和存储语句(Load_Store
  • 运算语句(Arithmetic
  • 类型转换语句(Type_ Conversion
  • 对象创建和操纵语句(Object_Create_Manipulation
  • 操作数栈管理语句(Operand_Stack_Management
  • 控制转移语句(Control_Transfer
  • 方法调用" title="方法调用">方法调用和返回语句(Method_Invoke_Return)。

    相应文法如下表:

                                      表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 

 

指令语句中方法调用和返回语句的文法如表3:

                                  表3 方法调用和返回语句文法

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 

    上表中,方法调用分为以下四种类型:

  • 调用对象的示例方法,调度对象的(虚)类型:invokevirtual
  • 调用由接口实现的方法:invokeinterface
  • 调用需要特殊处理的实例方法,即实例初始化方法、private方法或超类方法:invokespecial
  • 调用命名的类中的类(static)方法:invokestatic

3  Java字节码生成系统功能及结构 

    Java字节码生成系统的输入为Java字节码编程语言,输出为Java字节码文件。字节码生成系统的功能是读入Java字节码编程语言程序,通过BCEL(字节码工程库)生成字节码文件。

    BCEL字节码工程库是一个工具包,用于对Java类文件的静态分析,动态创建或修改。开发人员能够使用BCEL 库在一个较高的抽象层次上实现所需的功能,而不用具体处理Java字节码文件的内部细节。BCEL完全用Java语言写成,并遵守LGPL条款。

由于BCEL库是针对Java的class文件格式和虚拟机指令集所设计的,直接应用BCEL库进行Java字节码文件的生成比较困难,需要了解较多的Java虚拟机方面的知识。本文提出的Java字节码编程语言的文法与BCEL库的字节码生成接口相对应,易于应用BCEL库进行编译,完成字节码生成。Java字节码编程语言成为一座连接Java源程序和字节码文件的桥梁,先将Java源程序编译为中间代码,再使用BCEL库将中间代码编译为Java字节码,生成class文件。

    Java字节码生成系统可分为词法分析、语法分析和字节码生成三个阶段,其用例图如下:

                     图1 Java字节码生成系统的用例图

    系统的数据流图可表示为:

     Java字节码生成系统中,字节码编程语言与BCEL库中字节码生成接口具有对应关系,以方法调用为例,如下表:

表4 java字节码编程语言与BCEL库生成接口对应关系

Java字节码编程语言方法调用文法

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对应invokevirtual , invokeinterface       , invokespecial , invokestatic

public static

ReturnInstruction createReturn(Type type)

//type类型对应关系:

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字节码生成示例 

    下面通过生成阶乘Java程序字节码的介绍,说明Java字节码生成系统功能。左边是求阶乘的Java源程序,右边是相应的字节码编程语言代码。

    阶乘Java源程序 其中calculateFactorial方法的字节码编程语言代码  

                           表5 阶乘程序和相应字节码编程语言代码

阶乘Java源程序 

其中calculateFactorial方法的字节码编程语言代码 

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; 

    字节码编程语言代码编译为BCEL库调用,以阶乘为例,以阶乘为例,分别讨论:

  • 类和方法声明: 

                                    表6 类和方法声明转换

字节码编程语言代码 

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 ); 

 

  • 方法调用: 

                                   表7 方法调用转换

字节码编程语言代码 

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 ) ); 

 

结束语 

使用Java字节码编程语言来完成字节码的生成,屏蔽了底层生成字节码的具体方法,通过生成相应虚拟机命令的扩展形式,降低了字节码生成的难度。

Java字节码编程语言的应用广泛,可用于Java代码优化,如对Java源程序进行部分求值优化后,可对生成的滞留程序和例化程序编译为中间语言的形式,在利用BCEL库生成字节码,完成进一步的字节码优化。还可以对Java字节码编程语言进行优化,去掉冗余的控制转移和方法调用,进而生成更紧凑的Java字节码。

参考文献 

[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 虚拟机规范》.北京大学出版社,1997


本站内容除特别声明的原创文章之外,转载内容只为传递更多信息,并不代表本网站赞同其观点。转载的所有的文章、图片、音/视频文件等资料的版权归版权所有权人所有。本站采用的非本站原创文章及图片等内容无法一一联系确认版权者。如涉及作品内容、版权和其它问题,请及时通过电子邮件或电话通知我们,以便迅速采取适当措施,避免给双方造成不必要的经济损失。联系电话:010-82306118;邮箱:aet@chinaaet.com。