减小ipa体积之删除frameWork中无用mach-O文件

首先我们来简单的介绍一下mach-O。

什么是mach-O?

Mach-O格式全称为Mach Object文件格式的缩写,是mac上可执行文件的格式,类似于windows上的PE格式 (Portable Executable ), linux上的elf格式 (Executable and Linking Format)。

上面第一个图是苹果给出的mach-O格式的示意图,而第二个图是我们使用machOView来分析某个可执行文件中的armv7的格式。可以看出他们两者的关系是对应的。

在machO这其中包含了很多的有效的信息,包括字符串,代码段,oc类,oc协议等各种的信息,利用这些信息我们也做到分析代码或者程序逻辑的作用,比如,下面这个数据就是我从这个machO文件里面导出来的,获取到了某个framework一个OC类中的所有基本元素。

那什么又是FatFile/FatBinary

简单来说,就是一个由不同的编译架构后的Mach-O产物所合成的集合体。例如上面我就只截取armv7的Mach-O格式座位示例, 而实际上常用的还有arm64/x86_64/i386等格式。

而实际上,包括我们使用的那些framework,大多数也是的。比如下图我们继续用machOView分析一下。 

可以看到arm64/armv7架构的存在。

FrameWork跟最终可执行文件的区别在哪里?

这里我们先随便写一个简单的framework, 在这个framework中我们实现了两个oc类,如下图所示:

紧接着我们干净用machOView来看看这个新鲜出炉的framework,可以看到该FrameWork在armv7的格式下,里面存在多个.o文件。

如果我们选择其中一个继续看看的话,你就会看到一个完整的Mach-O格式的文件。

由此我们可以得知frameWork也是另外一种情况的Mach-O集合体,是由多个不同的子mach-O文件所组合而成的,他们可以单独的拆开,而可执行文件则把同一架构下的所有Mach-O文件都进行了合并,他们不能拆开,如果想要更加清晰的定义的话,可以去研究一下苹果的定义,这里不做过多的阐述。

我们能做什么?

可能到这里你还有点乱,没关系,我们直接来拆开一个framework给大家看看!

到了这一步,我们就已经知道了我们能把FrameWork中的各个子Mach-O文件拆开, 那么我们能不能把这些Mach-O文件中有效的部分重新组装一下, 生成新的一个FrameWork呢?

这必须是可以的,但是其实最重要的关键是在于怎么去确定这个Mach-O文件有没有被我们的程序使用到。

怎么确定一个Mach-O有没有被使用到?

我们直接再来一个简单的demo,尝试一下

此时进行编译

成功.....

然后拆分老的framework文件, 删掉拆分得到的MachOClassA, 并且用剩下的mach-O文件合并生成一个新的framework, 替换到工程中去并进行编译

你没看错, 他确实是失败了, 如果在程序中代码直接使用了某些类或者某些方法, 而其mach-O文件不存在的情况下, 会导致编译不过(找不到对应的方法), 这也就是说, 我们能够使用最简单粗暴的方法来判断这个machO文件是不是被需要的!

不过, 需要注意的是, category的实现方式是不一样的,故如果我们删除了category的方法, 但是直接把Mach-o删除的话, 编译时是不会报错的。有兴趣的同学可以自己去看看oc中关于category的实现。

另外还有在程序运行中动态使用的performselector方法(可以通过查询字符串列表排除)。

下面是相关的流程图。

怎么把Mach-O的删除工具应用到XCode中去

现在我们已经通过编译的手段获得了一堆mach-O文件, 但是很多都是pod中引进的, 这个时候我们需要在代码编译器执行删除.o文件的脚本 刚好Xcode确实有这么一个地方可以设置

成果

在debug模式下大概减少了0.5M, 实际二进制文件减小大概1.2M, 如果计算到最终提交到苹果并且经过DRM加密后, 预计可以减小1M左右。

PS

  1. category是需要过滤的, 这货有点特别
  2. 删除找出来的.o文件之后, 可能会引起一些特殊的情况, 当然一般是crash, 因为有一些特别的代码他们用法并不是直接引用某个方法, 而是通过NSString相关的方法来获得Sel或者Class
  3. 把查找.o文件的操作放在本地, 而在编译器上进行编译的时候就直接执行删除, 不占用编译器的时间(我们的项目要使用六个小时以上的时间来进行查找)
  4. 建议进行操作再跑一遍回归测试, 确保各个功能模块正常

其他实践与猜想以及做过的尝试

  1. .o文件其实是可以直接引进到工程里面直接编译的, 也就是说其实可以把frameWork拆开, 然后加到工程中, 一样能够正常使用
  2. 一开始其实是想把.o文件中__text段中无用的函数进行删除, 但发现流程过于复杂, 而暂时放弃, 查找程序中无用函数的方法以后有机会再进行分享(如果这个成功的话, 估计会减小至少3~4M左右的ipa大小), 附上查找到的程序中无用方法结果的示例

 

  1. 其实看了上面那种方法之后, 我们紧接着又能想到, 暴力的将.m文件中的代码删除, 然后看看哪些工程中可见的代码是可以删除的(ps. 主要针对非framework, 另外也同样需要注意category以及performselector的问题, 需要配合查找字符串列表一起进行,
    或者手工进行判断)。
