一种动静态结合的Java程序异常处理优化方法

文档序号:6355004阅读:310来源:国知局
专利名称:一种动静态结合的Java程序异常处理优化方法
技术领域
本发明属于Java编译运行环境设计技术领域,具体涉及Java静态编译器和动态 虚拟机中的异常处理优化方法。
背景技术
异常处理机制是现代编程语言中普遍采用的一种提高程序可靠性的方法。作为 目前应用最广泛的面向对象编程语言,Java也将异常处理机制视为语言规范的一个重要方 面。如何正确地实现Java的异常处理机制是实现任何Java编译运行环境的关键部分。目前Java编译运行环境主要采用静态和动态两种编译优化方式。静态优化方式 是将Java源程序或字节码(byte code)直接编译成可执行代码;动态编译优化方式,则先 将Java源程序翻译成平台无关的字节码,然后由Java虚拟机(Java Virtual Machine)对 字节码进行解释或优化编译执行。上述传统Java编译运行环境存在着各自的缺陷静态编译优化将程序编译成可 执行代码,它破坏了 Java的跨平台性,其优化的效果也不理想。而动态编译优化则会带来 高昂的运行时开销,给通过动态编译执行的程序带来了额外的负担。而糅合动、静优化技术 来优化Java程序的系统框架在静态端对源程序进行静态分析与优化并将静态分析的结果 传递给动态端,动态端结合静态分析的结果进行基于采样的动态优化,这样既保留Java的 跨平台性,又能减少运行时开销,保障程序性能。然而,现有的Java异常处理机制一般只适用于纯静态或纯动态的Java编译运行 环境。所以要完成以上工作还存在的一个问题是目前的技术中缺少一套既适用于静态优 化,又能在Java虚拟机中正常工作的Java异常处理机制。

发明内容
本发明的目的在于针对目前的技术中缺少一套既适用于静态优化,又能在Java 虚拟机中正常工作的Java异常处理机制的这一问题,提出一种Java动静态结合的异常处 理优化方法。本发明调研了不同的Java静态编译器和动态虚拟机中对异常处理机制设计的差 异,发现这些设计在处理原理上具有很大程度的相似,只是在具体的算法实现时有较大的 差异。该结果说明,建立统一优化方法框架的可能性和优越性。本发明采用的技术方案为为实现一个糅合动、静优化技术来完成Java程序编译 工作的框架,在这个框架上再完成适用的各种动、静态优化方法,从而达到提供一个最优的 异常处理机制的效果。本发明调研了动静结合的编译运行环境的特点异常信息的收集和异常处理是分 别在两个不同的环境的。一般来说,异常信息的收集这一过程发生在静态编译器端,而真正 执行异常处理的过程发生在动态虚拟机里面,即是动静结合的编译运行环境区别于传统的 纯静态或纯动态的编译运行环境的最关键之处。
针对调研中动静结合的编译运行环境的特点,本发明把动静结合的编译运行环境 分为两个阶段静态处理阶段和动态执行阶段。静态处理阶段主要是在静态编译器里分析 和收集程序的异常处理信息,如产生异常的语句,异常的类型及异常着陆点等信息;动态执 行阶段主要是利用静态分析得到的异常处理信息,在异常发生的时候根据异常的类型和异 常着陆点跳转到相应的异常处理代码段,执行异常处理的相关操作。本发明对基于动静结合的编译运行环境的Java异常处理方法,共分为5个阶段, 图1中是异常处理编译、执行设计的整体示意图,具体步骤如下
1、在静态处理阶段,分析识别Java程序中所有可能抛出异常的语句;
2、在静态处理阶段,利用静态编译器前端分析try-catch-finally的层次关系;
3、在静态处理阶段,确定可能抛出异常的语句的异常着陆点;
4、在静态处理阶段,将静态编译器收集到的异常处理信息转化为动态编译器需要的异 常处理信息;
5、在动态执行阶段,利用动态编译器提供的运行时支持函数来完成异常处理的跳转等 操作。前三个阶段只要是分析并收集程序的异常信息,这些异常处理信息主要用于静态 编译器对程序进行优化的过程。由于静态编译器里收集到的异常处理信息并不能直接在动 态虚拟机上使用,因此,该异常处理机制会在适当的时机将静态收集到的异常处理信息转 化为动态虚拟机需要的异常处理信息,这一过程对应于阶段四。最后,在Java程序运行过 程中,如果有异常产生,该机制会利用运行时环境提供的支持函数,再结合异常处理信息来 跳转到相应的异常处理的代码。本发明的有益效果是1)本发明提供了一个实现糅合动、静优化技术来完成Java 程序编译工作的统一优化框架,实现了 Java程序在动静结合的环境中编译和运行。2)本发 明使得一个Java程序可以同时运用动静态异常处理优化,提供了更多的优化机会。3 )本发 明使得更多不同的优化算法能在这一框架下方便的被实现,很大程度上方便了今后异常处 理优化的设计和实现。4)框架的实现不针对具体的某一平台,这样的设计增加了本框架的 平台可移植性。


