前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >减包-删除无用的代码

减包-删除无用的代码

作者头像
Helloted
发布2022-06-08 10:27:14
1.4K0
发布2022-06-08 10:27:14
举报
文章被收录于专栏:Helloted

一、减包的措施

1、资源:
  • 无用资源的删除
  • 重复文件的删除
  • 大文件压缩
  • 图片管理方式规范
  • on-Demand Resource动态下载

1.1. 删除无用图片

使用开源工具 LSUnusedResources 检查重复图片,但是可能会有误报,比如 [@”image%d”, index] 这种引用方式无法检查到,需要人工在核对一边。

1.1.1重复文件删除

借助 fdupes 这个开源工具,校验各资源的 MD5。

1.2. 图片文件压缩

使用开源工具 imageOptim 对所有图片压缩一遍。此工具会使用 git 上主流的图片压缩方法尝试一遍,选择最优方案。

1.3. 纯色图片使用代码生成

如果项目中纯色的图片比较多,可以考虑使用代码替代,生成后缓存到本地以供后期使用。

1.4. 不常用图片后台下发

对于项目中不常用的图片可以考虑由后台下发,但是此项收益可能不高,而且会影响使用体验,酌情使用。

1.5. 字体文件

字体文件一般都很大,如果项目中使用了多种字体文件,可以删掉不常用的字体文件。

2、编译选项处理
  • Generate Debug Symbols 设置为NO,设置成NO就不会在断点处停下。减少符号生成,这个待确认。
  • 舍弃架构armv7和armv7s,去除不必要的指令集
  • DEAD_CODE_STRIPPING = YES(好像默认就是YES)。 确定 dead code(代码被定义但从未被调用)被剥离,去掉冗余的代码
  • Optimization Level有几个编译优化选项,release版应该选择Fastest, Smalllest[-Os],这个选项会开启那些不增加代码大小的全部优化,并让可执行文件尽可能小。
  • Strip Debug Symbols During Copy 和 Symbols Hidden by Default 在release版本应该设为yes,可以去除不必要的调试符号。Symbols Hidden by Default会把所有符号都定义成”private extern”,设了后会减小体积。
  • Strip Linked Product:DEBUG下设为NO,RELEASE下设为YES,用于RELEASE模式下缩减app的大小;

二、Mach-o简介

Mach-O 为 Mach Object 文件格式的缩写,它是一种用于可执行文件、目标代码、动态库、内核转储的文件格式。作为 a.out 格式的替代,Mach-O 提供了更强的扩展性,并提升了 符号表 中信息的访问速度。

MachO 是一种文件规范,是一类文件的统称,包括但不限于以下几种常见的文件类型:

  • .o(目标文件)
  • .a(静态库文件 )
  • .dylib(动态库文件 )
  • .framework(库文件)
  • .dSYM(XCode 调试符号文件)
  • 可执行文件(没有扩展名)
  • dyld(动态链接器,一个特殊的可执行文件)
MachO 查看工具:OTool 与 MachOView:
  • OTool 是 macOS 自带的 MachO 文件查看工具,基于命令行,可以通过不同的命令参数快速地查看 MachO 文件各个方面的信息,OTool 位于(/Library/Developer/CommandLineTools/usr/bin/otool)
  • MachOView 是一款开源的 MachO 文件查看工具,基于图形界面,它为查看和编辑(基于 Intel 和 ARM 架构的)MachO 文件提供了完整的解决方案
1、Header

Header是文件的头部信息,包括CPU信息、文件类型、Command条数及Size信息。总体来说,作为开发者Header使用的较少,比较常用的是(uintptr_t)&_mh_execute_header获取header地址进行计算用。

2、Commands

Load Commands描述的是文件的加载信息,加载信息有很多,加载的段、符号表、动态库信息等都在Commands中取到。这个部分信息还是比较有用的,我们可以从这里获取到符号表和字符串表的偏移量

3、Data

Header 区域主要用于存储 MachO 文件的一般信息,并且描述了 LoadCommands 区域 而 LoadCommands 区域则详细描述了 Data 区域 如果说 Header 区域和 LoadCommands 区域的主要作用是:

  1. 让系统内核加载器知道如何读取 MachO 文件
  2. 并指定动态链接器来完成 MachO 文件后续的动态库加载
  3. 然后设置好程序入口等一些列程序启动前的信息

那么,Data 区域的作用,就是当程序运行起来后,为每一个映射到虚拟内存中的指令操作提供真实的物理存储支持

