Android 컴파일 최적화를 위한 Confusion 구성

Android 컴파일 최적화를 위한 Confusion 구성

안드로이드 컴파일 최적화

배경

java8 및 후속 새 버전의 Java 기능을 사용하기 위해 Google은 컴파일 프로세스에 디슈가링(desugaring) 단계를 추가했지만 이 단계는 컴파일 시간이 더 길어질 것이므로 Google은 D8 및 R8 컴파일러를 다음과 같이 출시했습니다. 컴파일 속도를 최적화하십시오.

데슈가란?

디슈가링은 문법적 수준에서 기본 바이트코드가 지원하지 않는 일부 기능을 컴파일 단계에서 기본 바이트코드 구조로 변환하는 것입니다(예: List의 제네릭 유형은 실제로 디슈가링 후 바이트코드 수준에서 객체임). Java8 구문 기능을 디슈가링하는 프로세스는 다채롭다고 할 수 있습니다. 물론 궁극적인 목표는 동일합니다. 즉, 모든 장치에서 새 구문을 실행하는 것입니다.

D8

D8의 기능은 Java 바이트 코드를 dex 코드로 변환하는 것이며 D8은 DX의 대안입니다. 컴파일 과정은 아래 그림과 같습니다.
D8

Android Studio 버전 3.1부터 D8이 기본 Dex 컴파일러로 사용됩니다. D8을 닫으려면 gradle.properties에 다음 구성을 추가할 수 있습니다.

android.enableD8=false
android.enableD8.desugaring=false

D8을 켤 때의 이점

  • 더 빠르고 짧은 시간에 컴파일
  • DEX는 컴파일할 때 더 적은 콘텐츠를 차지합니다.
  • .dex 파일이 더 작음
  • D8에 의해 컴파일된 .dex 파일은 동일하거나 더 나은 성능을 가집니다.

프로젝트에서 이미 Java 8을 사용하여 D8 컴파일을 최대한 활성화한 경우 컴파일 오류가 발생할 수 있습니다.

R8

원래 Proguard 압축 및 최적화(축소, 축소, 최적화) 부분을 대체하는 R8은 여전히 ​​Proguard와 동일한 유지 규칙을 사용하며 차세대 코드 압축 도구입니다. R8은 이전에 D8+Proguard 형태로 구축되었으며, R8은 난독화 및 D8 도구를 통합하여 구축 시간을 단축하고 출력 apk의 크기를 줄입니다.

R8

Gradle 플러그인 버전이 3.4.0 이상이 되면 R8은 기본적으로 코드 최적화를 시작합니다. R8을 활성화하지 않으려면 gradle.properties다음 구성을 추가할 수 있습니다.

android.enableR8=false

R8을 켜면 얻을 수 있는 이점

  • 코드 감소: 64 참조 한계 우회
  • 리소스 절감: 사용하지 않는 리소스 제거
  • 난독화된 코드: DEX 파일 크기 줄이기
  • 코드 최적화: DEX 파일 크기 추가 축소

참고:

https://developer.android.google.cn/studio/build/shrink-code

관련 평가 보고서
D8R8 평가 보고서

AS 다중 모듈 혼동 구성

AS 다중 모듈에서 각 모듈의 개별 구성 방법을 채택할 수 있습니다. 즉, proguard 파일은 각 모듈 아래에 구성되고 각 build.gradle 파일에 도입됩니다. A 폴더에 있는 각 모듈의 proguard 파일을 가져온 다음 앱 모듈에 있는 종속 모듈의 proguard 파일을 중앙에서 가져옵니다.
앱 모듈 cmcc_service를 예로 들어 설명하겠습니다.

buildTypes {
    
    
        release {
    
    
            minifyEnabled true //开启混淆
            shrinkResources true //无用资源去除
            zipAlignEnabled true
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'),'proguard-rules.pro',
                    '../proguardDefine/common-rules.pro', '../proguardDefine/live_lib-rules.pro',
                    '../proguardDefine/gs_api_adapter-rules.pro', '../proguardDefine/cmcc_service.pro',
                    '../proguardDefine/lib_voiceassistant-rules.pro','../proguardDefine/cmcc_softprobe-rules.pro'
            if (propertyHaveSigningConfigs)
                signingConfig signingConfigs.release
        }
}

그 중 proguard-android-optimize.txt안드로이드가 기본으로 설정한 일반적인 난독화 규칙, proguard-rules.pro앱 코드의 난독화 규칙, proguardDefine폴더 아래 종속 모듈이 일률적으로 배치되는 proguard위치 등이 있습니다.

