首页 > 编程知识 正文

java软件安装包(java安装包打不开)

时间:2023-05-04 11:53:29 阅读:1085 作者:4600

文本/移动客户端开发工程师yedmy

在安卓版本的近几个版本中,包大小配额已经超标,采取了包括图像压缩、H5函数、无用代码去除等方法进行减包,但减包压力仍然很大。希望能从代码的角度减少一些包的大小,感觉有点压力。对Q安装包的反编译后的Dalvik字节码进行了一段时间的分析,发现通过调整Java代码可以减少编译后的Dalvik字节码,从而减少包的大小。我在这方面做了很多尝试,有成功的,也有失败的,所以拿出来和大家分享,多交流。

优化思想

通过dexdump反编译apk中的dex,得到对应的Dalvik字节码,找到冗余字节码,并尝试移除或替换冗余字节码。

目前主要是替换或删除原有的java代码,减少相应的Dalvik指令,从而减少安装包的大小。

现在我们主要是从Dalvik字节码分析来调整Java代码,然后我们希望可以通过ASM等框架直接调整字节码来减少当前的包大小。

优化效果

去掉初始化分配方案——3354,整手Q的释放包大小减少了约80k。

堆功能优化——-整手Q释放包尺寸缩小2k左右。

其他尝试方案,包括字符串拼接、去掉接口的很多空方法等。因为效果比较小,很难统一修改等。只需列出分析结果,如果有大量项目,可以尝试优化。

优化方案如下:

1.消除初始化分配的冗余。

1.1、问题分析:

静态变量由类的所有对象共享,并且在类加载的准备阶段(如下所示)将被初始设置为系统零值。例如,字符串的初始值设置为空,但它存在于类中。

这种赋值行为将在下面的cinit类构造函数方法中执行,反复将String A设置为null,添加相应cinit方法的Dalvik指令,这是不必要的,可以杀死。

在对象创建中完成成员的内存分配后,相应的内存空间将被初始设置为系统零值(与静态变量相同),例如,int类型被设置为0并且存在于类中。

public int B=0;

这种赋值行为会在后续的init对象构造方法中执行,反复将int B设置为0,在对应的init方法中加入Dalvik指令,这是不必要的,可以杀死。

对于系统赋予默认零值的静态变量和成员变量,去掉初始化赋值,直接使用系统赋予的系统零值,可以减少cinit和init中的Dalvik指令,从而减小包的大小,提高类加载和对象创建的效率。

1.2、优化要点

注意静态最终变量必须赋初始值;

接口的变量都是静态的最终类型;

注意,只有系统给定的赋值为零的静态变量和成员变量才能用这种方式进行优化,其他问题如局部变量的变化会导致编译失败。

1.3.冗余的例子:

对应的字节码:

优化后:

对应的字节码:

减少了两行达尔维克指令的执行。最后,分析结果的平均优化可以减少安装包约8字节。

1.4.优化结果:

目前在手办Q6.3.0的分支上使用自编的过滤脚本就可以看到优化效果(对应的项目可以私底下找我要对应的优化脚本)。如果对整手Q实施这个方案,估计可以优化80k左右,修改4677个文件,冗余17164个。

2.调整与桩插入相对应的代码。

qzone补丁包引入了插桩的步骤,需要在Qzone类的所有构造函数中添加对mqq.app.MobileQQ类的引用。

的优化方案是,将存根插入对象构造函数的语句包括

代替

以Qzone中一个类的init为例,它由原始字节码组成

成为

3ae882e0c4c?from=pc">

这里替换一处代码,将System.out.print改成getName,可以减少对象构造函数的一行Dalvik指令,替换了1314处初始化函数中插入的代码,最终将对应的qzone_plugin.apk减少了2459字节,整个手q减少2457字节左右。<font color=#FF0000>一行代码,2k收益</font>,其实还是很划算的。

3、字符串拼接

下面是我针对String拼接的特殊情况“变量+”””和“””+变量”的不同形式举例分析Dalvik字节码。

字节码

从示例中可以看出各类字符串拼接方式的优劣,如果用String.valueOf绝对是最优方案。只是通过对“变量+”””和“””+变量”的形式在手q整个项目调整以后大概能够优化6k左右,如果只是优化qzone部分,效果比较微小,脚本方面不太好过滤对应情况,暂时没有加入,只是做了下试验。

PS:其实“String +”一般来说比StringBuffer的拼接更费字节码,这个部分可以自行验证,前提是a+b+…的形式中首位a这个为变量,而不是常量,如果a是常量,则实际上和StringBuffer等同,这也是个优化点,具体可以参考文章 从字节码视角看java字符串的拼接 。

4、调整interface到class,减少实现接口造成的空方法

很多代码中实现接口时有很多的空方法,并没有作用但还是会占用字节码,希望能够通过调整对应的interface为class,去除冗余的空方法,减少字节码,从而减少包大小。

示例如下:

改成

该方案的缺点在于修改必须手动,难度大,qzone中场景不足以引起量变,而且因为Qzone中<init>中还加入了插桩函数的负担,所以整体优化效果不佳,优化完qzone才2k不到的大小缩减,优化难度高收益小,弃坑。

这些减包思路希望能够给一起在减包路上踩坑的朋友们一些帮助吧。

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。