Mobile Development 14 min read

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.

Baidu Geek Talk
Baidu Geek Talk
Baidu Geek Talk
Dex Annotation Optimization for Baidu APP Android Package

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 field

Example 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 annotation

Optimization 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#classname

Result

The Dex annotation optimization reduces the final Dex size by approximately 1.2 MB, demonstrating the effectiveness of removing unnecessary annotations.

AndroidBytecodeDexlintAnnotation OptimizationTitan-DexWhitelist
Baidu Geek Talk
Written by

Baidu Geek Talk

Follow us to discover more Baidu tech insights.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.