참고: 가져온 3자 라이브러리는 일반적으로 해당 proguard 파일이 장착되어 있으므로 구성을 반복할 필요가 없습니다.gradle을 컴파일할 때 관련 파일 proguard 파일이 하나의 파일로 병합
됩니다 configuration.txt.
구성 위치

proguard-android-optimize.txt

# 禁用一些代码简化和优化,以及字段和类合并
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
# 运行优化 passes 的数量为 5,数值越高,混淆效果越好,但耗时也更长
-optimizationpasses 5
# 允许访问和修改保护代码
-allowaccessmodification

# 不允许使用大小写混合的类名
-dontusemixedcaseclassnames
# 不跳过非公共库类
-dontskipnonpubliclibraryclasses
# 详细输出
-verbose

# 保留一些反射所需的属性
-keepattributes *Annotation*,Signature,InnerClasses,EnclosingMethod
# 保留以下三个类及其公共成员
-keep public class com.google.vending.licensing.ILicensingService
-keep public class com.android.vending.licensing.ILicensingService
-keep public class com.google.android.vending.licensing.ILicensingService
# 忽略以下类,不输出 note 信息
-dontnote com.android.vending.licensing.ILicensingService
-dontnote com.google.vending.licensing.ILicensingService
-dontnote com.google.android.vending.licensing.ILicensingService

# 对于本地方法,参见 http://proguard.sourceforge.net/manual/examples.html#native
# 保留包含 native 方法的类和方法
-keepclasseswithmembernames,includedescriptorclasses class * {
    
    
    native <methods>;
}
# 保留公共的 View 子类的 set 和 get 方法
# 以便于使用属性动画
-keepclassmembers public class * extends android.view.View {
    
    
    void set*(***);
    *** get*();
}
# 保留 Activity 中可用于 XML 属性 onClick 中的方法
-keepclassmembers class * extends android.app.Activity {
    
    
    public void *(android.view.View);
}
# 对于枚举类,参见 http://proguard.sourceforge.net/manual/examples.html#enumerations
# 保留枚举类成员
-keepclassmembers enum * {
    
    
    public static **[] values();
    public static ** valueOf(java.lang.String);
}
# 保留实现 Parcelable 接口的类的 CREATOR 静态成员
-keepclassmembers class * implements android.os.Parcelable {
    
    
    public static final ** CREATOR;
}
# 保留 JavaScript 接口方法上的注解
-keepclassmembers class * {
    
    
    @android.webkit.JavascriptInterface <methods>;
}
# 支持库包含对新平台版本的引用
# 在应用链接旧版平台版本时,不要发出警告,因为它们是安全的
-dontnote android.support.**
-dontnote androidx.**
-dontwarn android.support.**
-dontwarn androidx.**
# 该类已弃用,但仍然保留用于向后兼容
-dontwarn android.util.FloatMath
#这段混淆规则用于保护使用了@Keep注解的类和成员不被混淆,以及忽略特定的冗余类。
-keep class android.support.annotation.Keep
-keep class androidx.annotation.Keep
#保留使用了@Keep注解的类和接口的所有成员
-keep @android.support.annotation.Keep class * {
    
    ;}
-keep @androidx.annotation.Keep class * {
    
    ;}
#保留使用了@Keep注解的类的方法
-keepclasseswithmembers class * {
    
    
@android.support.annotation.Keep <methods>;
}
-keepclasseswithmembers class * {
    
    
@androidx.annotation.Keep <methods>;
}
#保留使用了@Keep注解的类的字段
-keepclasseswithmembers class * {
    
    
@android.support.annotation.Keep <fields>;
}
-keepclasseswithmembers class * {
    
    
@androidx.annotation.Keep <fields>;
}
#保留使用了@Keep注解的类的构造方法
-keepclasseswithmembers class * {
    
    
@android.support.annotation.Keep <init>(...);
}
-keepclasseswithmembers class * {
    
    
@androidx.annotation.Keep <init>(...);
}
#忽略特定的冗余类
#android.jar和org.apache.http.legacy.jar中的类重复
-dontnote org.apache.http.**
-dontnote android.net.http.**
#android.jar和core-lambda-stubs.jar中的类重复
-dontnote java.lang.invoke.**

일부 타사에는 자체 난독화 규칙이 있습니다.

configuration.txt이러한 규칙은 파일 retrofit2 난독화 규칙 에도 병합됩니다.