图1所示为动静结合的Java异常处理机制的整体框架。图2所示为实施例Java异常代码片段。图3所示为实施例代码片段的补偿代码。图4所示为实施例对应的异常处理代码示意图。图5所示为实施例动态编译器的表示形式。图6所示为程序栈空间中方法栈的示意图。
具体实施例方式本发明设计并实现了上述的动静结合Java异常处理机制的整体框架,本节对该 框架的具体实施作一个详细的介绍。图1为动静结合的Java异常处理机制的整体框架,描 述了本发明框架中,Java程序编译和执行的流程。本发明分5个步骤前4个步骤属于静态分析的范畴,最后一个步骤是动态执行的范畴。下面将以实施例的形式对本发明每个步骤进行详细的介绍,展示本框架把Java 代码编译成可执行代码的全过程。(实施例Java异常代码片段见图2)。步骤一、分析识别可能抛出异常的语句
本步骤目的在于得到能够引发异常的语句,通常是下面三种语句中的一种(1) throw 语句;( 可能引发异常的函数调用语句;C3)在程序运行过程中可能违反Java语言的语 义规则的语句。以图2中的代码片段为例,第5行的除法操作就是一个能够引发异常的语 句,如果right这个变量的值为0,程序就会产生一个除零异常。静态编译器总会有一个将Java源程序转化为抽象语法树的过程。本发明的框架 在Java程序转化为相应的抽象语法树之后,对该抽象语法树进行操作,识别那些可能引发 不受检查异常的节点。下面我们给出处理的流程。首先,获得Java源程序转化后的抽象语法树后,遍历整个抽象语法树,查找可能 弓I发不受检查异常的语句,记录它的位置。接着,对记录下来的每一个节点查看其父节点是否是if语句。如果不是,则对其 进行标记。如果是,则检查判断条件是否包含当前节点发生异常的条件,如果没有,同样对 该节点做标记。然后对标记下来的每个节点,根据其类型判断其引发异常的条件,然后在抽象语 法树的适当位置插入相应的补偿代码。以图2中的代码为例,静态编译器会对本程序添加 判断,判断变量right的值是否为0,如不是则正常运行;如是则抛出异常。补偿后的代码 如图3,补偿代码中插入了第5、第6行的判断。经过上述的处理后,程序中可能引发异常的点就由throw语句的集合和会引发异 常的函数调用语句的集合组成,即补偿代码(图3)中的第6行throw语句。而函数调用语 句可以分为用户自定义函数调用语句和库函数调用语句。用户自定义函数抛出异常的本质 还是由函数体内的throw语句和函数调用语句抛出的,因此被调用的用户自定义函数抛出 的异常又可以归结为函数体内的throw语句和函数调用语句抛出的。步骤二、分析try-catch-finally的层次关系
try-catch-finally的层次关系也是处理异常的重要信息,收集这部分的信息必不可 少。该步骤和步骤一不存在因果关系,可以交换顺序,在本发明实现中为了方便将本步骤放 在步骤一之后。本步骤的难点在于try-catch-finally块是可以嵌套的,在try块和catch块甚 至是finally块中都可以包含另外的try-catch-finally块,实施例代码(图2)就是典型的 情况。正确地判断try-catch-finally块的嵌套关系是编译器正确实现异常处理机制的基 础。本发明设计的算法能正确地分析程序中try块的层次关系。该算法同样是在Java源 程序转化为相应的抽象语法树后进行的,故本步骤分析try块的层次关系同样是基于Java 源程序对应的抽象语法树的。本节着重分析的是try块的上一层try块的关系,为了描述 的方便称为parent_try关系,下同。下面是算法的描述当遇到一个try块时,首先将当前的抽象语法树的遍历结果 的状态记录下来,然后将当前的try块的信息记录到一个vector上。接着,判断刚才记下 来的抽象语法树的状态,如果在这次try之前没有遇到过try块或catch块或finally块,则将当前try块的parent_try记为空。如果上一层是try块,则上一层的try块则是当前 try块的parent_try ;如果是catch ±夬或finally ±夬,那么当前的try块的parent_try则 是该catch块或finally块对应的try块。用该算法可以很方便地得出图2中第1行的try的parentjry是空,而第2行的 try的parent_try是第1行的try,这样就得到了第2行的try是一个nested try的信息。上述算法的伪代码如下
算法分析try块的parent_try关系
输入一个由下列部分组成的try块层次关系的框架
(1) Java源代码对应的抽象语法树AST。(2) 一个用于记录try块信息的集合V。(3) 一个用于记录当前遍历到的try块的状态的栈S。输出包含所有try块的parent_try信息的状态的集合。/*V和S的初始状态都为空。*/ Begin
(1)从抽象语法树AST的根节点开始遍历,
(2)if当前节点η代表一个try块
(3)currentTry := η;
(4)enclosingTry :=栈S的栈顶元素对应的try块;
(5)enclosingType :=栈S的栈顶元素的类型;
(6)add currentTry into V;
(7)ifenclosingTry 为空
(8)currentTry->parent_try 为空
(9)else
(10)ifenclosingType == tryType
(11)currentTry->parent_try := enclosingTry;
(12)else ifenclosingType == (catchType || finallyType)
(13)currentTry->parent_try := enclosingTry->parent_try;
(14)end if
(15)end if
(16)push S (Pair(currentTry, tryType));
(17)forcurrentTry 中的每一条语句 smtdo
(18)ifsmt可能引发异常
(19)record_landpad(smt) //确定异常着陆点
(20)end if
(21)end for
(22)分析currentTry内部try块的层次关系
(23)pop S;
(24)为 currentTry 生成一个标签 after_EH_label
(25)if currentTry 后面有 finally 块
权利要求
1.一种Java动静态结合的异常处理优化方法,其特征在于把动静结合的编译运行环 境分为两个阶段静态处理阶段和动态执行阶段,具体步骤如下(1)在静态处理阶段,分析识别Java程序中所有可能抛出异常的语句;(2)在静态处理阶段,利用静态编译器前端分析try-catch-finally的层次关系;(3)在静态处理阶段,确定可能抛出异常的语句的异常着陆点;(4)在静态处理阶段,将静态编译器收集到的异常处理信息转化为动态编译器需要的 异常处理信息;(5)在动态执行阶段,利用动态编译器提供的运行时支持函数来完成异常处理的操作。
2.根据权利要求1所述的Java动静态结合的异常处理优化方法,其特征在于所述分析 识别Java程序中可能抛出异常的语句的步骤为首先,获得Java源程序转化的抽象语法树后,遍历整个抽象语法树,查找可能引发不 受检查异常的语句,记录它的位置;接着,对记录下来的每一个节点查看其父节点是否是if语句;如果不是,则对其进行 标记,如果是,则检查判断条件是否包含当前节点发生异常的条件,如果没有,同样对该节 点做标记;然后,对标记下来的每个节点,根据其类型判断其引发异常的条件,然后在抽象语法树 的适当位置插入相应的补偿代码。
3.根据权利要求1或2所述的Java动静态结合的异常处理优化方法,其特征在于所述 分析try-catch-finally的层次关系的具体步骤为当遇到一个try块时,首先将当前的抽象语法树的遍历结果的状态记录下来,然后将 当前的try块的信息记录到一个vector上;接着,判断刚才记下来的抽象语法树的状态,如 果在这次try之前没有遇到过try块或catch块或finally块,则将当前try块的parent_ try记为空;如果上一层是try块,则上一层的try块则是当前try块的parentjry ;如果 是catch块或finally块,那么当前的try块的parent_try则是该catch块或finally块 对应的try块。
4.根据权利要求3所述的Java动静态结合的异常处理优化方法,其特征在于所述确定 可能产生异常的语句的异常着陆点的步骤完成两个方面工作(1)确定程序的异常着陆点由步骤一和步骤二中收集到的可能抛出异常的语句集合和当前遍历到的try块的状 态的栈的信息作为输入参数,得到集合中所有可能抛出异常的语句的异常着陆点;其方法 是把需要处理的可能抛出异常的语句按照所处区域位置的不同分为四类,并且分别进行处 理1)需要处理的可能抛出异常的语句处于try块中,这时的异常着陆点是相继的catch 块、finally块,或者是parent_try相继的catch块、finally块,所需要做的只是把相应 try块的EH_bloCk_label作为异常着陆点;这里所述的try块的EH_bloCk_label是指该 try块对应的异常处理代码段的开始,该label下记录着进行对异常类型的分析和跳转;2)需要处理的可能抛出异常的语句处于catch块中,这种情况的异常着陆点有两种 可能一种是如果本catch块存在相继的finally块,着陆点就是相继的finally块 ’另 一种情况是不存在相继的finally块,那么就判断是否存在parentjry,并把着陆点定为parent_try 相继的 EH_block_label ;3)需要处理的可能抛出异常的语句处于final块中,这种情况下,直接判断是否存在 parent_try,并把着陆点定为 parent_try 相继的 EH_block_label ;4)需要处理的可能抛出异常的语句处于普通区域,即不属于上述三种情况,或上述三 种情况中没有找到异常着陆点,这种情况下,一旦异常发生,没有处理代码存在;(2)构造异常代码在分析出异常着陆点之后,编译器就构造异常处理代码,其算法以try-catch-finally 的粒度来完成;其步骤为第一,生成一个EH_bloCk_label标签,并在生成好的try块中的代码之后加入至EH_ block_label标签的跳转;第二,在EH_bloCk_label标签之后生成异常类型的判断以及跳 转的代码,即判断何种类型的异常由哪个catch来处理;如果有finally块存在,则在判断 完之后加入finally代码;第三,逐个生成catch_block_label标签和相应的catch块代 码,并在每个catch块代码的最后加入到下一个CatCh_bl0Ck_label标签的跳转;第四,生 成finally_block_label标签和相应的finally块代码。
5.根据权利要求4所述的Java动静态结合的异常处理优化方法,其特征在于所述异常 处理信息的转化的过程作为静态编译器的顶向动态编译器的顶的转化的过程处理。
6.根据权利要求1所述的Java动静态结合的异常处理优化方法,其特征在于所述利用 运行时环境的支持函数完成异常处理,主要是在即时编译器里面的异常处理的实现方式, 包括栈展开、栈回溯;其中,在进行栈展开操作时,运行时环境的支持函数根据异常产生函数的方法栈得到 当前函数的异常处理信息,如果该函数的异常处理代码可以处理该异常,则将程序跳转到 异常处理代码开始处执行;如果当前函数的异常处理代码不能处理该异常,运行时环境的 支持函数根据当前方法的方法栈的信息得到上一层调用者的方法栈的基址指针retbp,同 时还得到上一层方法的返回地址retpc,这样根据上一层调用函数的方法栈信息得到上一 层函数的异常处理信息;如果该函数的异常处理代码可以处理该异常,程序同样跳转到该 异常处理代码的开始,否则,再通过上述方法得到上层调用者的异常处理信息,直到找到可 以处理该异常的异常处理代码为止;如果所有函数的异常处理代码都不能处理该异常,则 程序终止运行。
全文摘要
本发明属于Java编译运行环境设计技术领域,具体一种Java动静态结合的的异常处理优化方法。本发明把动静结合的编译运行环境分为两个阶段静态处理阶段和动态执行阶段。静态处理阶段主要是在静态编译器里分析和收集程序的异常处理信息,如产生异常的语句,异常的类型及异常着陆点等信息;动态执行阶段主要是利用静态分析得到的异常处理信息,在异常发生的时候根据异常的类型和异常着陆点跳转到相应的异常处理代码段,执行异常处理的相关操作。本发明糅合动、静优化技术来完成Java程序编译工作,从而达到提供一个最优的异常处理机制的效果。
文档编号G06F11/00GK102117228SQ20111004700
公开日2011年7月6日 申请日期2011年2月28日 优先权日2011年2月28日
发明者杨珉, 王迪, 臧斌宇, 许铝才 申请人:复旦大学
网友询问留言 已有0条留言
  • 还没有人留言评论。精彩留言会获得点赞!
1