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