时间: 2024-10-20 04:47:23

减小ipa体积之删除frameWork中无用mach-O文件的相关文章

linux下rm命令删除文件名中包含特殊字符的文件【转】

转自:http://blog.itpub.net/143526/viewspace-1060083/ 1. 删除带"-"的文件名的方法 2. 删除包含其它特殊字符的文件 3. 删除系统打不出的乱码文件名 [@more@] 1. 删除带"-"的文件名的方法 大部分是由于误操作的原因,产生了一些 特殊字符的文件 如 -foo rm --help用法:rm [选项]... 目录...Remove (unlink) the FILE(s). -d, --directory 

如何删除Win8中无用的网络连接

  在使用Windows 8的过程中,有时会重复添加网络连接,虽然不影响正常使用,但是一长串无用的连接看起来很不顺眼.另外,一些默认的网络名称(如"网络 2"),既不直观也不好听.但是这些连接,是无法直接删除和改名的,我们只能借助注册表来完成. 单击系统托盘区的网络图标,在可用网络列表下查看当前正在使用的网络连接,例如zjggmxx-jwc2.然后按Win+R键调出运行对话框,输入regedit并按回车键,打开注册表编辑器,依次跳转到HKEY_LOCAL_MACHINESOFTWARE

如何删除Windows中正在运行的文件?

  方法1:关闭使用它的程序关闭 让我们从最显而易见的地方出发.你是不是刚刚用某个程序将文件打开,然后忘记关闭了呢?如果你把文件关了,但是程序还在运行,那就把程序也关掉,然后再试一下. 方法2:重启电脑 重启几乎是万金油,并且它很可能就能帮你解决掉这个问题!尽管这么做麻烦了点儿,但是它不要求任何技巧,也不需要你去摆弄任务管理器或者第三方的工具等玩意儿.重启还会清空你的内存,这样很可能还把其他的毛病捎带着给解决了.所以,如果你不想费心劳神去追究原因的话,就试试重启吧! 如果你已经试过重启了,而且仍

c#删除移动硬盘中$RECYCLE.BIN的文件、建立索引文件

  using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.IO; using System.Threading; namespace 为硬盘文件建立索引 {     public partial c

Android清除工程中无用资源文件的两种方法_Android

一.调用Android lint命令查找出没有用到的资源,并生成一个清单列表: 命令:lint –check "UnusedResources" [project_path] > result.txt 执行完之后会生成一个清单文件,内容如下: 二.使用代码自动删除无用的文件: public class DelAction { public static void main(String[] args) throws IOException { String projectPath

Android清除工程中无用资源文件的两种方法

一.调用Android lint命令查找出没有用到的资源,并生成一个清单列表: 命令:lint –check "UnusedResources" [project_path] > result.txt 执行完之后会生成一个清单文件,内容如下: 二.使用代码自动删除无用的文件: public class DelAction { public static void main(String[] args) throws IOException { String projectPath

Android Framework中添加AIDL文件编译

在framework中的 Android.mk文件中添加 ......           core/java/android/app/backup/IBackupManager.aidl \ core/java/android/app/backup/IRestoreObserver.aidl \ core/java/android/app/backup/IRestoreSession.aidl \ core/java/android/bluetooth/IBluetooth.aidl \ co

怎样删除XP系统中无用的动态链接

我们知道,占用内存的话就会对电脑系统的运行速度造成影响,尤其是那些配置比较低的电脑,对电脑系统比较了解的windows xp系统用户知道,系统的资源管理器经常在内存中留下动态链接,这些动态链接对我们是没有什么用处的,但是却占用了资源,影响到了系统的运行.那么如果遇到这种情况,我们应该怎么办呢?不用着急,下面小编就带大家一起来学习下xp系统如何卸载内存中无用的动态链接! 方法如下: 1.点击"开始"菜单,选择"运行"选项,在打开的对话框中输入"regedit

在.NET Framework中轻松处理XML数据(一)

xml|数据 在.NET Framework中,XmlTextReader和XmlTextWriter类提供了对xml数据的读和写操作.在本文中,作者讲述了XML阅读器(Reader)的体系结构及它们怎样与XMLDOM 和SAX 解释器结合.作者也演示了怎么样运用阅读器分析和验证XML文档,怎么样创建格式良好的XML文档,以及怎么样用函数读/写基于Base64和BinHex编码的大型的XML文档.最后,作者讲了怎么样实现一个基于流的读/写分析器,它把读写器都封装在一个单独的类里.大概三年前,