发明内容
本申请实施例提供一种字节码文件的处理方法、装置、设备及存储介质,以达到压缩应用程序包体积的目的。
第一方面,本申请实施例提供一种字节码文件的处理方法,包括:
将字节码文件中的多个第一目标方法所包括的目标指令保存到目标指令集合中,目标指令包括字段读写指令,或者,目标指令包括以下至少一种:字段读写指令、方法调用指令;
利用上述目标指令集合对上述多个第一目标方法进行方法内联。
本申请实施例提供的方法,对应用程序的字节码文件中的第一目标方法进行方法内联处理,即删除该第一目标方法,将调用该第一目标方法的方法调用指令替换为该第一目标方法所包括的目标指令,并将第一目标方法访问的字段和/或方法的访问权限修改为“公开”,通过这种处理实现对字节码文件的压缩,进而达到对应用程序的包体积进行压缩的目的。该方法中,先将方法内联过程中替换指令所需要的目标指令保存到目标指令集合中,在执行方法内联的过程中,不需要再次从字节码文件中查找目标指令,而是直接从目标指令集合中读取目标指令进行指令替换。由于目标指令集合中仅保存目标指令相关数据,其数据量远小于字节码文件,因此,直接从目标指令集合中读取目标指令的读取效率更高,从而提高方法内联的处理效率。
在第一方面的一个可选实施例中,将字节码文件中的多个第一目标方法所包括的目标指令保存到目标指令集合中的实现方式包括:通过扫描上述字节码文件查找上述多个第一目标方法,读取查找到的第一目标方法中的目标指令,将读取到的目标指令保存到目标指令集合中;相应的,利用目标指令集合对多个第一目标方法进行方法内联的实现方式包括:通过再次扫描字节码文件查找多个第一目标方法、多个第一目标方法各自被调用所对应的方法调用指令和目标字段,目标字段为目标指令集合中保存的字段读写指令指示的字段;删除查找到的第一目标方法;将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令;将查找到的目标字段的访问权限修改为“公开”;或者,通过再次扫描字节码文件查找多个第一目标方法、多个第一目标方法各自被调用所对应的方法调用指令、目标字段和第二目标方法,目标字段为目标指令集合中保存的字段读写指令指示的字段,第二目标方法为目标指令集合中保存的方法调用指令指示的方法;删除查找到的第一目标方法;将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令;将查找到的目标字段的访问权限修改为“公开”;将查找到的第二目标方法的访问权限修改为“公开”。
在该实施例中,通过第一次扫描字节码文件读取目标指令并保存到目标指令集合中,通过第二次扫描字节码文件执行方法内联。由于第一次扫描字节码文件的过程中读取了目标指令并保存到目标指令集合中,使得第二次扫描字节码文件的过程中,可以利用目标指令集合快速查找替换所需要的指令、目标字段及第二目标方法,因此可以通过第二次扫描字节码文件一并实现方法内联中的第一目标方法删除、指令替换、访问权限修改,进一步提高处理效率。
在此基础上,第一次和/或第二次扫描字节码文件过程中,查找第一目标方法的实现方式可以包括:
查找由编译器生成的、静态类型的,且方法名以“access”为前缀的方法作为第一目标方法;和/或,查找只包括有字段读写指令,且不属于预定的免内联方法集合的赋值方法和取值方法作为第一目标方法。
并非所有方法均可以通过方法内联进行优化。若方法指令过多,方法内联并不能达到减少代码、压缩字节码文件的目的,甚至还会导致热修复问题。发明人在实现本申请的过程中发现,由编译器生成的桥接方法可以通过方法内联进行优化,且桥接方法的指令较少,优化之后能够达到字节码文件压缩的目的。因此,可以查找编译器生成的桥接方法作为第一目标方法。发明人在实现本申请的过程中还发现,只包含字段读写指令的赋值方法和取值方法也可以通过方法内联实现优化,但也有一部分符合这一条件的赋值方法和取值方法若通过方法内联进行优化,在应用程序运行过程中会导致热修复问题,因此,预先识别出这部分赋值方法和取值方法,将识别出来的方法确定免内联方法集合,查找符合上述条件且不包含在该免内联方法集合中的赋值方法和取值方法,对其进行方法内联,从而达到字节码文件压缩的目的。
在上述第一方面的两次扫描字节码文件的任意实施例中,查找目标字段的实现方式可以包括:将从字节码文件中扫描到的字段与目标指令集合中保存的字段读写指令指示的字段进行匹配,匹配成功的字段作为目标字段。
由于在第一次扫描字节码文件的过程中将目标指令保存到了目标指令集合中,因此,在第二次字节码文件的扫描过程中可以将扫描到的字段与目标指令集合中的字段读写指令指示的字段进行匹配,从而快速查找出目标字段,提高处理效率。
在上述第一方面的两次扫描字节码文件的任意实施例中,查找第二目标方法的实现方式可以是:读取字节码文件中的非第一目标方法的方法索引;将非第一目标方法的方法索引与目标指令集合中保存的方法调用指令指示的方法索引进行匹配,匹配成功的方法为第二目标方法。
由于在第一次扫描字节码文件的过程中将目标指令保存到了目标指令集合中,因此,在第二次字节码文件的扫描过程中可以将扫描到的非第一目标方法的方法索引与目标指令集合中保存的方法调用指令指示的方法索引进行匹配,从而快速查找到第二目标方法,提高处理效率。
在上述第一方面的两次扫描字节码文件的实施例中,将读取到的目标指令保存到目标指令集合之前,还可以读取查找到的第一目标方法的方法索引。相应的,将读取到的目标指令保存到目标指令集合中的实现方式可以是:将读取到的第一目标方法的方法索引和目标指令关联保存到目标指令集合中。
在此基础上,一方面,通过再次扫描字节码文件查找第一目标方法和第二目标方法的实现方式还可以是:读取从字节码文件中扫描到的方法的方法索引;将扫描到的方法的方法索引与目标指令集合中保存的方法索引进行匹配;与目标指令集合中保存的方法调用指令指示的方法索引匹配成功的方法为第二目标方法,与目标指令集合中保存的第一目标方法的方法索引匹配成功的方法为第一目标方法。在该实施例中,目标指令集合中关联保存有第一目标方法的方法索引和目标指令,那么,在第二次扫描字节码文件以执行方法内联的过程中,对于扫描到的方法,读取其方法索引并在目标指令集合中进行匹配,通过一次匹配可以识别出该方法是否为第一目标方法以及第二目标方法。即,第一目标方法和第二目标方法采用相同的手段进行匹配查找,可简化查找过程,提高处理效率。
另一方面,查找多个第一目标方法各自被调用所对应的方法调用指令的实现方式可以是:将从字节码文件中扫描到的方法调用指令指示的方法索引与目标指令集合中保存的第一目标方法的方法索引进行匹配,匹配成功的方法调用指令作为第一目标方法被调用所对应的方法调用指令;将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令,其实现方式可以是:将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为所述目标指令集合中与本第一目标方法的方法索引关联保存的目标指令。在该实施例中,指令替换也可以通过在目标指令集合中进行匹配快速完成,提高了处理效率。
第二方面,本申请实施例提供一种字节码文件的处理装置,包括:
目标指令提取模块,用于将字节码文件中的多个第一目标方法所包括的目标指令保存到目标指令集合中,目标指令包括字段读写指令,或者,目标指令包括以下至少一种:字段读写指令、方法调用指令;
方法内联执行模块,用于利用目标指令集合对多个第一目标方法进行方法内联。
本申请实施例提供的装置,对应用程序的字节码文件中的第一目标方法进行方法内联处理,即删除该第一目标方法,将调用该第一目标方法的方法调用指令替换为该第一目标方法所包括的目标指令,并将第一目标方法访问的字段和/或方法的访问权限修改为“公开”,通过这种处理实现对字节码文件的压缩,进而达到对应用程序的包体积进行压缩的目的。该装置实现其功能的过程中,先将方法内联过程中替换指令所需要的目标指令保存到目标指令集合中,在执行方法内联的过程中,不需要再次从字节码文件中查找目标指令,而是直接从目标指令集合中读取目标指令进行指令替换。由于目标指令集合中仅保存目标指令相关数据,其数据量远小于字节码文件,因此,直接从目标指令集合中读取目标指令的读取效率更高,从而提高方法内联的处理效率。
在第二方面的一个可选实施例中,目标指令提取模块具体可以用于:通过扫描上述字节码文件查找上述多个第一目标方法,读取查找到的第一目标方法中的目标指令,将读取到的目标指令保存到目标指令集合中;相应的,方法内联执行模块具体可以用于:通过再次扫描字节码文件查找多个第一目标方法、多个第一目标方法各自被调用所对应的方法调用指令和目标字段,目标字段为目标指令集合中保存的字段读写指令指示的字段;删除查找到的第一目标方法;将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令;将查找到的目标字段的访问权限修改为“公开”;或者,通过再次扫描字节码文件查找多个第一目标方法、多个第一目标方法各自被调用所对应的方法调用指令、目标字段和第二目标方法,目标字段为目标指令集合中保存的字段读写指令指示的字段,第二目标方法为目标指令集合中保存的方法调用指令指示的方法;删除查找到的第一目标方法;将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令;将查找到的目标字段的访问权限修改为“公开”;将查找到的第二目标方法的访问权限修改为“公开”。
在该实施例中,通过第一次扫描字节码文件读取目标指令并保存到目标指令集合中,通过第二次扫描字节码文件执行方法内联。由于第一次扫描字节码文件的过程中读取了目标指令并保存到目标指令集合中,使得第二次扫描字节码文件的过程中,可以利用目标指令集合快速查找替换所需要的指令、目标字段及第二目标方法,因此可以通过第二次扫描字节码文件一并实现方法内联中的第一目标方法删除、指令替换、访问权限修改,进一步提高处理效率。
在此基础上,目标指令提取模块通过扫描字节码文件查找第一目标方法的实现方式可以包括:查找由编译器生成的、静态类型的,且方法名以“access”为前缀的方法作为第一目标方法;和/或,查找只包括有字段读写指令,且不属于预定的免内联方法集合的赋值方法和取值方法作为第一目标方法。方法内联执行模块通过再次扫描字节码文件查找第一目标方法实现方式可以包括:查找由编译器生成的、静态类型的,且方法名以“access”为前缀的方法作为第一目标方法;和/或,查找只包括有字段读写指令,且不属于预定的免内联方法集合的赋值方法和取值方法作为第一目标方法。
并非所有方法均可以通过方法内联进行优化。若方法指令过多,方法内联并不能达到减少代码、压缩字节码文件的目的,甚至还会导致热修复问题。发明人在实现本申请的过程中发现,由编译器生成的桥接方法可以通过方法内联进行优化,且桥接方法的指令较少,优化之后能够达到字节码文件压缩的目的。因此,可以查找编译器生成的桥接方法作为第一目标方法。发明人在实现本申请的过程中还发现,只包含字段读写指令的赋值方法和取值方法也可以通过方法内联实现优化,但也有一部分符合这一条件的赋值方法和取值方法若通过方法内联进行优化,在应用程序运行过程中会导致热修复问题,因此,预先识别出这部分赋值方法和取值方法,将识别出来的方法确定免内联方法集合,查找符合上述条件且不包含在该免内联方法集合中的赋值方法和取值方法,对其进行方法内联,从而达到字节码文件压缩的目的。
在上述第二方面的两次扫描字节码文件的任意实施例中,方法内联执行模块查找目标字段的实现方式可以包括:将从字节码文件中扫描到的字段与目标指令集合中保存的字段读写指令指示的字段进行匹配,匹配成功的字段作为目标字段。
由于在第一次扫描字节码文件的过程中将目标指令保存到了目标指令集合中,因此,在第二次字节码文件的扫描过程中可以将扫描到的字段与目标指令集合中的字段读写指令指示的字段进行匹配,从而快速查找出目标字段,提高处理效率。
在上述第二方面的两次扫描字节码文件的任意实施例中,方法内联执行模块查找第二目标方法的实现方式可以是:读取字节码文件中的非第一目标方法的方法索引;将非第一目标方法的方法索引与目标指令集合中保存的方法调用指令指示的方法索引进行匹配,匹配成功的方法为第二目标方法。
由于在第一次扫描字节码文件的过程中将目标指令保存到了目标指令集合中,因此,在第二次字节码文件的扫描过程中可以将扫描到的非第一目标方法的方法索引与目标指令集合中保存的方法调用指令指示的方法索引进行匹配,从而快速查找到第二目标方法,提高处理效率。
在上述第二方面的两次扫描字节码文件的实施例中,目标指令读取模块将读取到的目标指令保存到目标指令集合之前,还可以读取查找到的第一目标方法的方法索引。相应的,目标指令提取模块将读取到的目标指令保存到目标指令集合中的实现方式可以是:将读取到的第一目标方法的方法索引和目标指令关联保存到目标指令集合中。
在此基础上,一方面,方法内联执行模块通过再次扫描字节码文件查找第一目标方法和第二目标方法的实现方式还可以是:读取从字节码文件中扫描到的方法的方法索引;将扫描到的方法的方法索引与目标指令集合中保存的方法索引进行匹配;与目标指令集合中保存的方法调用指令指示的方法索引匹配成功的方法为第二目标方法,与目标指令集合中保存的第一目标方法的方法索引匹配成功的方法为第一目标方法。在该实施例中,目标指令集合中关联保存有第一目标方法的方法索引和目标指令,那么,在第二次扫描字节码文件以执行方法内联的过程中,对于扫描到的方法,读取其方法索引并在目标指令集合中进行匹配,通过一次匹配可以识别出该方法是否为第一目标方法以及第二目标方法。即,第一目标方法和第二目标方法采用相同的手段进行匹配查找,可简化查找过程,提高处理效率。
另一方面,方法内联执行模块查找多个第一目标方法各自被调用所对应的方法调用指令的实现方式可以是:将从字节码文件中扫描到的方法调用指令指示的方法索引与目标指令集合中保存的第一目标方法的方法索引进行匹配,匹配成功的方法调用指令作为第一目标方法被调用所对应的方法调用指令;方法内联执行模块将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令,其实现方式可以是:将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为所述目标指令集合中与本第一目标方法的方法索引关联保存的目标指令。在该实施例中,指令替换也可以通过在目标指令集合中进行匹配快速完成,提高了处理效率。
第三方面,本申请实施例提供一种计算机设备,包括处理器和存储器;存储器用于存储执行第一方面各个实施例所述方法的程序;处理器被配置为执行存储器中存储的程序。
本申请实施例提供的计算机设备,对应用程序的字节码文件中的第一目标方法进行方法内联处理,即删除该第一目标方法,将调用该第一目标方法的方法调用指令替换为该第一目标方法所包括的目标指令,并将第一目标方法访问的字段和/或方法的访问权限修改为“公开”,通过这种处理实现对字节码文件的压缩,进而达到对应用程序的包体积进行压缩的目的。该计算机设备执行上述程序的过程中,先将方法内联过程中替换指令所需要的目标指令保存到目标指令集合中,在执行方法内联的过程中,不需要再次从字节码文件中查找目标指令,而是直接从目标指令集合中读取目标指令进行指令替换。由于目标指令集合中仅保存目标指令相关数据,其数据量远小于字节码文件,因此,直接从目标指令集合中读取目标指令的读取效率更高,从而提高方法内联的处理效率。
第四方面,本申请实施例提供一种计算机可读存储介质,存储有执行第一方面各个实施例所述方法的程序。
本申请实施例提供的计算机可读存储介质,对应用程序的字节码文件中的第一目标方法进行方法内联处理,即删除该第一目标方法,将调用该第一目标方法的方法调用指令替换为该第一目标方法所包括的目标指令,并将第一目标方法访问的字段和/或方法的访问权限修改为“公开”,通过这种处理实现对字节码文件的压缩,进而达到对应用程序的包体积进行压缩的目的。程序执行过程中,先将方法内联过程中替换指令所需要的目标指令保存到目标指令集合中,在执行方法内联的过程中,不需要再次从字节码文件中查找目标指令,而是直接从目标指令集合中读取目标指令进行指令替换。由于目标指令集合中仅保存目标指令相关数据,其数据量远小于字节码文件,因此,直接从目标指令集合中读取目标指令的读取效率更高,从而提高方法内联的处理效率。
具体实施方式
为了更好的理解上述技术方案,下面通过附图以及具体实施例对本申请实施例的技术方案做详细的说明,应当理解本申请实施例以及实施例中的具体特征是对本申请实施例技术方案的详细的说明,而不是对本申请技术方案的限定,在不冲突的情况下,本申请实施例以及实施例中的技术特征可以相互组合。
本申请实施例提供一种字节码文件的处理方法,通过对应用程序的字节码文件中的第一目标方法进行方法内联处理,可以压缩字节码文件。利用压缩后的字节码文件进行应用程序打包,可达到压缩应用程序包大小的目的。
并非所有方法均可以通过方法内联进行优化。若方法指令过多,方法内联并不能达到减少代码、压缩字节码文件的目的,甚至还会导致热修复问题。
发明人在实现本申请的过程中发现,由编译器生成的桥接方法可以通过方法内联进行优化,且桥接方法的指令较少,优化之后能够达到字节码文件压缩的目的。因此,可以查找编译器生成的桥接方法作为第一目标方法。针对外部类访问内部类成员以及内部类访问外部类成员的需求,一种处理方式是在编写源代码时通过编写对应的方法代码实现,为了减少代码编写的工作量,另一种处理方式是由编译器(例如JAVAC)将应用程序的JAVA源代码编译成字节码的过程中生成桥接方法,以便通过生成的桥接方法实现上述访问。编译器自动生成桥接方法的处理方式虽然简化了代码编写过程,但增加了字节码文件的体积。发明人在实现本发明的过程中发现,对桥接方法进行方法内联,仍然可以达到上述访问目的,且可减少字节码文件的体积。
发明人在实现本申请的过程中还发现,只包含字段读写指令的赋值方法和取值方法也可以通过方法内联实现优化,但也有一部分符合这一条件的赋值(setter)方法和取值(getter)方法若通过方法内联进行优化,在应用程序运行过程中会导致热修复问题,因此,预先识别出这部分赋值方法和取值方法,将识别出来的方法确定免内联方法集合,查找符合上述条件且不包含在该免内联方法集合中的赋值方法和取值方法,对其进行方法内联,从而达到字节码文件压缩的目的。
应当指出的是,本发明实施例并不限定仅对桥接方法、符合上述条件的赋值方法和取值方法进行方法内联。在实际应用中,还可以根据实际情况定义其他第一目标方法,并对其进行方法内联。
如图1所示,本发明实施例提供的字节码文件的处理方法包括如下操作:
步骤101、将字节码文件中的多个第一目标方法所包括的目标指令保存到目标指令集合中。
其中,根据优化对象(第一目标方法)不同,目标指令的内容也有所不同。一种情况下(如仅将上述赋值方法和取值方法作为优化对象),目标指令包括字段读写指令,但不包括方法调用指令。另一种情况下(如将桥接方法及上述赋值方法和取值方法均作为优化对象),目标指令包括以下至少一种:字段读写指令、方法调用指令。实际应用中,可以根据应用场景及需求等因素确定哪些指令作为目标指令。
其中,字节码文件是指应用程序的多个字节码文件。优选的,是指应用程序的全部字节码文件,相应的,多个第一目标方法是指全部字节码文件中的全部第一目标方法。
其中,不对目标指令集合的数据结构进行限定,可采用现有的任意数据结构实现目标指令集合。
步骤102、利用上述目标指令集合对上述多个第一目标方法进行方法内联。
本申请实施例提供的方法,对应用程序的字节码文件中的第一目标方法进行方法内联处理,即删除该第一目标方法,将调用该第一目标方法的方法调用指令替换为该第一目标方法所包括的目标指令,并将第一目标方法访问的字段和/或方法的访问权限修改为“公开”,通过这种处理实现对字节码文件的压缩,进而达到对应用程序的包体积进行压缩的目的。该方法中,先将方法内联过程中替换指令所需要的目标指令保存到目标指令集合中,在执行方法内联的过程中,不需要再次从字节码文件中查找目标指令,而是直接从目标指令集合中读取目标指令进行指令替换。由于目标指令集合中仅保存目标指令相关数据,其数据量远小于字节码文件,因此,直接从目标指令集合中读取目标指令的读取效率更高,从而提高方法内联的处理效率。
在一个可选实施例中,通过一次扫描上述字节码文件实现上述步骤101,通过再次扫描上述字节码文件实现上述步骤102。即:通过扫描上述字节码文件查找上述多个第一目标方法,读取查找到的第一目标方法中的目标指令,将读取到的目标指令保存到目标指令集合中;通过再次扫描字节码文件查找多个第一目标方法、多个第一目标方法各自被调用所对应的方法调用指令和目标字段(若目标指令还可以包括方法调用指令,再次扫描字节码文件时还查找第二目标方法),其中,目标字段为目标指令集合中保存的字段读写指令指示的字段,第二目标方法为目标指令集合中保存的方法调用指令指示的方法;删除查找到的第一目标方法;将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令;将查找到的目标字段的访问权限修改为“公开”(若查找且查找到第二目标方法,还将查找到的第二目标方法的访问权限修改为“公开”)。
本申请实施例中,字段读写指令指示的字段是指字段读写指令访问的字段,在字段读写指令中包括该字段(具体包括该字段的字段名)。
本申请实施例中,方法调用指令指示的方法是指方法调用指令访问(或称调用)的方法,在方法调用指令中包括该方法的方法索引。
在该实施例中,通过第一次扫描字节码文件读取目标指令并保存到目标指令集合中,通过第二次扫描字节码文件执行方法内联。由于第一次扫描字节码文件的过程中读取了目标指令并保存到目标指令集合中,使得第二次扫描字节码文件的过程中,可以利用目标指令集合快速查找替换所需要的指令、目标字段及第二目标方法,因此可以通过第二次扫描字节码文件一并实现方法内联中的第一目标方法删除、指令替换、访问权限修改,进一步提高处理效率。
在另一个可选实施例中,通过一次扫描上述字节码文件实现上述步骤101以及上述步骤102中的部分子步骤(即删除第一目标方法),通过再次扫描上述字节码文件实现上述步骤102中的其余子步骤。即,通过扫描上述字节码文件查找上述多个第一目标方法,读取查找到的第一目标方法中的目标指令,将读取到的目标指令保存到目标指令集合中,并删除查找到的第一目标方法;通过再次扫描字节码文件查找多个第一目标方法各自被调用所对应的方法调用指令和目标字段(若目标指令还可以包括方法调用指令,再次扫描字节码文件时还查找第二目标方法);将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令;将查找到的目标字段的访问权限修改为“公开”(若查找且查找到第二目标方法,还将查找到的第二目标方法的访问权限修改为“公开”)。
在第一次扫描字节码文件的过程中就删除第一目标方法,可以减少第二次扫描字节码文件的处理量,进一步提高处理效率。
应用程序的字节码文件中包括方法数据和字段数据,其中,方法数据用于描述应用程序的方法,包括方法索引、方法的指令(如字段读写指令、方法调用指令等)、方法状态(INT)等数据,字段数据包括字段名、字段访问权限等数据。相应的,所谓删除第一目标方法,是指删除第一目标方法的方法数据。
本申请实施例中,第一次扫描字节码文件可以仅扫描字节码文件中的方法数据,即:每扫描到一个方法的方法数据,即通过方法数据判断该方法是否为第一目标方法,若扫描到字段数据,则跳过字段数据不继续对其进行扫描。
以查找上述桥接方法为例,在第一次扫描字节码文件过程中,查找由编译器生成的、静态类型的,且方法名以“access”为前缀的方法作为第一目标方法。在一个可选的实现方式中,在第一次扫描字节码文件的过程中,每扫描到一个方法的方法数据,则:从该方法的方法状态中查找“synthetic”状态位,根据该状态位的取值判断该方法是否为编译器生成的方法,从该方法的方法状态中查找“static”状态位,根据该状态位的取值判断该方法是否为静态类型的方法,将该方法的方法名与字符串“access$”进行匹配以判断方法名是否以“access”为前缀;若该方法是由编译器生成的静态方法,且以“access”为前缀,则该方法为桥接方法,从该方法的方法数据中查找字段读写指令和方法调用指令,将查找到的字段读写指令和/或方法调用指令保存到目标指令集合中,否则,跳过该方法继续进行后续扫描。
以查找上述赋值方法和取值方法为例,在第一次扫描字节码文件过程中,查找只包括有字段读写指令,且不属于预定的免内联方法集合的赋值方法和取值方法作为第一目标方法。在一个可选的实现方式中,在第一次扫描字节码文件的过程中,每扫描到一个方法的方法数据,则:通过该方法的方法名判断该方法是否为赋值方法或取值方法;若该方法是赋值方法或取值方法,判断该方法的指令是否仅包括字段读写指令;若该方法仅包含字段读写指令,则判断该方法是否属于预定的免内联方法集合;若该方法为仅包含字段读写指令、且不属于免内联方法集合中的赋值方法或取值方法,则将该方法的字段读写指令保存到目标指令集合中,否则,跳过该方法继续进行后续扫描。
本申请实施例中,免内联方法集合可以但不仅限于利用现有的混淆工具(如Proguard)得到,例如,提取并解析Proguard的keep规则得到免内联方法集合。
若在第二次扫描字节码文件的过程中删除第一目标方法,那么,通过再次扫描字节码文件查找第一目标方法的实现方式可以参照第一次扫描字节码文件过程中查找第一目标方法的实现方式,此处不再赘述。
除此之外,还可以通过其他实现方式在第二次扫描字节码文件时查找第一目标方法。例如,读取从字节码文件中扫描到的方法的方法索引;将扫描到的方法的方法索引与目标指令集合中保存的第一目标方法的方法索引进行匹配;匹配成功的方法为第一目标方法。更具体地,在第二次扫描字节码文件的过程中,每扫描到一个方法的方法数据,则将该方法的方法索引与目标指令集合中保存的第一目标方法的方法索引进行匹配,若匹配成功,删除该方法的方法数据。
上述情况下,目标指令集合中还需要保存第一目标方法的方法索引。本申请实施例中,方法索引包括方法名、方法所在类的类名和方法签名(即方法参数类型)。应当指出的是,一个字节码文件对应一个类,因此,一个字节码文件中可以仅保存一个类名,那么,在删除第一目标方法的方法数据时,对于方法索引,仅删除其方法名和方法签名部分。
相应的,在将读取到的目标指令保存到目标指令集合之前,还读取查找到的第一目标方法的方法索引。相应的,将读取到的目标指令保存到目标指令集合中的实现方式可以是:将读取到的第一目标方法的方法索引和目标指令关联保存到目标指令集合中。
应当指出的是,在方法内联进行指令替换时,需要区分目标指令集合中的目标指令属于哪个第一目标方法,因此,需要将第一目标方法的目标指令与第一目标方法的标识信息关联保存。方法索引作为方法的标识信息仅是其中一种实现方式,能区分各个第一目标方法的信息均可以作为第一目标方法的标识信息,本申请对此不做限定。
在上述两次扫描字节码文件的任意实施例中,查找目标字段的实现方式可以包括:将从字节码文件中扫描到的字段与目标指令集合中保存的字段读写指令指示的字段进行匹配,匹配成功的字段作为目标字段。
由于在第一次扫描字节码文件的过程中将目标指令保存到了目标指令集合中,因此,在第二次字节码文件的扫描过程中可以将扫描到的字段与目标指令集合中的字段读写指令指示的字段进行匹配,从而快速查找出目标字段,提高处理效率。
在上述两次扫描字节码文件的任意实施例中,查找第二目标方法的一种实现方式可以是:读取字节码文件中的非第一目标方法的方法索引;将非第一目标方法的方法索引与目标指令集合中保存的方法调用指令指示的方法索引进行匹配,匹配成功的方法为第二目标方法。由于在第一次扫描字节码文件的过程中将目标指令保存到了目标指令集合中,因此,在第二次字节码文件的扫描过程中可以将扫描到的非第一目标方法的方法索引与目标指令集合中保存的方法调用指令指示的方法索引进行匹配,从而快速查找到第二目标方法,提高处理效率。
查找第一目标方法第二目标方法的实现方式还可以是:读取从字节码文件中扫描到的方法的方法索引;将扫描到的方法的方法索引与目标指令集合中保存的方法调用指令指示的方法索引进行匹配,匹配成功的方法为第二目标方法。
在一个可行的实现方式中,读取从字节码文件中扫描到的方法的方法索引,将扫描到的方法的方法索引与目标指令集合中保存的方法索引进行匹配;与方法调用指令指示的方法索引匹配成功的方法为第二目标方法,与第一目标方法的方法索引匹配成功的方法为第一目标方法。在该实现方式中,目标指令集合中关联保存有第一目标方法的方法索引和目标指令,那么,在第二次扫描字节码文件以执行方法内联的过程中,对于扫描到的方法,读取其方法索引并在目标指令集合中进行匹配,通过一次匹配可以识别出该方法是否为第一目标方法以及第二目标方法。即,第一目标方法和第二目标方法采用相同的手段进行匹配查找,可简化查找过程,提高处理效率。
若目标指令集合中关联保存有第一目标方法的方法索引和目标指令,查找多个第一目标方法各自被调用所对应的方法调用指令的实现方式可以是:将从字节码文件中扫描到的方法调用指令指示的方法索引与目标指令集合中保存的第一目标方法的方法索引进行匹配,匹配成功的方法调用指令作为第一目标方法被调用所对应的方法调用指令;将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令,其实现方式可以是:将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为所述目标指令集合中与本第一目标方法的方法索引关联保存的目标指令。在该实施例中,指令替换也可以通过在目标指令集合中进行匹配快速完成,提高了处理效率。
可见,本申请实施例中,第二次扫描字节码文件是对字节码文件的方法及字段进行扫描。
下面结合具体场景对本申请实施例提供方法进行说明。
对某安卓应用程序的字节码文件进行打包的过程中,对字节码文件中的桥接方法和符合条件的getter和setter方法进行方法内联,以减少该安卓应用程序的方法数和包大小。具体的:
扫描安卓应用程序的所有字节码文件的方法,每扫描到一个方法的方法数据:
从中读取该方法的方法名,通过方法名判断该方法是否为以“access”为前缀的方法或getter方法、setter方法;
若该方法是以“access”为前缀的方法,进一步从该方法的方法状态中查找“synthetic”状态位,根据该状态位的取值判断该方法是否为编译器生成的方法,从该方法的方法状态中查找“static”状态位,根据该状态位的取值判断该方法是否为静态类型的方法,若该方法是由编译器生成的静态方法,且以“access”为前缀,则该方法为桥接方法,从该方法的方法数据中查找字段读写指令和方法调用指令,将查找到的字段读写指令和/或方法调用指令保存到目标指令集合中,否则,跳过该方法继续进行后续扫描;
若getter方法或setter方法,判断该方法的指令是否仅包括字段读写指令;若该方法仅包含字段读写指令,则判断该方法是否属于预定的免内联方法集合;若该方法为仅包含字段读写指令、且不属于免内联方法集合中的赋值方法或取值方法,则将该方法的字段读写指令保存到目标指令集合中,否则,跳过该方法继续进行后续扫描。
完成第一次字节码文件扫描后,再次对字节码文件中的字段和方法进行扫描,每扫描到一个字段的字段数据:
将该字段与目标指令集合中保存的字段读取指令指示的字段进行匹配,若匹配成功,则将该字段的读写权限修改为“公开(public)”;否则,跳过该字段,继续进行扫描。
每扫描到一个方法的方法数据:
从中读取该方法的方法索引,将该方法的方法索引与目标指令集合中保存的方法索引进行匹配;
若与目标指令集合中保存的第一目标方法的方法索引匹配成功,删除该方法的方法数据;
若与目标指令集合中保存的方法调用指令指示的方法索引匹配成功,将该方法的访问权限修改为“公开”;
若与目标指令集合中保存的方法索引匹配不成功,在该方法的指令中查找方法调用指令,将查找到的方法调用指令指示的方法索引与目标指令集合中保存的第一目标方法的方法索引匹配,若匹配成功,利用匹配成功的方法索引关联保存的目标指令替换查找到的该方法调用指令;否则,跳过该方法,继续后续扫描。
应当指出的是,上述通过两次扫描字节码文件实现方法内联为优选的实现方式。在实际应用中,也可以通过多次扫描字节码文件实现方法内联。例如,通过至少一次扫描字节码文件查找目标字段,通过至少一次扫描字节码文件查找调用第一目标方法的方法。
基于与方法同样的发明构思,本申请实施例提供一种字节码文件的处理装置,如图2所示,包括:
目标指令提取模块201,用于将字节码文件中的多个第一目标方法所包括的目标指令保存到目标指令集合中,目标指令包括字段读写指令,或者,目标指令包括以下至少一种:字段读写指令、方法调用指令;
方法内联执行模块202,用于利用目标指令集合对多个第一目标方法进行方法内联。
本申请实施例提供的装置,对应用程序的字节码文件中的第一目标方法进行方法内联处理,即删除该第一目标方法,将调用该第一目标方法的方法调用指令替换为该第一目标方法所包括的目标指令,并将第一目标方法访问的字段和/或方法的访问权限修改为“公开”,通过这种处理实现对字节码文件的压缩,进而达到对应用程序的包体积进行压缩的目的。该装置实现其功能的过程中,先将方法内联过程中替换指令所需要的目标指令保存到目标指令集合中,在执行方法内联的过程中,不需要再次从字节码文件中查找目标指令,而是直接从目标指令集合中读取目标指令进行指令替换。由于目标指令集合中仅保存目标指令相关数据,其数据量远小于字节码文件,因此,直接从目标指令集合中读取目标指令的读取效率更高,从而提高方法内联的处理效率。
在一个可选实施例中,目标指令提取模块具体可以用于:通过扫描上述字节码文件查找上述多个第一目标方法,读取查找到的第一目标方法中的目标指令,将读取到的目标指令保存到目标指令集合中;相应的,方法内联执行模块具体可以用于:通过再次扫描字节码文件查找多个第一目标方法、多个第一目标方法各自被调用所对应的方法调用指令和目标字段,目标字段为目标指令集合中保存的字段读写指令指示的字段;删除查找到的第一目标方法;将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令;将查找到的目标字段的访问权限修改为“公开”;或者,通过再次扫描字节码文件查找多个第一目标方法、多个第一目标方法各自被调用所对应的方法调用指令、目标字段和第二目标方法,目标字段为目标指令集合中保存的字段读写指令指示的字段,第二目标方法为目标指令集合中保存的方法调用指令指示的方法;删除查找到的第一目标方法;将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令;将查找到的目标字段的访问权限修改为“公开”;将查找到的第二目标方法的访问权限修改为“公开”。
在该实施例中,通过第一次扫描字节码文件读取目标指令并保存到目标指令集合中,通过第二次扫描字节码文件执行方法内联。由于第一次扫描字节码文件的过程中读取了目标指令并保存到目标指令集合中,使得第二次扫描字节码文件的过程中,可以利用目标指令集合快速查找替换所需要的指令、目标字段及第二目标方法,因此可以通过第二次扫描字节码文件一并实现方法内联中的第一目标方法删除、指令替换、访问权限修改,进一步提高处理效率。
在此基础上,目标指令提取模块通过扫描字节码文件查找第一目标方法的实现方式可以包括:查找由编译器生成的、静态类型的,且方法名以“access”为前缀的方法作为第一目标方法;和/或,查找只包括有字段读写指令,且不属于预定的免内联方法集合的赋值方法和取值方法作为第一目标方法。方法内联执行模块通过再次扫描字节码文件查找第一目标方法实现方式可以包括:查找由编译器生成的、静态类型的,且方法名以“access”为前缀的方法作为第一目标方法;和/或,查找只包括有字段读写指令,且不属于预定的免内联方法集合的赋值方法和取值方法作为第一目标方法。
并非所有方法均可以通过方法内联进行优化。若方法指令过多,方法内联并不能达到减少代码、压缩字节码文件的目的,甚至还会导致热修复问题。发明人在实现本申请的过程中发现,由编译器生成的桥接方法可以通过方法内联进行优化,且桥接方法的指令较少,优化之后能够达到字节码文件压缩的目的。因此,可以查找编译器生成的桥接方法作为第一目标方法。发明人在实现本申请的过程中还发现,只包含字段读写指令的赋值方法和取值方法也可以通过方法内联实现优化,但也有一部分符合这一条件的赋值方法和取值方法若通过方法内联进行优化,在应用程序运行过程中会导致热修复问题,因此,预先识别出这部分赋值方法和取值方法,将识别出来的方法确定免内联方法集合,查找符合上述条件且不包含在该免内联方法集合中的赋值方法和取值方法,对其进行方法内联,从而达到字节码文件压缩的目的。
在上述两次扫描字节码文件的任意装置侧实施例中,方法内联执行模块查找目标字段的实现方式可以包括:将从字节码文件中扫描到的字段与目标指令集合中保存的字段读写指令指示的字段进行匹配,匹配成功的字段作为目标字段。
由于在第一次扫描字节码文件的过程中将目标指令保存到了目标指令集合中,因此,在第二次字节码文件的扫描过程中可以将扫描到的字段与目标指令集合中的字段读写指令指示的字段进行匹配,从而快速查找出目标字段,提高处理效率。
在上述两次扫描字节码文件的任意装置侧实施例中,方法内联执行模块查找第二目标方法的实现方式可以是:读取字节码文件中的非第一目标方法的方法索引;将非第一目标方法的方法索引与目标指令集合中保存的方法调用指令指示的方法索引进行匹配,匹配成功的方法为第二目标方法。
由于在第一次扫描字节码文件的过程中将目标指令保存到了目标指令集合中,因此,在第二次字节码文件的扫描过程中可以将扫描到的非第一目标方法的方法索引与目标指令集合中保存的方法调用指令指示的方法索引进行匹配,从而快速查找到第二目标方法,提高处理效率。
在上述两次扫描字节码文件的装置侧实施例中,目标指令读取模块将读取到的目标指令保存到目标指令集合之前,还可以读取查找到的第一目标方法的方法索引。相应的,目标指令提取模块将读取到的目标指令保存到目标指令集合中的实现方式可以是:将读取到的第一目标方法的方法索引和目标指令关联保存到目标指令集合中。
在此基础上,一方面,方法内联执行模块通过再次扫描字节码文件查找第一目标方法和第二目标方法的实现方式还可以是:读取从字节码文件中扫描到的方法的方法索引;将扫描到的方法的方法索引与目标指令集合中保存的方法索引进行匹配;与目标指令集合中保存的方法调用指令指示的方法索引匹配成功的方法为第二目标方法,与目标指令集合中保存的第一目标方法的方法索引匹配成功的方法为第一目标方法。在该实施例中,目标指令集合中关联保存有第一目标方法的方法索引和目标指令,那么,在第二次扫描字节码文件以执行方法内联的过程中,对于扫描到的方法,读取其方法索引并在目标指令集合中进行匹配,通过一次匹配可以识别出该方法是否为第一目标方法以及第二目标方法。即,第一目标方法和第二目标方法采用相同的手段进行匹配查找,可简化查找过程,提高处理效率。
另一方面,方法内联执行模块查找多个第一目标方法各自被调用所对应的方法调用指令的实现方式可以是:将从字节码文件中扫描到的方法调用指令指示的方法索引与目标指令集合中保存的第一目标方法的方法索引进行匹配,匹配成功的方法调用指令作为第一目标方法被调用所对应的方法调用指令;方法内联执行模块将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为目标指令集合中保存的本第一目标方法所包括目标指令,其实现方式可以是:将查找到的多个第一目标方法各自被调用所对应的方法调用指令替换为所述目标指令集合中与本第一目标方法的方法索引关联保存的目标指令。在该实施例中,指令替换也可以通过在目标指令集合中进行匹配快速完成,提高了处理效率。
基于与方法同样的发明构思,本申请实施例提供一种计算机设备,包括处理器和存储器;存储器用于存储执行各个方法实施例所述方法的程序;处理器被配置为执行存储器中存储的程序。
本申请实施例提供的计算机设备,对应用程序的字节码文件中的第一目标方法进行方法内联处理,即删除该第一目标方法,将调用该第一目标方法的方法调用指令替换为该第一目标方法所包括的目标指令,并将第一目标方法访问的字段和/或方法的访问权限修改为“公开”,通过这种处理实现对字节码文件的压缩,进而达到对应用程序的包体积进行压缩的目的。该计算机设备执行上述程序的过程中,先将方法内联过程中替换指令所需要的目标指令保存到目标指令集合中,在执行方法内联的过程中,不需要再次从字节码文件中查找目标指令,而是直接从目标指令集合中读取目标指令进行指令替换。由于目标指令集合中仅保存目标指令相关数据,其数据量远小于字节码文件,因此,直接从目标指令集合中读取目标指令的读取效率更高,从而提高方法内联的处理效率。
图3示出的是与本申请实施例提供的方法实施例相关的计算机设备的部分结构的框图。参考图3,计算机设备包括:
电源,通过电源管理系统与中央处理器逻辑相连,从而通过电源管理系统实现管理充电、放电、以及功耗管理等功能;主板,提供部件之间的电连接通路,各个部件通过主板进行电信号传输,各个部件通过插接、焊接等方式安装在主板上;中央处理器,主要包括算术逻辑运算单元(ALU,Arithmetic Logic Unit)、程序计数器(PC,Program Counter)、寄存器组、高速缓冲存储器(Cache)以及用于传输数据、控制及状态的总线(Bus)接口;内存储器、磁盘(即上述保存有执行各个方法实施例所述方法的程序的存储器)、输入单元(包括鼠标、键盘、触控面板等)、显示单元(包括显示器和显卡)和网卡通过总线与中央处理器进行数据交换。
执行各个方法实施例所述方法的程序及相关的数据首先从磁盘中被读取到内存储器中,中央处理器从内存储器中读取并加载程序。
本领域技术人员可以理解,图3中示出的计算机设备结构并不构成对计算机设备的限定,可以包括比图示更多或更少的部件,或者组合某些部件,或者不同的部件布置。
基于与方法同样的发明构思,本申请实施例提供一种计算机可读存储介质,存储有执行第一方面各个实施例所述方法的程序。
本申请实施例提供的计算机可读存储介质,对应用程序的字节码文件中的第一目标方法进行方法内联处理,即删除该第一目标方法,将调用该第一目标方法的方法调用指令替换为该第一目标方法所包括的目标指令,并将第一目标方法访问的字段和/或方法的访问权限修改为“公开”,通过这种处理实现对字节码文件的压缩,进而达到对应用程序的包体积进行压缩的目的。程序执行过程中,先将方法内联过程中替换指令所需要的目标指令保存到目标指令集合中,在执行方法内联的过程中,不需要再次从字节码文件中查找目标指令,而是直接从目标指令集合中读取目标指令进行指令替换。由于目标指令集合中仅保存目标指令相关数据,其数据量远小于字节码文件,因此,直接从目标指令集合中读取目标指令的读取效率更高,从而提高方法内联的处理效率。
本说明书是参照根据本说明书实施例的方法、设备(系统)、和计算机程序产品的流程图和/或方框图来描述的。应理解可由计算机程序指令实现流程图和/或方框图中的每一流程和/或方框、以及流程图和/或方框图中的流程和/或方框的结合。可提供这些计算机程序指令到通用计算机、专用计算机、嵌入式处理机或其他可编程数据处理设备的处理器以产生一个机器,使得通过计算机或其他可编程数据处理设备的处理器执行的指令产生用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的设备。
这些计算机程序指令也可存储在能引导计算机或其他可编程数据处理设备以特定方式工作的计算机可读存储器中,使得存储在该计算机可读存储器中的指令产生包括指令设备的制造品,该指令设备实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能。
这些计算机程序指令也可装载到计算机或其他可编程数据处理设备上,使得在计算机或其他可编程设备上执行一系列操作步骤以产生计算机实现的处理,从而在计算机或其他可编程设备上执行的指令提供用于实现在流程图一个流程或多个流程和/或方框图一个方框或多个方框中指定的功能的步骤。
尽管已描述了本说明书的优选实施例,但本领域内的技术人员一旦得知了基本创造性概念,则可对这些实施例作出另外的变更和修改。所以,所附权利要求意欲解释为包括优选实施例以及落入本说明书范围的所有变更和修改。
显然,本领域的技术人员可以对本说明书进行各种改动和变型而不脱离本说明书的精神和范围。这样,倘若本说明书的这些修改和变型属于本说明书权利要求及其等同技术的范围之内,则本说明书也意图包含这些改动和变型在内。