Data 区域通常是 MachO 文件中最大的部分,主要包含:代码段、数据段,链接信息等 注意:不要把 Data 区域与数据段搞混掉了,Data 区域指的是广义上的数据,而不是特指数据段的数据

Section

用途

__TEXT.__text

主程序代码,存放的是汇编后的代码

__TEXT.__cstring

C 语言字符串

__TEXT.__const

const 关键字修饰的常量

__TEXT.__stubs

用于 Stub 的占位代码,很多地方称之为桩代码。

__TEXT.__stubs_helper

当 Stub 无法找到真正的符号地址后的最终指向

__TEXT.__objc_methname

Objective-C 方法名称

__TEXT.__objc_methtype

Objective-C 方法类型

__TEXT.__objc_classname

Objective-C 类名称

__DATA.__data

初始化过的可变数据

__DATA.__la_symbol_ptr

lazy binding 的指针表,表中的指针一开始都指向 __stub_helper

__DATA.nl_symbol_ptr

非 lazy binding 的指针表,每个表项中的指针都指向一个在装载过程中,被动态链机器搜索完成的符号

__DATA.__const

没有初始化过的常量

__DATA.__cfstring

程序中使用的 Core Foundation 字符串(CFStringRefs)

__DATA.__bss

BSS,存放为初始化的全局变量,即常说的静态内存分配

__DATA.__common

没有初始化过的符号声明

__DATA.__objc_classlist

Objective-C 类列表

__DATA.__objc_protolist

Objective-C 原型

__DATA.__objc_imginfo

Objective-C 镜像信息

__DATA.__objc_selfrefs

Objective-C self 引用

__DATA.__objc_protorefs

Objective-C 原型引用

__DATA.__objc_superrefs

Objective-C 超类引用

三、利用Otool工具查找无用代码

OTool 是 macOS 自带的 MachO 文件查看工具,基于命令行,可以通过不同的命令参数快速地查看 MachO 文件各个方面的信息,OTool 位于(/Library/Developer/CommandLineTools/usr/bin/otool)

1、所有方法
代码语言:javascript
复制
 “otool - ov $path”将输出Objective - C类结构及其定义的方法。

通过匹配可以和筛选,可以将获取所有的方法,除了setter and getter方法…

代码

代码语言:javascript
复制
def imp_selectors(path):
    re_sel_imp = re.compile('\s*imp\s*0x\w+ ([+|-]\[.+\s(.+)\])')
    re_properties_start = re.compile('\s*baseProperties 0x\w{9}')
    re_properties_end = re.compile('\w{16} 0x\w{9} _OBJC_CLASS_\$_(.+)')
    re_property = re.compile('\s*name\s*0x\w+ (.+)')
    imp_sels = {}
    is_properties_area = False

    for line in os.popen('/usr/bin/otool -oV %s' % path).readlines():
        results = re_sel_imp.findall(line)
        if results:
            (class_sel, sel) = results[0]
            if sel in imp_sels:
                imp_sels[sel].add(class_sel)
            else:
                imp_sels[sel] = set([class_sel])
        else:
            # delete setter and getter methods as ivar assignment will not trigger them
            # 删除相关的set方法
            if re_properties_start.findall(line):
                is_properties_area = True
            if re_properties_end.findall(line):
                is_properties_area = False
            if is_properties_area:
                property_result = re_property.findall(line)
                if property_result:
                    property_name = property_result[0]
                    if property_name and property_name in imp_sels:
                        # properties layout in mach-o is after func imp
                        imp_sels.pop(property_name)
                        # 拼接set方法
                        setter = 'set' + property_name[0].upper() + property_name[1:] + ':'
                        # 干掉set方法
                        if setter in imp_sels:
                            imp_sels.pop(setter)
    return imp_sels
2、引用的方法
代码语言:javascript
复制
otool -v -s __DATA __objc_selrefs $path
3、找出未引用代码

所有代码与引用的代码的差集即为未使用代码

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、减包的措施
    • 1、资源:
      • 2、编译选项处理
      • 二、Mach-o简介
        • MachO 查看工具:OTool 与 MachOView:
          • 1、Header
            • 2、Commands
              • 3、Data
              • 三、利用Otool工具查找无用代码
                • 1、所有方法
                  • 2、引用的方法
                    • 3、找出未引用代码
                    相关产品与服务
                    文件存储
                    文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档