实现Android APK瘦身99.99%
摘要: 如何瘦身是 APK 的重要优化技术。APK 在安装和更新时都需要经过网络下载到设备,APK 越小,用户体验越好。本文作者通过对 APK 内在机制的详细解析,给出了对 APK 各组成成分的优化方法及技术,并实现了一个基本 APK 的最小化过程。
正文:
高尔夫运动中,分数最小者胜出。
让我们将这一原则应用到 Android App 开发中。我们将玩转一个称为“ApkGolf”的 APK,目的是创建一个尽可能具有最少字节数的 App,并可安装在运行 Oreo 的设备上。
基线测定
一开始,我们用 Android Studio 生成一个缺省的 App,创建密钥库(Keystore)
并对 App 签名,然后使用命令stat -f%z $filename
测定生成 APK 文件的字节数大小。
进一步,为确保该 APK 工作正常,我们将在一台运行 Oreo 的 Nexus 5x 手机上安装它。
看上去挺漂亮。但是现在我们的 APK 大小近乎 1.5Mb。
APK Analyser
考虑到我们 App 的功能非常简单,1.5Mb 的规模看上去过于臃肿了。因此,我们要深入了解一下该项目,看看是否有一些能立竿见影地削减文件大小的地方。Android Studio 生成了:
- 扩展
AppCompatActivity
而得到的MainActivity
; - 使用根视图
ConstraintLayout
的布局文件; - Value 文件,其中包含三种颜色、一个字符串资源(Resource)和一个主题(Theme);
AppCompat
和ConstraintLayout
的支持库;- 一个
AndroidManifest.xml
文件; - PNG 格式的启动图标,分别是正方形、圆形和前台的。
看上去首当其冲的目标是启动图标文件,因为 APK 中共包含了 15 个图像文件,并且在mipmap-anydpi-v26
下还有两个 XML 文件。下面,让我们使用 Android Studio 的 APK Analyser
(https://developer.android.com/studio/build/apk-analyzer.html)
对该 APK 文件做一个定量分析。
给出的结果与我们的最初假设大相径庭,其中显示 Dex 文件是大头,而上述资源仅占 APK 大小的 20%。
文件 | 大小占比 |
---|---|
classes.dex | 74% |
res | 20% |
resources.arsc | 4% |
META-INF | 2% |
AndroidManifest.xml | <1% |
下面让我们逐个分析每个文件的行为。
Dex 文件
看上去罪魁祸首是classes.dex
文件,它占据了 73% 的空间,因而它成为我们的首要削减目标。该文件为 Dex 格式
其中包含了我们的全部编译后代码,以及对 Android 框架和支持库中外部方法的引用。
然而android.support
软件包中引用了超过 13000 种的方法,对于一个简单的“Hello World”App 而言,完全没有必要。
资源
目录“res”中包含了大量的布局(Layout)文件、Drawable 和动画,它们并非在 Android Studio UI 中立刻可见。同样,它们也是由支持库推入其中的,约占 APK 规模的 20%。
在resources.arsc
文件中,还包含了对每个资源的引用。
签名
目录“META-INF
”中包含有CERT.SF
、MANIFEST.MF
和CERT.RSA
文件,这些文件都需要 v1 APK 签名
(https://source.android.com/security/apksigning/v2#v1-verification) 。
如果有攻击者修改了我们 APK 中的代码,签名就会不匹配。这一机制保障了用户能避免执行第三方恶意软件的风险。
在MANIFEST.MF
文件中列出了 APK 中的所有文件。其中,CERT.SF
文件中包含了文件清单的摘要,以及每个文件的独立摘要。CERT.RSA
文件中包含了一个公钥,用于验证CERT.SF
文件的完整性。
在签名文件中,没有目标明显可优化。
AndroidManifest 文件
看上去AndroidManifest
文件非常类似于我们的原始输入文件。唯一差别在于,文件中的字符串和 Drawable 等资源被整数资源 ID 所替代,这些 ID 以0x7F
开头。
启用最小化功能(Minification)
我们尚未在 App 的build.gradle
文件中设置允许最小化(Minification)和资源收缩(Resource Shrinking)。我们现在做此设置:
android {buildTypes {release {minifyEnabled trueshrinkResources trueproguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'}}
}
-keep class com.fractalwrench.** { *; }
将minifyEnabled
属性设置为“true”值,这将启用 Proguard
(https://www.guardsquare.com/en/proguard) ,
该功能将从 App 中剥离出那些未使用的代码,并对符号的名称做模糊化处理,使得 App 难以被反向工程。
设置shrinkResources
属性,将会在 APK 中移除任何并非直接引用的资源。这时如果我们使用反射机制间接地访问资源,就会导致问题,但是本文给出的 App 并不存在这样的问题。
优化为 786 Kb(削减 50%)
我们已经实现了 APK 规模减半,并未对我们的 APP 有任何可见的影响。
对于那些尚未在 App 中启用AndroidManifest.xml
和shrinkResources
的开发人员,这是本文给出的最需要重视的并应学会的技巧。他们仅花费数小时做配置和测试,就能轻松地削减数兆的规模。
我们尚未了解 AppCompat 的工作机制
现在classes.dex
文件已削减到占用 APK 的 57%。在我们的 Dex 文件中,大多数方法引用属于android.support
软件包,因此我们将要去除该支持库。具体做法为:
- 从
build.gradle
中彻底清除依赖块。 dependencies { implementation ‘com.android.support:appcompat-v7:26.1.0’ implementation ‘com.android.support.constraint:constraint-layout:1.0.2’ } - 更新
MainActivity
,以扩展android.app.Activity
。
public class MainActivity extends Activity
- 更新布局,使用单一的
TextView
。
<?xml version="1.0" encoding="utf-8"?>
<TextView xmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"android:text="Hello World!" />
- 删除
styles.xml
文件,并从AndroidManifest
文件的<application>
元素中移除android:theme
属性。 - 删除
colors.xml
文件。 - 在 gradle 同步时做 50 次上推(push-up)。
优化为 108 Kb(削减 87%)
天哪,我们刚刚实现了近十倍的削减,即从 786Kb 削减到 108Kb。唯一可见的更改是工具条(Toolbar)的颜色,现在它使用了缺省的 OS 主题。
目录“res”现在占用 APK 规模约 95%,原因是所有的加载图标。如果这些 PNG 图片是由我们自己的设计师所给出的,那么我们可以尝试 将它们转换为 WebP 格式,该格式更加高效,并被 API 15 及以上所支持。
幸运的是,Google 已经优化了我们的 Drawable。即便没有这种优化,ImageOptim 也可优化 PNG 并从中剥离不必要的元数据。
让我们当一次坏人,将我们所有的加载图标替换为单一的单像素黑点,并置于未验证的res/drawable
目录中。图片大小约 67 个字节。
优化为 6808 字节(削减 94%)
我们已经移除了几乎全部的资源,因此毫不奇怪 APK 规模已经削减了约 95%。但是resources.arsc
依然引用了如下项:
- 一个布局文件;
- 一个字符串资源;
- 一个调用图标。
让我们从第一项着手。
布局文件(优化为 6262 字节,削减 9%)
Android 框架会膨胀我们的 XML 文件
并自动创建一个TextView
对象,用于Activity
对象的contentView
。
我们可以尝试一些跳过中间的过程,具体做法是移除 XML 文件,并使用程序设置contentView
。这样会降低资源的规模,因为我们减少了一个 XML 文件。但是 Dex 文件将会增大,因为我们引用了额外的TextView
方法。
TextView textView = new TextView(this);
textView.setText("Hello World!");
setContentView(textView);
让我们查看一下这一权衡做法的工作情况,它削减了 5710 个字节。
App 名称(优化为 6034 字节,削减 4%)
下面我们将删除strings.xml
文件,并将AndroidManifest
中的android:label
属性值更改为“A”。这看上去是一个小更改,但是它从resources.arsc
中删除了一项,削减了 Manifest 文件中的字符数,并从“res”目录中移除了一个文件。略有裨益,我们削减了 228 个字节。
加载图标(优化为 5300 字节,削减 13%)
Android Platform 代码库中的resources.arsc
的文档
告诉我们,APK 中的每个资源通过resources.arsc
中的一个整数 ID 引用。这些 ID 具有两个命名空间(Namespace):
0x01: 系统资源(预装在 framework-res.apk 中);0x7f: 应用资源(捆绑在应用的.apk 文件中)。
那么如果在0x01
命名空间中引用了一个资源,我们的 APK 发生了什么?我们应该可以在削减文件规模的同时,得到一个更漂亮的图标。
android:icon="@android:drawable/btn_star"
虽然文档是这样说的,但是在一个生产 App 中,我们应该保持“永远不要信任系统资源”这一原则。该步骤会导致 Google Play 验证失败,而且考虑到我们知道某些制造商已经重定义了白色
因此在具体操作时需要慎重。
Manifest 文件(优化为 5252 字节,削减 1%)
目前为止,我们尚未对 Manifest 文件下手。
android:allowBackup="true"
android:supportsRtl="true"
移除这些属性将会削减 48 个字节。
防止破解(优化为 4984 字节,削减 5%)
看上去 Dex 文件中依然包括BuildConfig
和R
。
-keep class com.fractalwrench.MainActivity { *; }
如果我们精炼 Proguard 规则,就会清除掉这些类。
命名混淆(优化为 4936 字节,削减 1%)
现在对我们的Activity
赋予一个混淆后的名字。对于正常类,Proguard 可自动实现混淆功能,但是考虑到Activity
类名会通过Intents
唤醒,因此缺省情况下不要混淆Activity
的名字。
MainActivity -> c.javacom.fractalwrench.apkgolf -> c.c
META-INF(优化为 3307 字节,削减 33%)
当前在 App 签名中,我们使用了 v1 和 v2 签名。看上去这完全是浪费,尤其是 v2 会对整个 APK 做哈希,提供了更高级的保护能力和性能
(https://source.android.com/security/apksigning/#apk-signing-schemes)。
在 APK Analyser 中,v2 签名并不可见,因为它在 APK 文件本身中以二进制块的形式存在。v1 签名是可见的,它是以CERT.RSA
和 CERT.SF
文件的形式给出。
Android Studio UI 中提供了 v1 签名的复选框,我们需要去除该选择,并生成一个签名的 APK。我们也需要做相反的过程。
签名 | 大小(字节) |
---|---|
v1 | 3511 |
v2 | 3307 |
看上去从此以后我们使用的是 v2。
下面的操作将无需 IDE 的支持
现在我们要手工编辑我们的 APK 了。我们将使用如下命令:
# 1\. 创建一个未签名的 APK。
./gradlew assembleRelease# 2\. 解压缩归档文件。
unzip app-release-unsigned.apk -d app# 对文件进行编辑。# 3\. 压缩归档文件
zip -r app app.zip# 4\. 运行 zipalign。
zipalign -v -p 4 app-release-unsigned.apk app-release-aligned.apk# 5\. 使用 v2 签名运行 apksigner。
apksigner sign --v1-signing-enabled false --ks $HOME/fake.jks --out signed-release.apk app-release-unsigned.apk# 6\. 验证签名。
apksigner verify signed-release.apk
详细概述了 APK 签名过程。总而言之,gradle 生成了一个未签名的归档文件,zipalign 更改了未压缩资源的字节对齐方式,用于改进加载 APK 时的 RAM 使用,最后 APK 将被加密签名。
未签名且未对齐的 APK 大小为 1902 字节,这意味着签名和对齐过程增加了约 1 Kb。
文件大小差异(优化为 2608 字节,削减 21%)
很奇怪!我们对未对齐的 APK 解压缩并手工签名,并手动移除了META-INF/MANIFEST.MF
,这削减了 543 字节。如果有人知道原因,请告诉我!
现在我们的签名 APK 中只有三个文件,当然还可以去除resources.arsc
,因为我们并未定义任何资源!
这将使我们仅保留 Manifest 和classes.dex
文件,两个文件大小相当。
压缩破解(Compression Hack)(优化为 2599 个字节,削减 0.5%)
让我们将剩余的字符串都更改为‘c’,更新版本为 26,然后生成一个签名的 APK。
compileSdkVersion 26buildToolsVersion "26.0.1"defaultConfig {applicationId "c.c"minSdkVersion 26targetSdkVersion 26versionCode 26versionName "26"}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="c.c"><applicationandroid:icon="@android:drawable/btn_star"android:label="c"><activity android:name="c.c.c">
这将削减 9 个字节。
尽管文件中的字符数并未改变,但是我们更改了‘c’字符的频次。这使得压缩算法可以进一步降低文件的大小。
你好,ADB(优化到 2462 字节,削减 5%)
通过移除```Activity````的 Launch Intent Filter,我们可以进一步优化 Manifest。此后,我们将使用如下命令加载 App:
adb shell am start -a android.intent.action.MAIN -n c.c/.c
下面给出新的 Manifest 文件:
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="c.c"><application><activityandroid:name="c"android:exported="true" /></application>
</manifest>
我们还移除了加载图标。
削减方法引用(优化为 2179 字节,削减 12%)
我们最初需求是生成一个可安装在设备上的 APK。现在是运行“Hello World”的时候了。
我们的 App 引用了TextView
、Bundle
和Activity
中的方法。通过移除Activity
,并替换为用户定义的Application
类,我们可以进一步削减 Dex 文件大小。现在我们的 Dex 文件应该仅引用了单一的方法,即Application
的构造函数。
现在我们的源文件如下:
package c.c;
import android.app.Application;
public class c extends Application {}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"package="c.c"><application android:name=".c" />
</manifest>
我们可以使用 adb 验证该 APK 是可以成功安装的,也可以通过 Setting App 做验证。
Dex 优化(优化为 1961 字节,削减 10%)
在此次优化中,我花费了多个小时研究 Dex 文件格式
意在了解诸如校验码和偏移量等各种机制,它们是手工编辑文件中的难点。
但是长话短说,被我证实的是,只要存在classes.dex
文件,APK 文件就能安装。因此,只要简单地删除原始文件并在终端运行touch classes.dex
,使用这一空文件就能获得近 10% 的规模削减。
有时看上去最愚蠢的方法反而最有效。
理解 Manifest 文件(优化为 1961 字节,削减 0%)
非签名 APK 中的 Manifest 文件是二进制的 XML 格式,该格式看上去并没有官方的文档。我们可以使用 HexFiend编译器去修改文件内容
(https://github.com/ridiculousfish/HexFiend) 。
我们可以猜测出位于文件头部的数个感兴趣项。头四个字节编码了38
,是与 Dex 文件所使用的版本相同。随后的两个字节编码为660
,这无疑是文件的大小。
下面,我们尝试通过设置 targetSdkVersion 为1
并更新文件大小头部为659
,去删除一个字节。不幸的是,Android 系统拒绝了这个非法的 APK,因此看上去这里另有玄机。
无需理解 Manifest 文件(优化为 1777 字节,削减 9%)
下面我们让我们对整个文件输入虚字符,然后在不更改文件大小的情况下尝试安装 APK。这将确定校验码是否发挥作用,以及更改是否使得文件头部的偏移值失效。
令人惊奇的是,下图的 Manifest 文件被解释为一个有效的 APK,可运行在运行 Oreo 的 Nexus 5X 手机上:
我想我听到了负责维护BinaryXMLParser.java
的 Android Framework 工程师对着枕头在大声尖叫。
为最大化收益,我们将使用空字节(Null)替换这些虚字符。这可使简化使用 HexFiend 查看文件的重要部分,也将使前期的压缩破解可削减一些字节。
UTF-8 格式的 Manifest 文件
下图给出了一些 Manifest 文件中的重要成分。如果没有这些成分,APK 将会安装失败。
一些事情即刻是很明显的,例如 Manifest 文件和软件包标记。在字符串池中还可以找到软件包名称和 versionCode。
十六进制的 Manifest 文件
以十六进制查看文件可显示文件头部的值,这些值描述了字符串池及其它值,例如0x9402
是文件的大小。字符串也具有一种有意思的编码。如果字段超出了 8 个字节,它们的总长度将在随后的两个字节中指定。
但是,看上去我们并不能从中做更进一步的削减。
大功告成?(优化为 1757 字节,削减 1%)
让我们查看一下最终的 APK。
终归,我们使用 v2 签名在 APK 中留名。让我们创建一个利用压缩破解的新密钥库。
这可削减 20 个字节。
第五阶段:最终采纳
现在的1757
个字节是相当的小。据我所知,这是最小的现有 APK。
但是我完全有理由确信,Android 社区中会有人能再做进一步的优化,并打破我的记录。
更多Android进阶指南 可以扫码 解锁 《Android十大板块文档》

1.Android车载应用开发系统学习指南(附项目实战)
2.Android Framework学习指南,助力成为系统级开发高手
3.2023最新Android中高级面试题汇总+解析,告别零offer
4.企业级Android音视频开发学习路线+项目实战(附源码)
5.Android Jetpack从入门到精通,构建高质量UI界面
6.Flutter技术解析与实战,跨平台首要之选
7.Kotlin从入门到实战,全方面提升架构基础
8.高级Android插件化与组件化(含实战教程和源码)
9.Android 性能优化实战+360°全方面性能调优
10.Android零基础入门到精通,高手进阶之路
敲代码不易,关注一下吧。ღ( ´・ᴗ・` ) 🤔
相关文章:

实现Android APK瘦身99.99%
摘要: 如何瘦身是 APK 的重要优化技术。APK 在安装和更新时都需要经过网络下载到设备,APK 越小,用户体验越好。本文作者通过对 APK 内在机制的详细解析,给出了对 APK 各组成成分的优化方法及技术,并实现了一个基本 APK…...

webScoket长连接人性化解读
今天我们来整理一下webScoket,首先 webScoket是HTML5提出的一个基于TCP的一个全双工可靠通讯协议,处在应用层。很多人喜欢说webScoket是一次连接,这是误区,其实他是基于TCP的只不过将三次握手与四次挥手进行隐藏,封装。…...

ESDA in PySal (1) 利用 A-DBSCAN 聚类点并探索边界模糊性
ESDA in PySAL (1) 利用 A-DBSCAN 聚类点并探索边界模糊性 在本例中,我们将以柏林的 AirBnb 房源样本为例,说明如何使用 A-DBSCAN (Arribas-Bel et al., 2019)。A-DBSCAN 可以让我们做两件事: 识别高密度 AirBnb 房源集群并划定其边界探索这些边界的稳定性%matplotlib inli…...

利用GitHub实现域名跳转
利用GitHub实现域名跳转 一、注册一个 github账号 你需要注册一个 github账号,最好取一个有意义的名字,比如姓名全拼,昵称全拼,如果被占用,可以加上有意义的数字. 本文中假设用户名为 UNIT-wuji(也是我的博客名) 地址: https:/…...

【Linux详解】——共享内存
📖 前言:本期介绍共享内存。 目录 🕒 1. 共享内存的原理🕒 2. 共享内存的概念🕘 2.1 接口认识🕘 2.2 演示生成key的唯一性🕘 2.3 再谈key 🕒 3. 共享内存相关命令🕒 4. 利…...

Golang 几个不错的实用函数库
文章目录 samber/lothoas/go-funkduke-git/lancetelliotchance/piegookit/goutildablelv/cyan 大咖好呀,我是恋喵大鲤鱼。 Golang 标准库是 Go 语言自带的一组核心功能库,功能全面,易于使用。 在 Golang 标准库的基础上,还可以进…...

【Linux】地址空间概念
目录 前言: 地址空间回顾 验证:一个变量是否会有两个值? 一. 什么是地址空间 虚拟地址与物理地址之间的关系 二. 地址空间是如何设计的 1. 回答一个变量两个值 2.扩展 继续深入理解 三. 为什么要有地址空间 原因: 1. 使…...

视频集中存储/直播点播平台EasyDSS点播文件分类功能新升级
视频推拉流EasyDSS视频直播点播平台,集视频直播、点播、转码、管理、录像、检索、时移回看等功能于一体,可提供音视频采集、视频推拉流、播放H.265编码视频、存储、分发等视频能力服务。 TSINGSEE青犀视频的EasyDSS平台具有点播文件分类展示方法…...

JavaScript基础06——let和var两个关键字有啥不同
哈喽,小伙伴们大家好,我是雷工! 每日学习一点点,今天继续学习JavaScript基础知识,下面是学习笔记。 1、变量的本质 内存:计算机中存储数据的地方,相当于一空间。 变量的本质:是程序…...

Apache Doris 2.0.1 1.2.7 版本正式发布!
亲爱的社区小伙伴们,我们很高兴的宣布,2023 年 9 月 4 日 我们正式发布了 Apache Doris 2.0.1 和 Apache Doris 1.2.7 这两个版本,这两个版本由上百名位贡献者共同努力完成的,提供了更多有用的新特性,同时修复了若干已…...

YOLOv5算法改进(11)— 替换主干网络之EfficientNetv2
前言:Hello大家好,我是小哥谈。EfficientNetV2是一个网络模型,旨在提供更小的模型和更快的训练速度。它是EfficientNetV1的改进版本。EfficientNetV2通过使用更小的模型参数和采用一种称为Progressive Learning的渐进学习策略来实现这一目标。…...

Lombok讲解
Lombok是一个可以通过简单的注解形式来帮助我们简化消除一些必须有但显得很臃肿的Java代码的工具,如:getter、setter、equals、hashCode、toString等。 Lombok的常用注解有: Data:这是一个自定义注解,它相当于Getter…...

【Android】功能丰富的dumpsys activity
在Android中,要查看客户端Binder的连接数,可以通过dumpsys命令结合service参数来获取相关信息。请按照以下步骤进行操作: 连接到设备的计算机上,打开命令行终端。 使用adb shell命令进入设备的Shell环境。 执行以下命令来查看服…...

亚马逊云科技 云技能孵化营——我的云技能之旅
文章目录 每日一句正能量前言活动流程后记 每日一句正能量 不能在已经获得足够多的成功时,还对自己的能力保持怀疑,露出自信的微笑,走出自信的步伐,做一个自信的人! 前言 亚马逊云科技 (Amazon Web Services) 是全球云…...

南大通用数据库-Gbase-8a-学习-38-常规日志(general log)
目录 一、环境信息 二、general log的用途 三、general log相关参数介绍 四、LInux环境模拟实验 1、查看参数配置 2、开启general log 3、输入测试SQL 4、查看文件级别general log 5、改为表级别general log 6、再次输入测试SQL 7、查看gbase.general_log 一、环境信…...

汽车信息安全导图
尊敬的读者们,欢迎来到我的信息安全专栏。在这个专栏中,我将结合我在信息安全领域的开发经验,为大家深入浅出地讲解信息安全的重要性和相关知识点。 在数字化时代,信息成为了我们生活中不可或缺的一部分。我们的个人信息、交易数据、社交网络、公司机密等都以电子形式存储…...

【元宇宙】区块链,元宇宙最大化的驱动力
如今,一些观察者认为区块链是在结构上实现元宇宙的必要条件,而其他人则认为这种说法是荒谬的。人们对于区块链技术本身仍然有很多困惑,所以根本谈不上清楚地了解込块链技术与元宇宙的关系。所以,我们可以从区块链的定义开始介绍。…...

$ref属性的介绍与使用
在Vue.js中,$ref是一个特殊的属性,用于访问Vue组件中的DOM元素或子组件实例。它允许你直接访问组件内部的DOM元素或子组件,并且可以在需要时进行操作或修改。以下是有关$ref的详细介绍和示例演示,给大家做一个简单的介绍和概念区分…...

Holistic Evaluation of Language Models
本文是LLM系列文章,针对《Holistic Evaluation of Language Models》的翻译。 语言模型的整体评价 摘要1 引言2 前言3 核心场景4 一般指标5 有针对性的评估6 模型7 通过提示进行调整8 实验和结果9 相关工作和讨论10 缺失11 不足和未来工作12 结论 摘要 语言模型&a…...

android 布局 横屏 android横屏适配
一、刘海屏适配 1、layoutInDisplayCutoutMode属性 Android 9.0系统中提供了3种layoutInDisplayCutoutMode属性来允许应用自主决定该如何对刘海屏设备进行适配。 LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT 这是一种默认的属性,在不进行明确指定的情况下,系…...

北京已收录2023开学了《乡村振兴战略下传统村落文化旅游设计》中国建筑出版传媒许少辉八一新书
北京已收录2023开学了《乡村振兴战略下传统村落文化旅游设计》中国建筑出版传媒许少辉八一新书...

【Linux】Ubuntu20.04版本配置pytorch环境2023.09.05【教程】
【Linux】Ubuntu20.04版本配置pytorch环境2023.09.05【教程】 文章目录 【Linux】Ubuntu20.04版本配置pytorch环境2023.09.05【教程】一、安装Anaconda虚拟环境管理器二、创建虚拟环境并激活三、安装Pytorch四、测试pytorchReference 一、安装Anaconda虚拟环境管理器 首先进入…...

11 Python的正则表达式
概述 在上一节,我们介绍了Python的文件操作,包括:打开文件、读取文件、写入文件、关闭文件、文件指针移动、获取目录列表等内容。在这一节中,我们将介绍Python的正则表达式。正则表达式是一种强大的工具,用于在文本中进…...

关于工信部发布的app备案以及小程序备案流程
一、相关政策 通知:https://beian.miit.gov.cn/#/Integrated/lawStatute 腾讯备案:网站备案 首次备案-网站备案-文档中心-腾讯云 阿里备案:网站备案_ICP备案_备案迁移_备案-阿里云 二、遇到的问题 APP备案 安卓获取平台公钥方法…...

【高等数学基础知识篇】——不定积分
文章目录 一、不定积分的概念与基本性质1.1 原函数与不定积分的基本概念1.2 不定积分的基本性质 二、不定积分基本公式与积分法2.1 不定积分基本公式2.2 不定积分的积分法2.2.1 换元积分法2.2.2 分部积分法 三、两类重要函数的不定积分——有理函数与三角有理函数3.1 有理函数的…...

python使用鼠标在图片上画框
python rect.py 图片文件夹先左击左上角,再右击右下角,画出一个框结果保存在res文件夹rect.py import cv2, sys, ospathsys.argv[1] imcv2.imread(path) alos.listdir(path) al.sort() if not os.path.exists(res): os.makedirs(res)def getInfo(event,…...

算法通关村第十五关:青铜-用4KB内存寻找重复元素
青铜挑战-用4KB内存寻找重复元素 位运算在查找元素中的妙用 题目要求: 给定一个数组,包含从1到N的整数,N最大为32000,数组可能还有重复值,且N的取值不定,若只有4KB的内存可用,该如何打印数组中…...

SQL注入 - 宽字节注入
文章目录 SQL注入 - 宽字节注入宽字节注入前置知识宽字节靶场实战判断是否存在SQL注入判断位数判显错位判库名判表名判列名 SQL注入 - 宽字节注入 靶场 sqli - labs less-32 宽字节注入主要是绕过魔术引号的,数据库解析中除了UTF-8编码外的所有编码如:G…...

Flink基础
Flink architecture job manager is master task managers are workers task slot is a unit of resource in cluster, number of slot is equal to number of cores(超线程则slot2*cores), slot一组内存一些线程共享CPU when starting a cluster,job manager will allocate a …...

javaee spring aop 注解实现
切面类 package com.test.advice;import org.aspectj.lang.ProceedingJoinPoint; import org.aspectj.lang.annotation.*;//切面类 Aspect public class MyAdvice {//定义切点表达式Pointcut("execution(* com.test.service.impl.*.add(..))")public void pc(){}//B…...