# The proguard configuration file for the following section is /home/cl/.gradle/caches/transforms-3/29b6aa006718d6829551a18646bf70bb/transformed/rules/lib/META-INF/proguard/retrofit2.pro
# Retrofit does reflection on generic parameters. InnerClasses is required to use Signature and
# EnclosingMethod is required to use InnerClasses.
-keepattributes Signature, InnerClasses, EnclosingMethod

# Retain service method parameters when optimizing.
-keepclassmembers,allowshrinking,allowobfuscation interface * {
    
    
    @retrofit2.http.* <methods>;
}

# Ignore annotation used for build tooling.
-dontwarn org.codehaus.mojo.animal_sniffer.IgnoreJRERequirement

# Ignore JSR 305 annotations for embedding nullability information.
-dontwarn javax.annotation.**

# Guarded by a NoClassDefFoundError try/catch and only used when on the classpath.
-dontwarn kotlin.Unit

# Top-level functions that can only be used by Kotlin.
-dontwarn retrofit2.-KotlinExtensions

# End of content from /home/cl/.gradle/caches/transforms-3/29b6aa006718d6829551a18646bf70bb/transformed/rules/lib/META-INF/proguard/retrofit2.pro

RxJava2\RxAndroid 혼동 규칙

-dontwarn java.util.concurrent.Flow*

Okhttp3 난독화 규칙

# The proguard configuration file for the following section is /home/cl/.gradle/caches/transforms-3/af3ecb4c3ae4accf6423845d738f047d/transformed/rules/lib/META-INF/proguard/okhttp3.pro
# JSR 305 annotations are for embedding nullability information.
-dontwarn javax.annotation.**

# A resource is loaded with a relative path so the package of this class must be preserved.
-keepnames class okhttp3.internal.publicsuffix.PublicSuffixDatabase

# Animal Sniffer compileOnly dependency to ensure APIs are compatible with older versions of Java.
-dontwarn org.codehaus.mojo.animal_sniffer.*

# OkHttp platform used only on JVM and when Conscrypt dependency is available.
-dontwarn okhttp3.internal.platform.ConscryptPlatform

# End of content from /home/cl/.gradle/caches/transforms-3/af3ecb4c3ae4accf6423845d738f047d/transformed/rules/lib/META-INF/proguard/okhttp3.pro

더 많은 난독화 구성 가능

# 指定不去忽略非公共库的类
-dontskipnonpubliclibraryclasses
# 指定不去忽略非公共库的成员
-dontskipnonpubliclibraryclassmembers
# 混淆时不做预校验
-dontpreverify
# 忽略警告
-ignorewarnings
# 保留代码行号,方便异常信息的追踪
-keepattributes SourceFile,LineNumberTable
# appcompat库不做混淆
-keep class androidx.appcompat.**
#保留 AndroidManifest.xml 文件:防止删除 AndroidManifest.xml 文件中定义的组件
-keep public class * extends android.app.Fragment
-keep public class * extends android.app.Activity
-keep public class * extends android.app.Application
-keep public class * extends android.app.Service
-keep public class * extends android.content.BroadcastReceiver
-keep public class * extends android.content.ContentProvider
-keep public class * extends android.preference.Preference
-keep public class * extends android.view.View

#保留序列化,例如 Serializable 接口
-keepclassmembers class * implements java.io.Serializable {
    
    
    static final long serialVersionUID;
    private static final java.io.ObjectStreamField[] serialPersistentFields;
    private void writeObject(java.io.ObjectOutputStream);
    private void readObject(java.io.ObjectInputStream);
    java.lang.Object writeReplace();
    java.lang.Object readResolve();
}

#带有Context、View、AttributeSet类型参数的初始化方法
-keepclasseswithmembers class * {
    
    
    public <init>(android.content.Context);
}
-keepclasseswithmembers class * {
    
    
    public <init>(android.content.Context, android.util.AttributeSet);
}
-keepclasseswithmembers class * {
    
    
    public <init>(android.content.Context, android.util.AttributeSet, int);
}
-keepclassmembers class * extends android.app.Activity {
    
    
   public void *(android.view.View);
}

#保留资源R类
-keep class **.R$* {
    
    *;}

#避免回调函数 onXXEvent 混淆
-keepclassmembers class * {
    
    
    void *(**On*Event);
    void *(**On*Listener);
    void *(**on*Changed);
}

