Dex Annotation Optimization for Baidu APP Android Package
In the second part of Baidu’s APK‑size‑optimization series, the team uses the Titan‑Dex framework to strip unnecessary build‑type and system Dex annotations—such as generic signatures and class‑relationship metadata—while automatically generating a whitelist via custom Lint detectors, ultimately shrinking the final Dex by about 1.2 MB.
This article is the second part of the Baidu APP Android package size‑optimization series. It focuses on optimizing Dex annotations to reduce APK size.
Annotations in Java (introduced in Java 5) can be retained in the bytecode. In Dex files, many compile‑time annotations (e.g., generic signatures) and system annotations (class‑relationship information) are unnecessary for runtime execution and can be removed.
Annotation lifecycle classification
Three RetentionPolicy levels are described:
RetentionPolicy.SOURCE – discarded after source compilation.
RetentionPolicy.CLASS – kept in the .class file but removed by the JVM.
RetentionPolicy.RUNTIME – kept in the class file and available at runtime.
Dex annotation visibility classification
Annotations are divided into three visibility groups:
Build annotations (compile‑time only, e.g., .annotation build Landroid/annotation/SuppressLint; )
System annotations – generic signature ( Ldalvik/annotation/Signature ) and class‑relationship annotations such as Ldalvik/annotation/MemberClasses , Ldalvik/annotation/InnerClass , Ldalvik/annotation/EnclosingClass , Ldalvik/annotation/EnclosingMethod .
Example of a generic‑signature annotation in smali:
.field public jsonObjectList:Ljava/util/List;
.annotation system Ldalvik/annotation/Signature;
value = {
"Ljava/util/List<",
"Lorg/json/JSONObject;",
">;"
}
.end annotation
.end fieldExample of class‑relationship annotations for an inner class:
.class public Lcom/baidu/searchbox/OuterClass$InnerClass;
.super Ljava/lang/Object;
# annotations
.annotation system Ldalvik/annotation/EnclosingClass;
value = Lcom/baidu/searchbox/OuterClass;
.end annotation
.annotation system Ldalvik/annotation/InnerClass;
accessFlags = 0x1
name = "InnerClass"
.end annotationOptimization target
The goal is to remove all build‑type annotations and system annotations that are not required by the app. The removable types include all build annotations and system annotations such as Signature, MemberClasses, InnerClass, EnclosingClass, and EnclosingMethod, unless the class is whitelisted.
Implementation using Titan‑Dex
Titan‑Dex, Baidu’s open‑source Dalvik/ART bytecode manipulation framework, is used to traverse Dex classes, methods, and fields, inspect each DexAnnotation, and delete those that match the removal rules. The core visitor logic is shown below:
override fun visitClass(dcn: DexClassNode) {
val outDexClassNode = DexClassNode(dcn.type, dcn.accessFlags, dcn.superType, dcn.interfaces)
// traverse class, method, field annotations
dcn.accept(object : DexClassVisitor(outDexClassNode.asVisitor()) {
override fun visitAnnotation(annotationInfo: DexAnnotationVisitorInfo): DexAnnotationVisitor? {
return if (removeAnnotation(annotationInfo, dcn.type.toTypeDescriptor())) null else super.visitAnnotation(annotationInfo)
}
// similar overrides for methods, fields, and parameter annotations
})
}
private fun removeAnnotation(annotationInfo: DexAnnotationVisitorInfo, classType: String): Boolean {
if (annotationInfo.visibility.name == ANNOTATION_TYPE_BUILD && optBuild) return true
if (!optSystem) return false
return when (annotationInfo.type.toTypeDescriptor()) {
ANNOTATION_SIGNATURE, ANNOTATION_INNERCLASS, ANNOTATION_ENCLOSINGMETHOD,
ANNOTATION_ENCLOSINGCLASS, ANNOTATION_MEMBERCLASS -> classType !in whiteListSet
else -> false
}
}A whitelist mechanism is provided so that classes which use reflection APIs to read annotation information (e.g., Gson.fromJson, Class.getGeneric… ) are excluded from removal.
Automated detection and whitelist generation
To avoid manual whitelist maintenance, three custom Android Lint detectors were created:
ClassShipUseDetector – scans for class‑relationship reflection calls.
SignatureUseDetector – scans for generic‑signature reflection calls.
EncapsulationDetector – scans for Gson.fromJson wrappers.
Based on lint results, five whitelist rule types are defined (superclass, annotation, package, classname, anonymous) and a Gradle plugin automatically generates the whitelist during the Transform phase. Example rules:
com.baidu.searchbox.net.update.v2.AbstractCommandListener#superclass
com.google.gson.reflect.TypeToken#superclass
com.google.gson.annotations.SerializedName#annotation
com.google.gson.**#package
com.alipay.**#package
com.baidu.FinalDb#classnameResult
The Dex annotation optimization reduces the final Dex size by approximately 1.2 MB, demonstrating the effectiveness of removing unnecessary annotations.
Baidu Geek Talk
Follow us to discover more Baidu tech insights.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.