CN109032572A - 一种基于字节码的java程序方法内联的方法 - Google Patents
一种基于字节码的java程序方法内联的方法 Download PDFInfo
- Publication number
- CN109032572A CN109032572A CN201710428549.4A CN201710428549A CN109032572A CN 109032572 A CN109032572 A CN 109032572A CN 201710428549 A CN201710428549 A CN 201710428549A CN 109032572 A CN109032572 A CN 109032572A
- Authority
- CN
- China
- Prior art keywords
- node
- instruction
- inline
- callee
- attribute
- Prior art date
- Legal status (The legal status is an assumption and is not a legal conclusion. Google has not performed a legal analysis and makes no representation as to the accuracy of the status listed.)
- Granted
Links
Classifications
-
- G—PHYSICS
- G06—COMPUTING; CALCULATING OR COUNTING
- G06F—ELECTRIC DIGITAL DATA PROCESSING
- G06F8/00—Arrangements for software engineering
- G06F8/70—Software maintenance or management
- G06F8/73—Program documentation
Landscapes
- Engineering & Computer Science (AREA)
- Software Systems (AREA)
- General Engineering & Computer Science (AREA)
- Theoretical Computer Science (AREA)
- Library & Information Science (AREA)
- Physics & Mathematics (AREA)
- General Physics & Mathematics (AREA)
- Devices For Executing Special Programs (AREA)
Abstract
本申请公开了一种基于字节码的JAVA程序方法内联的方法,包括:将类文件解析成类节点,并将该类的属性和方法分别依次生成属性节点、方法节点,然后添加到预先定义的节点仓库中;读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则进入下一步;对判断结果为可以执行内联的方法执行方法内联操作。本申请通过ASM框架将类文件解析成类节点,再将类的方法和属性分别生成方法节点和属性节点;通过遍历所述节点仓库中的方法节点,对可以执行内联操作的方法执行内联操作,从而实现方法的合并。本申请能够在不减少应用程序功能的情况下减少方法数量,显著减少了开发者的工作量,提高了工作效率,降低开发成本。
Description
技术领域
本申请涉及计算机开发领域,具体涉及一种基于字节码的JAVA程序方法内联的方法。本申请同时提供一种基于字节码的JAVA程序方法内联的装置,以及一种电子设备。
背景技术
dex文件是Android系统的可执行文件,包含应用程序的全部操作指令以及资源文件。在安卓应用构建过程中存在一个限制,即一个dex文件最多拥有65536个方法,当方法数超过65536时,会导致生成dex文件失败。
由于当前业务的发展越来越快,客户端的体量越来越大,单一dex模式下65536个方法早已不能满足业务量的需求。这大大限制了Android开发的发展,成为Android应用程序满足用户需求的一大障碍,Android程序开发者在面对此种问题时,必须考虑删减一部分功能,或者其他更加复杂的办法解决这个问题,大大增加了开发难度和开发成本。
发明内容
本申请实施例提供一种基于字节码的JAVA程序方法内联的方法,以解决单一dex模式下方法数超过限制导致dex文件构建失败的问题。
本申请提供一种基于字节码的JAVA程序方法内联的方法,包括:
将类文件解析成类节点,并将该类的属性和方法分别依次生成属性节点、方法节点,然后添加到预先定义的节点仓库中;
读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则进入下一步;
对判断结果为可以执行内联的方法执行方法内联操作。
可选的,在所述读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性的步骤之前,进行以下操作:
从节点仓库获取所有的方法节点并依次处理,添加每个方法节点对其他方法节点以及属性节点的依赖关系;
进行所述执行方法内联操作时,根据所述依赖关系确定内联的插入点。
可选的,,所述从节点仓库获取所有的方法节点并依次处理,添加每个方法节点对其他方法节点以及属性节点的依赖关系,具体过程如下:
对每一个方法的指令序列进行遍历,通过指令的操作码判断当前指令的类型,
若指令是方法调用指令,则:
解析出指令访问的方法所属类型的名称,方法名称,方法参数列表和返回值,从而从节点仓库查找对应的方法节点,添加方法-方法之间的依赖关系;
若指令是属性访问指令,则
解析出指令访问的属性所属类型的名称,属性名称,从而从节点仓库查找对应的属性节点,添加方法-属性之间的依赖关系。
可选的,所述将类文件解析成类节点是通过ASM框架实现的。
可选的,所述判断是否存在内联的可行性,在符合如下各个判断项目的情况下,则判断结果为是:
该方法不是构造方法或者静态初始化方法;
该方法不是同步方法;
该方法不是native方法;
该方法不是枚举类型;
该方法是私有方法,或静态方法,或该方法是
final方法且不是继承自父类方法或接口;
该方法在内联后不需要提升libClass的方法/属性的访问权限;
该方法的方法体异常表为空;
该方法不存在自身调用;
该方法不存在条件跳转指令;
该方法不存在下述情况:在其内部通过invoke-special指令访问父类方法,并且其调用方不仅限于当前方法所述类型;
该方法不属于下述情况:该方法是static方法,同时其在内联后可能导致运行时其所属类型未执行初始化。
可选的,所述判断项目还包括:该方法不存在如下情况:其指令数量超过阀值,同时调用点不止一处。
可选的,所述阀值可以由用户配置。
可选的,所述内联操作包括:
将所述可以执行内联的方法作为被调用方,称为callee,调用方称为caller;通过依赖关系找出callee的依赖方caller,分析caller的指令序列,找到所述caller调用callee的指令,该调用指令所在程序位置为内联的插入点;
删除所述调用callee的调用指令;
利用构造store指令栈的方法,将所述callee指令序列插入到插入点并进行完善操作,使插入后的所述caller在不需要所述callee时能够正常运行;
删除所述callee,去除caller-callee依赖关系并将该方法节点从节点仓库中删除。
可选的,在删除所述调用callee的调用指令后、构造store指令栈之前,判断所述callee是否为空方法,
若是,则逆序处理所述callee的参数列表,如果参数是float或double类型,则插入pop2指令,否则插入pop指令;如果callee同时还是成员方法,则额外插入一条pop指令将调用方法的对象从栈中弹出;
跳过所述利用构造store指令栈的方法,将所述callee指令序列插入到插入点并进行完善操作,使插入后的所述caller在不需要所述callee时能够正常运行的步骤,直接执行所述删除callee方法,去除caller-callee依赖关系并将该方法节点从节点仓库中删除;
若否,则进入所述利用构造store指令栈的方法,将所述callee指令序列插入到插入点并进行完善操作,使插入后的所述caller在不需要所述callee时能够正常运行的步骤。
可选的,所述利用构造store指令栈的方法,将所述callee指令序列插入到插入点并进行完善操作,使插入后的所述caller在不需要所述callee时能够正常运行,包括以下步骤:
构造store指令栈;
按顺序处理callee的参数列表,根据每个参数的数据类型构造相应的store指令,并为中每条store指令设定相应的寄存器的值,添加到store指令栈中;
将store指令栈中的指令依次取出,插入到插入点;
遍历callee指令序列,根据指令的不同做出相应完善操作。
可选的,所述根据每个参数的数据类型构造相应的store指令的具体方法为:
如果参数类型是float类型,则构造的store指令为fstore指令;
如果参数类型是long类型,则构造的store指令为lstore指令;
如果参数类型是double类型,则构造的store指令为dstore指令;
如果参数类型是boolean、byte、char、short、int类型,则构造的store指令为istorte指令;
如果参数类型是上述类型之外的其他类型,则构造的store指令为astore指令。
可选的,所述为每条指令分配相应的寄存器的值的具体方法为:
从方法节点获取caller最大本地变量数量,记为offset,并根据callee是否为静态方法,初始化used的值,即:如果所述callee是静态方法,used的值初始化为0,否则,used的值初始化为1;
每条store指令的寄存器数值为offset+used,其中,used的值按照store指令的顺序自增,如果所述store指令是lstore/dstore指令,则used的值自增量为2,如果所述store指令是其他指令,则used的值自增量为1。
可选的,在所述将store指令栈中的指令依次取出,插入到插入点之后,所述遍历callee指令序列,根据指令的不同做出相应完善操作之前,判断caller的类型,如果caller是成员方法,则构造astore指令,寄存器值为offset,插入到插入点。
可选的,所述遍历callee指令序列,根据指令的不同做出相应完善操作,具体包括:
如果指令是load/store指令,将寄存器数值自增offset;
如果指令是inc指令,将寄存器数值自增offset;
如果指令是属性访问指令,解析出指令访问的属性所属类型的名称,属性名称,从而从节点仓库查找对应的属性节点,根据属性节点所属类型和caller所属类型的亲近关系,计算是否需要提升属性节点及属性节点所属类的访问权限,如果需要,则进行提升;同时增加caller-属性依赖关系;
如果指令是方法调用指令,解析出指令访问的方法所属类型的名称,方法名称,方法参数列表和返回值,从而从节点仓库查找对应的方法节点,根据方法节点所属类型和caller所属类型的亲近关系,计算是否需要提升方法节点及方法节点所属类的访问权限,如果需要,则进行提升;同时增加caller-方法依赖关系。
可选的,对下述步骤采用对节点仓库的方法节点遍历的方式执行:
读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则进入执行方法内联操作;
其中,所述判断是否存在内联的可行性的判断结果为否,则跳过所述执行方法内联操作的步骤,直接进入对下一个方法节点操作。
可选的,所述判断是否存在内联的可行性的判断结果为否,以及
判断是否存在内联的可行性的判断结果为是,并进入执行方法内联操作的步骤结束后;进行下述步骤:
判断节点仓库是否存在方法节点,若是,则进入下一个方法节点继续遍历;若否,则结束本次遍历。
本申请还提供一种基于字节码的JAVA程序方法内联的装置,其特征在于,包括:
解析单元,用于将类文件解析成类节点,同时将该类的属性和方法分别依次生成属性节点、方法节点,并添加到预先定义的节点仓库中;
判断单元,用于读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则将所述方法节点送入执行内联单元;
执行内联单元,用于对判断结果为可以执行内联的方法执行方法内联操作。
本申请还提供一种电子设备,包括:
处理器;以及
存储器,用于存储一种基于字节码的JAVA程序方法内联的程序,该设备通电并通过所述处理器运行所述基于字节码的JAVA程序方法内联的程序后,执行下述步骤:
将类文件解析成类节点,并将该类的属性和方法分别依次生成属性节点、方法节点,然后添加到预先定义的节点仓库中;
读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则进入下一步;
对判断结果为可以执行内联的方法执行方法内联操作。与现有技术相比,本申请具有以下优点:
本申请通过ASM框架将类文件解析成类节点,再将类的方法和属性分别生成方法节点和属性节点;通过遍历所述节点仓库中的方法节点,对可以执行内联操作的方法执行内联操作,从而实现方法的合并。本申请能够在不减少应用程序功能的情况下减少方法数量,从而将方法总数降至65536限制之下,大大减少了开发者的工作量,提高了工作效率,降低开发成本。
附图说明
图1是本申请的一种基于字节码的JAVA程序方法内联的方法实施例的流程图。
图2是本申请的对可执行内联操作的方法执行内联操作的流程图。
图3是本申请的基于字节码的JAVA程序方法内联的方法的实施例的优选方案的流程图。
图4是本申请的一种基于字节码的JAVA程序方法内联的装置实施例的示意图。
图5是本申请的一种基于字节码的JAVA程序方法内联的电子设备实施例的示意图。
具体实施方式
在下面的描述中阐述了很多具体细节以便于充分理解本申请。但是本申请能够以很多不同于在此描述的其它方式来实施,本领域技术人员可以在不违背本申请内涵的情况下做类似推广,因此本申请不受下面公开的具体实施的限制。
请参考图1,其为本申请的一种基于字节码的JAVA程序方法内联的方法实施例的流程图。
S101:将类文件解析成类节点,并将该类的属性和方法分别依次生成属性节点、方法节点,然后添加到预先定义的节点仓库中。
本步骤为后续操作提供准备工作,将类文件解析成节点文件并添加到预先定义的节点仓库中。所述类文件包括JAVA类文件。JAVA类文件是JAVA编译器编译源文件时生成的字节码文件。类文件包含描述类的每个变量和方法的信息,还可包含用来表示JAVA对象的每个方法、静态数据和说明的字节码。所述类节点是每个类被解析成的目标格式,以节点树的形式反映方法与方法、方法与属性之间的关系,本实施例使用ASM框架将类文件解析成类节点。ASM是一个JAVA字节码分析、创建和修改的开源应用框架,它可以动态生成二进制格式的stub类或其他代理类,或者在类被JAVA虚拟机装入内存之前,动态修改类。在ASM中提供了诸多的API用于对类的内容进行字节码操作的方法,本实施例采用Tree API解析类文件,所述Tree API是基于对象的方式来处理字节码的一组API,Tree API的最核心的一个类就是ClassNode,它就代表了一个JAVA Class文件,它里面的属性对应到了一个Class文件的各个部分。当用Tree API把类文件解析成类节点后,ClassNode会依方法和属性分别生成方法列表和属性列表,所述方法列表,是指该类所拥有的所有方法的列表,所述属性列表是指该类所拥有的所有属性的列表。获取当前ClassNode的方法列表和属性列表,方法列表和属性列表中储存着方法节点和属性节点。
所属节点仓库是为储存节点而定义的,由于在判断和执行方法内联时需要遍历每个节点,因此为这些节点设定专门的节点仓库,便于取用。
生成类节点、方法节点和属性节点的方法有很多种,也可以使用其他方法实现本步骤的目的。
S102:读取所述节点仓库的方法节点,针对每一个被读取的方法节点,判断是否存在内联的可行性;若是,则进入下一步。
本步骤的目的是判断每一个方法节点是否可以执行内联,为下一步执行内联操作提供操作资源。
方法节点包括以下几个方面的内容:
方法名称,参数列表,返回值,访问修饰符,方法体指令序列;
方法所属的类;
所有的依赖节点和被依赖节点。
根据每一个方法节点内容,对其能否执行内联的判断方法如下:
通过方法名称判断方法是否是构造方法或者静态初始化方法(构造方法名称为“init”,静态初始化方法名称为“clinit”)。如果该方法是构造方法,执行内联会导致运行时异常,则该方法不能执行内联,将该方法跳过;
通过方法节点的访问权限描述符判断该方法是否是同步方法,如果该方法是同步方法,执行内联会导致逻辑上的运行时并发问题,甚至可能导致运行时异常,则该方法不能执行内联,将该方法跳过;
通过方法节点的访问权限描述符判断该方法是否是native方法,如果该方法是native方法,方法实现是在C/C++层面实现,则该方法不能执行内联,将该方法跳过;
通过方法节点获取方法所属的类节点,通过类节点的访问权限描述符判断该方法是否是枚举类型,如果该类型是枚举类型,方法内联可能导致运行时构造EnumMap类型出现异常,则该方法不能执行内联,将该方法跳过;
如果该方法不满足以下任何一个条件:
1)该方法是私有方法;2)该方法是静态方法;3)该方法是final方法但该方法不是继承自父类或者接口
则该方法在运行时存在多态调用的可能性,该方法不能执行内联,将该方法跳过;
由于libClass是由运行时系统提供,不具备可修改性。如果该方法在内联后,需要提升libClass的方法/属性的访问权限,则该方法不能执行内联,将该方法跳过;
通过方法节点获取该方法的异常表(try-catch),如果该方法体异常表不为空,则方法内联后会导致异常表错乱,则该方法不能执行内联,将该方法跳过;
如果该方法存在自身调用,执行方法内联会导致死循环内联,则该方法不能执行内联,将该方法跳过;
依次分析方法的每一条指令,如果存在条件跳转指令(指令操作码在153至166之间或指令操作码是170、171、198、199中的一种),则执行方法内联会导致指令跳转错乱,该方法不能执行内联,将该方法跳过;
如果该方法的指令数量超过阀值(阀值可以由用户配置),同时调用点不止一处,该方法内联会导致class文件变大,则该方法不能执行内联,将该方法跳过;
如果该方法内通过invoke-special指令访问父类方法,并且该方法的调用方不仅限于当前方法所属类型,则方法内联后会导致运行时非法访问错误,该方法不能执行内联,将该方法跳过;
如果该方法是static方法,同时该方法内联后可能导致运行时该方法所属类型未执行初始化的,则该方法不能执行内联,将该方法跳过;
如果方法在以上条件中的任意一个判断中被跳过,则说明该方法不能执行内联。如果以上条件都通过,即方法没有在判断过程中被跳过,则该方法被视为可以执行内联。
在判断方法是否可以执行内联之前需要添加方法与方法、方法与属性之间的依赖关系。所述依赖关系是指在代码层面上的相互依赖的关系,具体分为方法与方法之间的依赖关系和方法与属性之间的依赖关系。举一个例子来说,如果A方法调用B方法,即是A方法依赖B方法,B方法被A方法所依赖;同理,如果A方法访问了B属性,即是A方法依赖B属性,B属性被A方法所依赖。
由于本申请在判定一个方法可以执行内联后,就需要获取所有依赖这个方法的方法,换句话说,就是要获取所有调用过这个方法的方法,从而在这些方的方法体内相应指令位置实现方法内联。节点之间的依赖关系就可以提供上述信息。可以这样理解,依赖关系记录着方法与方法之间、方法与属性之间的调用关系。
添加依赖关系的具体方法如下:
对每一个方法的指令序列进行遍历,通过指令的操作码判断当前指令的类型,若指令是方法调用指令,则解析出指令访问的方法所属类型的名称、方法名称、方法参数列表和返回值,从而从节点仓库查找对应的方法节点,添加方法-方法之间的依赖关系;若指令是属性访问指令,则解析出指令访问的属性所属类型的名称、属性名称、从而从节点仓库查找对应的属性节点,添加方法-属性之间的依赖关系。
S103:对判断结果为可以执行内联的方法执行方法内联操作。
本步骤的目的是将能够执行内联操作的方法执行内联并在对方法执行内联后进行相关的完善,使程序能够正常运行。
请参考图2,其为本申请的对可执行内联操作的方法执行内联操作的一具体实例的流程图,具体执行内联的步骤为:
S103-1:将所述可以执行内联的方法作为被调用方,称为callee,调用方称为caller;通过依赖关系找出callee的依赖方caller,分析caller的指令序列,找到所述caller调用callee的指令,该调用指令所在程序位置为内联的插入点。
本步骤的主要任务是确定内联插入点。
S103-2:删除所述调用callee的调用指令。
本步骤使得caller不再调用callee,为在此之后将callee的指令复制到所述插入点中并作完善使之顺利运行的工作提供基础操作。
S103-3:利用构造store指令栈的方法,将所述callee指令序列插入到插入点并进行完善操作,使插入后的所述caller在不需要所述callee时能够正常运行。
本步骤的目的是将callee的功能迁移到caller中,使插入后的所述caller在不需要所述callee时能够正常实现callee的功能,所述callee指令序列是指callee被解析成方法节点后的每一条指令所形成的有顺序的序列,将所述callee指令序列插入到插入点有多种方法,本实施例采用构造store指令栈的方法进行callee指令序列的迁移。具体步骤为:
构造store指令栈。所述store指令,是指“串存储指令”,意思是将中央处理器(CPU)中的累加器中的数据加载到内存中指定位置。所述store指令栈,是指由store指令和每条store指令所指定的加载到内存中的位置构成的栈。所述栈是一种运算受限的线性表。其限制是仅允许在表的一端进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;从一个栈删除元素又称作出栈或退栈,它是把栈顶元素删除掉,使其相邻的元素成为新的栈顶元素。
按顺序处理callee的参数列表,根据每个参数的数据类型构造相应的store指令,并为每条store指令设定相应的寄存器的值,添加到store指令栈中。根据每个参数的数据类型构造相应的store指令的具体方法为:
如果参数类型是float类型,则构造的store指令为fstore指令;
如果参数类型是long类型,则构造的store指令为lstore指令;
如果参数类型是double类型,则构造的store指令为dstore指令;
如果参数类型是boolean、byte、char、short、int类型,则构造的store指令为istorte指令;
如果参数类型是上述类型之外的其他类型,则构造的store指令为astore指令。
为每条指令分配相应的寄存器的值的具体方法为:
从方法节点获取caller最大本地变量数量,记为offset,并根据callee是否为静态方法,初始化used的值,即:如果所述callee是静态方法,used的值初始化为0,否则,used的值初始化为1;
每条store指令的寄存器数值为offset+used,其中,used的值按照store指令的顺序自增,如果所述store指令是lstore/dstore指令,则used的值自增量为2,如果所述store指令是其他指令,则used的值自增量为1。
将store指令栈中的指令依次取出,插入到插入点。本步骤将构造好的完整的store指令栈中的指令插入到插入点。
遍历callee指令序列,根据指令的不同做出相应完善操作。在本步骤之前,需要对caller的类型加以判断,如果caller是成员方法,则需要构造astore指令,寄存器的值设定为offset,插入到插入点,这是因为,成员方法需要一条指令来存储本地局部变量。本步骤所述遍历callee指令序列,根据指令的不同做出相应完善操作,具体包括:如果指令是load/store指令,将寄存器数值自增offset;如果指令是inc指令,将寄存器数值自增offset;如果指令是属性访问指令,解析出指令访问的属性所属类型的名称、属性名称,从而从节点仓库查找对应的属性节点,根据属性节点所属类型和caller所属类型的亲近关系,计算是否需要提升属性节点及属性节点所属类的访问权限,如果需要,则进行提升;同时增加caller-属性依赖关系;如果指令是方法调用指令,解析出指令访问的方法所属类型的名称、方法名称、方法参数列表和返回值,从而从节点仓库查找对应的方法节点,根据方法节点所属类型和caller所属类型的亲近关系,计算是否需要提升方法节点及方法节点所属类的访问权限,如果需要,则进行提升;同时增加caller-方法依赖关系。
需要特别注意的是,在构造store指令栈之前,需要判断callee是否是空方法,如果callee是空方法,则所述callee中的所有指令都没有实质的操作内容,因此没有意义执行,在这种情况下,这些没有意义的指令应当直接被跳过,因此,如果callee是空方法,则逆序处理所述callee的参数列表,如果参数是float或double类型,则插入pop2指令,否则插入pop指令;如果callee同时还是成员方法,则额外插入一条pop指令将调用方法的对象从栈中弹出;这些工作完成后,直接跳到下一步,不必构造store指令栈。
S103-4:删除所述callee,去除caller-callee依赖关系并将该方法节点从节点仓库中删除。
本步骤是内联操作的最后一步,由于前述步骤已经完全在不需要callee的情况下实现callee的所有功能,因此,callee能够被彻底删除,同时,在内联过程中使用的依赖关系也不需要继续使用,因此,依赖关系也一并删除。对于已经执行内联操作的方法节点在此步骤中删除。
请参考图3,其为本申请的基于字节码的JAVA程序方法内联的方法的实施例的优选方案的流程图,本优选方案的具体实施步骤为:
S201:将类文件解析成类节点,同时将该类的属性和方法分别依次生成属性节点、方法节点,并添加到预先定义的节点仓库中。
本步骤与第一实施例中S101相同,在此不再赘述。
S202:读取所述节点仓库中未被读取过的方法节点,针对被读取的方法节点,是否存在内联的可行性?
本步骤内联可行性的判断方法与第一实施例中步骤S102相同。经过判断,若被读取的方法节点存在内联可行性,则执行下一步;否则,进入步骤S204。
S203:对判断结果为可以执行内联的方法执行方法内联操作。
本步骤与第一实施例中S103相同,在此不再赘述。
S204:节点仓库中的方法列表是否遍历结束?
本步骤的目的是判断所述类文件生成的所有方法节点是否全部遍历,节点仓库里方法节点存储为一个列表,遍历完此列表便是完成方法节点的遍历,否则继续进入步骤S202。
S205:内联结束。
相对应的,本申请提供一种基于字节码的JAVA程序方法内联的装置,请参考图4,其为本申请的一种基于字节码的JAVA程序方法内联的装置实施例的示意图。该装置包括:
解析单元301,用于将类文件解析成类节点,同时将该类的属性和方法分别依次生成属性节点、方法节点,并添加到预先定义的节点仓库中;
判断单元302,用于读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则将所述方法节点送入执行内联单元303;
执行内联单元303,用于对判断结果为可以执行内联的方法执行方法内联操作。
本申请还提供一种电子设备,请参考图5,其为本申请的一种基于字节码的JAVA程序方法内联的电子设备实施例的示意图。该电子设备包括:
处理器401;以及
存储器402,用于存储一种基于字节码的JAVA程序方法内联的程序,该设备通电并通过所述处理器运行所述基于字节码的JAVA程序方法内联的程序后,执行下述步骤:
将类文件解析成类节点,同时将该类的属性和方法分别依次生成属性节点、方法节点,并添加到预先定义的节点仓库中;
读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则进入下一步;
对判断结果为可以执行内联的方法执行方法内联操作。
本申请虽然以较佳实施例公开如上,但其并不是用来限定本申请,任何本领域技术人员在不脱离本申请的精神和范围内,都可以做出可能的变动和修改,因此本申请的保护范围应当以本申请权利要求所界定的范围为准。
在一个典型的配置中,计算设备包括一个或多个处理器(CPU)、输入/输出接口、网络接口和内存。
内存可能包括计算机可读介质中的非永久性存储器,随机存取存储器(RAM)和/或非易失性内存等形式,如只读存储器(ROM)或闪存(flash RAM)。内存是计算机可读介质的示例。
1、计算机可读介质包括永久性和非永久性、可移动和非可移动媒体可以由任何方法或技术来实现信息存储。信息可以是计算机可读指令、数据结构、程序的模块或其他数据。计算机的存储介质的例子包括,但不限于相变内存(PRAM)、静态随机存取存储器(SRAM)、动态随机存取存储器(DRAM)、其他类型的随机存取存储器(RAM)、只读存储器(ROM)、电可擦除可编程只读存储器(EEPROM)、快闪记忆体或其他内存技术、只读光盘只读存储器(CD-ROM)、数字多功能光盘(DVD)或其他光学存储、磁盒式磁带,磁带磁磁盘存储或其他磁性存储设备或任何其他非传输介质,可用于存储可以被计算设备访问的信息。按照本文中的界定,计算机可读介质不包括非暂存电脑可读媒体(transitory media),如调制的数据信号和载波。
2、本领域技术人员应明白,本申请的实施例可提供为方法、系统或计算机程序产品。因此,本申请可采用完全硬件实施例、完全软件实施例或结合软件和硬件方面的实施例的形式。而且,本申请可采用在一个或多个其中包含有计算机可用程序代码的计算机可用存储介质(包括但不限于磁盘存储器、CD-ROM、光学存储器等)上实施的计算机程序产品的形式。
Claims (18)
1.一种基于字节码的JAVA程序方法内联的方法,其特征在于,包括:
将类文件解析成类节点,并将该类的属性和方法分别依次生成属性节点、方法节点,然后添加到预先定义的节点仓库中;
读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则进入下一步;
对判断结果为可以执行内联的方法执行方法内联操作。
2.根据权利要求1所述的基于字节码的JAVA程序方法内联的方法,其特征在于,在所述读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性的步骤之前,进行以下操作:
从节点仓库获取所有的方法节点并依次处理,添加每个方法节点对其他方法节点以及属性节点的依赖关系;
进行所述执行方法内联操作时,根据所述依赖关系确定内联的插入点。
3.根据权利要求2所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述从节点仓库获取所有的方法节点并依次处理,添加每个方法节点对其他方法节点以及属性节点的依赖关系,具体过程如下:
对每一个方法的指令序列进行遍历,通过指令的操作码判断当前指令的类型,
若指令是方法调用指令,则:
解析出指令访问的方法所属类型的名称,方法名称,方法参数列表和返回值,从而从节点仓库查找对应的方法节点,添加方法-方法之间的依赖关系;
若指令是属性访问指令,则
解析出指令访问的属性所属类型的名称,属性名称,从而从节点仓库查找对应的属性节点,添加方法-属性之间的依赖关系。
4.根据权利要求1所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述将类文件解析成类节点是通过ASM框架实现的。
5.根据权利要求1所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述判断是否存在内联的可行性,在符合如下各个判断项目的情况下,则判断结果为是:
该方法不是构造方法或者静态初始化方法;
该方法不是同步方法;
该方法不是native方法;
该方法不是枚举类型;
该方法是私有方法,或静态方法,或该方法是
final方法且不是继承自父类方法或接口;
该方法在内联后不需要提升libClass的方法/属性的访问权限;
该方法的方法体异常表为空;
该方法不存在自身调用;
该方法不存在条件跳转指令;
该方法不存在下述情况:在其内部通过invoke-special指令访问父类方法,并且其调用方不仅限于当前方法所述类型;
该方法不属于下述情况:该方法是static方法,同时其在内联后可能导致运行时其所属类型未执行初始化。
6.根据权利要求5所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述判断项目还包括:该方法不存在如下情况:其指令数量超过阀值,同时调用点不止一处。
7.根据权利要求6所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述阀值可以由用户配置。
8.根据权利要求2所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述内联操作包括:
将所述可以执行内联的方法作为被调用方,称为callee,调用方称为caller;通过依赖关系找出callee的依赖方caller,分析caller的指令序列,找到所述caller调用callee的指令,该调用指令所在程序位置为内联的插入点;
删除所述调用callee的调用指令;
利用构造store指令栈的方法,将所述callee指令序列插入到插入点并进行完善操作,使插入后的所述caller在不需要所述callee时能够正常运行;
删除所述callee,去除caller-callee依赖关系并将该方法节点从节点仓库中删除。
9.根据权利要求8所述的基于字节码的JAVA程序方法内联的方法,其特征在于,在删除所述调用callee的调用指令后、构造store指令栈之前,判断所述callee是否为空方法,
若是,则逆序处理所述callee的参数列表,如果参数是float或double类型,则插入pop2指令,否则插入pop指令;如果callee同时还是成员方法,则额外插入一条pop指令将调用方法的对象从栈中弹出;
跳过所述利用构造store指令栈的方法,将所述callee指令序列插入到插入点并进行完善操作,使插入后的所述caller在不需要所述callee时能够正常运行的步骤,直接执行所述删除callee方法,去除caller-callee依赖关系并将该方法节点从节点仓库中删除;
若否,则进入所述利用构造store指令栈的方法,将所述callee指令序列插入到插入点并进行完善操作,使插入后的所述caller在不需要所述callee时能够正常运行的步骤。
10.根据权利要求8所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述利用构造store指令栈的方法,将所述callee指令序列插入到插入点并进行完善操作,使插入后的所述caller在不需要所述callee时能够正常运行,包括以下步骤:
构造store指令栈;
按顺序处理callee的参数列表,根据每个参数的数据类型构造相应的store指令,并为中每条store指令设定相应的寄存器的值,添加到store指令栈中;
将store指令栈中的指令依次取出,插入到插入点;
遍历callee指令序列,根据指令的不同做出相应完善操作。
11.根据权利要求10所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述根据每个参数的数据类型构造相应的store指令的具体方法为:
如果参数类型是float类型,则构造的store指令为fstore指令;
如果参数类型是long类型,则构造的store指令为lstore指令;
如果参数类型是double类型,则构造的store指令为dstore指令;
如果参数类型是boolean、byte、char、short、int类型,则构造的store指令为istorte指令;
如果参数类型是上述类型之外的其他类型,则构造的store指令为astore指令。
12.根据权利要求11所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述为每条指令分配相应的寄存器的值的具体方法为:
从方法节点获取caller最大本地变量数量,记为offset,并根据callee是否为静态方法,初始化used的值,即:如果所述callee是静态方法,used的值初始化为0,否则,used的值初始化为1;
每条store指令的寄存器数值为offset+used,其中,used的值按照store指令的顺序自增,如果所述store指令是lstore/dstore指令,则used的值自增量为2,如果所述store指令是其他指令,则used的值自增量为1。
13.根据权利要求11所述的基于字节码的JAVA程序方法内联的方法,其特征在于,在所述将store指令栈中的指令依次取出,插入到插入点之后,所述遍历callee指令序列,根据指令的不同做出相应完善操作之前,判断caller的类型,如果caller是成员方法,则构造astore指令,寄存器值为offset,插入到插入点。
14.根据权利要求10所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述遍历callee指令序列,根据指令的不同做出相应完善操作,具体包括:
如果指令是load/store指令,将寄存器数值自增offset;
如果指令是inc指令,将寄存器数值自增offset;
如果指令是属性访问指令,解析出指令访问的属性所属类型的名称,属性名称,从而从节点仓库查找对应的属性节点,根据属性节点所属类型和caller所属类型的亲近关系,计算是否需要提升属性节点及属性节点所属类的访问权限,如果需要,则进行提升;同时增加caller-属性依赖关系;
如果指令是方法调用指令,解析出指令访问的方法所属类型的名称,方法名称,方法参数列表和返回值,从而从节点仓库查找对应的方法节点,根据方法节点所属类型和caller所属类型的亲近关系,计算是否需要提升方法节点及方法节点所属类的访问权限,如果需要,则进行提升;同时增加caller-方法依赖关系。
15.根据权利要求1-14任一项所述的基于字节码的JAVA程序方法内联的方法,其特征在于,对下述步骤采用对节点仓库的方法节点遍历的方式执行:
读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则进入执行方法内联操作;
其中,所述判断是否存在内联的可行性的判断结果为否,则跳过所述执行方法内联操作的步骤,直接进入对下一个方法节点操作。
16.根据权利要求15所述的基于字节码的JAVA程序方法内联的方法,其特征在于,所述判断是否存在内联的可行性的判断结果为否,以及
判断是否存在内联的可行性的判断结果为是,并进入执行方法内联操作的步骤结束后;进行下述步骤:
判断节点仓库是否存在方法节点,若是,则进入下一个方法节点继续遍历;若否,则结束本次遍历。
17.一种基于字节码的JAVA程序方法内联的装置,其特征在于,包括:
解析单元,用于将类文件解析成类节点,同时将该类的属性和方法分别依次生成属性节点、方法节点,并添加到预先定义的节点仓库中;
判断单元,用于读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则将所述方法节点送入执行内联单元;
执行内联单元,用于对判断结果为可以执行内联的方法执行方法内联操作。
18.一种电子设备,其特征在于,包括:
处理器;以及
存储器,用于存储一种基于字节码的JAVA程序方法内联的程序,该设备通电并通过所述处理器运行所述基于字节码的JAVA程序方法内联的程序后,执行下述步骤:
将类文件解析成类节点,并将该类的属性和方法分别依次生成属性节点、方法节点,然后添加到预先定义的节点仓库中;
读取所述节点仓库的方法节点,针对被读取的方法节点,判断是否存在内联的可行性;若是,则进入下一步;
对判断结果为可以执行内联的方法执行方法内联操作。
Priority Applications (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201710428549.4A CN109032572B (zh) | 2017-06-08 | 2017-06-08 | 一种基于字节码的java程序方法内联的方法 |
Applications Claiming Priority (1)
Application Number | Priority Date | Filing Date | Title |
---|---|---|---|
CN201710428549.4A CN109032572B (zh) | 2017-06-08 | 2017-06-08 | 一种基于字节码的java程序方法内联的方法 |
Publications (2)
Publication Number | Publication Date |
---|---|
CN109032572A true CN109032572A (zh) | 2018-12-18 |
CN109032572B CN109032572B (zh) | 2023-03-31 |
Family
ID=64629542
Family Applications (1)
Application Number | Title | Priority Date | Filing Date |
---|---|---|---|
CN201710428549.4A Active CN109032572B (zh) | 2017-06-08 | 2017-06-08 | 一种基于字节码的java程序方法内联的方法 |
Country Status (1)
Country | Link |
---|---|
CN (1) | CN109032572B (zh) |
Cited By (3)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN109933327A (zh) * | 2019-02-02 | 2019-06-25 | 中国科学院计算技术研究所 | 基于代码融合编译框架的OpenCL编译器设计方法和系统 |
CN110442353A (zh) * | 2019-07-26 | 2019-11-12 | 北京奇艺世纪科技有限公司 | 一种安装包管理的方法、装置及电子设备 |
CN114003317A (zh) * | 2021-10-29 | 2022-02-01 | 北京达佳互联信息技术有限公司 | 内联实现方法及装置、电子设备、存储介质及程序产品 |
Citations (12)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN1158459A (zh) * | 1995-12-08 | 1997-09-03 | 太阳微系统有限公司 | 在保密解译程序中优化运行时调用专用变量函数的系统和方法 |
US20080086514A1 (en) * | 2006-10-04 | 2008-04-10 | Salesforce.Com, Inc. | Methods and systems for providing fault recovery to side effects occurring during data processing |
CN101739333A (zh) * | 2008-11-25 | 2010-06-16 | 国际商业机器公司 | 应用程序的调试方法、调试工具及调试装置 |
CN102132289A (zh) * | 2008-08-21 | 2011-07-20 | 汤姆森特许公司 | 用于代码迷惑的方法及设备 |
US20120174068A1 (en) * | 2010-12-30 | 2012-07-05 | Sap Ag | Testing Software Code |
CN102646035A (zh) * | 2012-02-17 | 2012-08-22 | 南京南瑞继保电气有限公司 | 基于api接口和脚本定义相结合的可视化代码生成方法 |
CN104662513A (zh) * | 2012-07-10 | 2015-05-27 | 洛林·克雷默 | 自动改进程序编译中的并行处理的方法及其系统 |
CN105224864A (zh) * | 2015-11-04 | 2016-01-06 | 中国科学院计算技术研究所 | 一种抵御代码重用攻击的工作进程随机化方法及系统 |
CN105404794A (zh) * | 2014-09-04 | 2016-03-16 | 腾讯科技(深圳)有限公司 | Java应用软件的保护方法和装置 |
CN105653956A (zh) * | 2016-03-02 | 2016-06-08 | 中国科学院信息工程研究所 | 基于动态行为依赖图的Android恶意软件分类方法 |
CN106295385A (zh) * | 2015-05-29 | 2017-01-04 | 华为技术有限公司 | 一种数据保护方法和装置 |
CN108614702A (zh) * | 2016-12-28 | 2018-10-02 | 阿里巴巴集团控股有限公司 | 字节码优化方法及装置 |
-
2017
- 2017-06-08 CN CN201710428549.4A patent/CN109032572B/zh active Active
Patent Citations (12)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN1158459A (zh) * | 1995-12-08 | 1997-09-03 | 太阳微系统有限公司 | 在保密解译程序中优化运行时调用专用变量函数的系统和方法 |
US20080086514A1 (en) * | 2006-10-04 | 2008-04-10 | Salesforce.Com, Inc. | Methods and systems for providing fault recovery to side effects occurring during data processing |
CN102132289A (zh) * | 2008-08-21 | 2011-07-20 | 汤姆森特许公司 | 用于代码迷惑的方法及设备 |
CN101739333A (zh) * | 2008-11-25 | 2010-06-16 | 国际商业机器公司 | 应用程序的调试方法、调试工具及调试装置 |
US20120174068A1 (en) * | 2010-12-30 | 2012-07-05 | Sap Ag | Testing Software Code |
CN102646035A (zh) * | 2012-02-17 | 2012-08-22 | 南京南瑞继保电气有限公司 | 基于api接口和脚本定义相结合的可视化代码生成方法 |
CN104662513A (zh) * | 2012-07-10 | 2015-05-27 | 洛林·克雷默 | 自动改进程序编译中的并行处理的方法及其系统 |
CN105404794A (zh) * | 2014-09-04 | 2016-03-16 | 腾讯科技(深圳)有限公司 | Java应用软件的保护方法和装置 |
CN106295385A (zh) * | 2015-05-29 | 2017-01-04 | 华为技术有限公司 | 一种数据保护方法和装置 |
CN105224864A (zh) * | 2015-11-04 | 2016-01-06 | 中国科学院计算技术研究所 | 一种抵御代码重用攻击的工作进程随机化方法及系统 |
CN105653956A (zh) * | 2016-03-02 | 2016-06-08 | 中国科学院信息工程研究所 | 基于动态行为依赖图的Android恶意软件分类方法 |
CN108614702A (zh) * | 2016-12-28 | 2018-10-02 | 阿里巴巴集团控股有限公司 | 字节码优化方法及装置 |
Non-Patent Citations (3)
Title |
---|
PHILIPPE SMETS: "Data Fusion in the Transferable Belief Model", 《IN PROCEEDINGS OF THE THIRD INTERNATIONAL CONFERENCE ON INFORMATION FUSION》 * |
凌勇: "一种嵌入式Java虚拟机编译技术优化研究", 《中国优秀博士学位论文全文数据库信息科技辑》 * |
吴泽智 等: "基于即时编译的动态污点跟踪优化", 《软件学报》 * |
Cited By (4)
Publication number | Priority date | Publication date | Assignee | Title |
---|---|---|---|---|
CN109933327A (zh) * | 2019-02-02 | 2019-06-25 | 中国科学院计算技术研究所 | 基于代码融合编译框架的OpenCL编译器设计方法和系统 |
CN109933327B (zh) * | 2019-02-02 | 2021-01-08 | 中国科学院计算技术研究所 | 基于代码融合编译框架的OpenCL编译器设计方法和系统 |
CN110442353A (zh) * | 2019-07-26 | 2019-11-12 | 北京奇艺世纪科技有限公司 | 一种安装包管理的方法、装置及电子设备 |
CN114003317A (zh) * | 2021-10-29 | 2022-02-01 | 北京达佳互联信息技术有限公司 | 内联实现方法及装置、电子设备、存储介质及程序产品 |
Also Published As
Publication number | Publication date |
---|---|
CN109032572B (zh) | 2023-03-31 |
Similar Documents
Publication | Publication Date | Title |
---|---|---|
US9122490B2 (en) | Code dependency calculation | |
CN111090433B (zh) | 一种数据处理的方法、装置和存储介质 | |
CN102349056B (zh) | 动态组合数据流处理应用程序 | |
US7552422B2 (en) | Test case inheritance controlled via attributes | |
CN110599183B (zh) | 智能合约调用方法、装置及存储介质 | |
CN108614702B (zh) | 字节码优化方法及装置 | |
CN109240666B (zh) | 基于调用栈和依赖路径的函数调用代码生成方法及系统 | |
CN109032572A (zh) | 一种基于字节码的java程序方法内联的方法 | |
TWI724570B (zh) | 資料結構的讀取及更新方法、裝置、電子設備及儲存媒體 | |
Andrews | Making use of empty intersections to improve the performance of CbO-type algorithms | |
CN109388403A (zh) | 依赖注入方法、装置、设备和存储介质 | |
US7472391B2 (en) | Resource loader for applications that utilize relative uniform resource identifiers | |
WO2024045382A1 (zh) | 区块链中实现反射机制 | |
US8751872B2 (en) | Separation of error information from error propagation information | |
US8707260B2 (en) | Resolving interdependencies between heterogeneous artifacts in a software system | |
US20090204953A1 (en) | Transforming data structures between different programming languages | |
CN111352631B (zh) | 一种接口兼容性检测方法及装置 | |
Farinier et al. | Mergeable persistent data structures | |
CN107766048B (zh) | 一种页面编译方法及装置 | |
Settle et al. | aMatReader: Importing adjacency matrices via Cytoscape Automation | |
JP7059757B2 (ja) | Api処理方法、端末、api処理プログラム | |
US8010572B1 (en) | Kstore scenario simulator processor and XML file | |
CN113391812A (zh) | 应用程序模块的分析方法、装置以及分析工具 | |
Lorenz et al. | Application embedding: A language approach to declarative web programming | |
Doglio | Mastering Python High Performance |
Legal Events
Date | Code | Title | Description |
---|---|---|---|
PB01 | Publication | ||
PB01 | Publication | ||
SE01 | Entry into force of request for substantive examination | ||
SE01 | Entry into force of request for substantive examination | ||
GR01 | Patent grant | ||
GR01 | Patent grant |