#业务实体不做混淆,避免gson解析错误
-dontwarn com.grandstream.convergentconference.entity.**
-keep class com.grandstream.convergentconference.entity.** {
    
     *;}

#Rxjava、RxAndroid,官方ReadMe文档中说明无需特殊配置
-dontwarn java.util.concurrent.Flow*
#okhttp3、okio、retrofit,jar包中已包含相关proguard规则,无需配置
#其他一些配置

Android.bp 혼동 구성

android_app {
    
    
    name: "MyApp",
    package_name: "com.example.myapp",
    srcs: ["java/**/*.java"],
    manifest: "AndroidManifest.xml",
    dex_preopt: {
    
    
        enabled: true,
    },
    apk_cert_permissions: [
        "android.permission.ACCESS_FINE_LOCATION",
        "android.permission.RECORD_AUDIO",
        "android.permission.READ_CONTACTS",
    ],
    certificates: ["platform"],
    resource_files: ["res/**/*"],
    enable_proguard: true,
    proguard_flags: ["proguard-android.txt"],
    dex_preopt_image_dir: "target/product/${TARGET_PRODUCT}/obj/dex_preopt_image",
}

이 중 enable_proguard는 true로 설정하여 코드 및 리소스 난독화를 활성화하고, proguard_flags는 Proguard 난독화 규칙 파일을 지정하며, 코드 및 리소스 난독화 규칙은 파일에서 지정할 수 있습니다.
resource_files는 AndroidManifest.xml 파일을 포함하여 애플리케이션의 리소스 파일을 지정합니다.

android.mk 혼동 구성

LOCAL_PROGUARD_ENABLED := obfuscation optimization

LOCAL_PROGUARD_FLAG_FILES := proguard.flags
ifeq (eng,$(TARGET_BUILD_VARIANT))
    LOCAL_PROGUARD_FLAG_FILES += proguard-test.flags
else
    LOCAL_PROGUARD_FLAG_FILES += proguard-release.flags
endif

LOCAL_PROGUARD_ENABLED몇 가지 구성이 있습니다.

  1. LOCAL_PROGUARD_ENABLED := disabled: 난독화를 비활성화합니다.
  2. LOCAL_PROGUARD_ENABLED := obfuscate: 최적화 없이 코드 난독화만 활성화합니다.
  3. LOCAL_PROGUARD_ENABLED := optimize: 최적화만 활성화하고 코드 난독화는 사용하지 않습니다.
  4. LOCAL_PROGUARD_ENABLED := obfuscate optimize: 코드 난독화와 최적화를 동시에 가능하게 합니다.

LOCAL_PROGUARD_FLAG_FILES기본적으로 빌드 시스템은 앱별 파일을 지정하기 위해 android-general 난독화 파일을 로드해야 합니다 proguard.
이러한 옵션을 구성하는 데 능숙하지 않은 경우 네이티브 애플리케이션의 난독화 구성을 확인할 수 있으며 이는 매우 고무적입니다.

난독화된 스택 복원

안드로이드의 내장 혼동 스택 복원 도구 proguardgui를 사용하여 해결

Android/Sdk/tools/proguard/bin$ ls
proguard.sh  proguardgui.sh  retrace.sh
/Android/Sdk/tools/proguard/bin$ ./proguardgui.sh

스크립트가 실행된 후 ProGuard 디버깅 인터페이스가 열립니다.
proguard GUI 도구

혼동 전후의 매핑 파일 mapping.txt와 복원해야 할 logcat 예외 로그를 ​​채우고 Retrace 버튼을 클릭하여 혼동 전에 예외 정보를 복원하십시오.

결론적으로

요컨대 Android는 이미 일반적인 난독화 규칙을 작성했습니다. 우리가 관심을 갖는 것은 우리가 직접 개발하는 코드 부분에 대한 난독화 규칙일 수 있습니다. 좋은 난독화 작업에는 더 안전한 코드, 더 작은 패키지 크기 및 더 빠른 작업과 같은 많은 이점이 있습니다
. 속도는 빠르지만 혼란도 예상하지 못한 비정상 동작을 불러오기 때문에 하루빨리 테스트를 잘 하시고 사용하시길 바랍니다.

참고

https://blog.csdn.net/Mr_dsw/article/details/90141647
https://blog.csdn.net/wwj_748/article/details/115874571
안드로이드 혼돈, 새로 선보인 D8과 R8으로 달라진 점은?
https://toutiao.io/posts/ijfhzkv/preview

추천

출처blog.csdn.net/u011897062/article/details/130603761