Mobile Development 18 min read

Bytecode and Reference Detection for Android Apps: Principles, Implementation, and Gradle Plugin

The article explains how bytecode‑level reference detection—implemented via a custom Gradle plugin that uses JavaAssist or ASM to scan compiled .class files for missing or inaccessible methods, fields, and classes—can automatically catch runtime‑crash‑inducing errors in large modular Android projects, offering configurable strict or warning modes to enhance build safety.

vivo Internet Technology
vivo Internet Technology
vivo Internet Technology
Bytecode and Reference Detection for Android Apps: Principles, Implementation, and Gradle Plugin

This article, authored by the Vivo official store client team, introduces the concept of Java bytecode and the need for bytecode‑level reference detection in large Android projects.

1. Java Bytecode – Java bytecode is the instruction format executed by the JVM. It can be inspected with javap -c -v xxx.class to view the compiled class file.

2. Bytecode Detection – After compiling .java or .kt files into .class files, the bytecode can be analyzed to detect missing method, field, or class references that would cause runtime crashes.

3. Background – The internal sales website (APP) consists of 12 independent sub‑modules, each compiled into AAR files. The architecture is layered into business, component, and framework layers, leading to complex inter‑module dependencies.

During development, scenarios were observed where a method or field was removed in a newer module version, causing Method Not Found or Field Not Found errors at runtime despite successful compilation.

4. Need for Automation – Manual testing cannot catch all reference problems. Traditional static analysis tools (FindBugs, Lint) cannot detect these runtime reference issues, so a custom automated detection tool is required.

5. Solution Overview – The proposed solution analyses compiled .class files during the Gradle build using bytecode manipulation libraries such as JavaAssist or ASM. A custom Gradle Transform (or plugin) scans each class for method calls, field accesses, and class references, checking for:

Deleted methods or mismatched signatures

Non‑public methods/fields accessed from unauthorized classes

Deleted or non‑public classes

If a problem is found, the build can either fail (strict mode) or log the error.

6. Implementation Example (Kotlin + JavaAssist)

// Gradle Plugin, custom Transform (simplified example)
// Method reference detection
classObj.declaredBehaviors.forEach { ctMethod ->
    ctMethod.instrument(object : ExprEditor() {
        override fun edit(m: MethodCall?) {
            super.edit(m)
            try {
                if (ctMethod.declaringClass.name.isNeedCheck()) return
                if (m == null) throw Exception("MethodCall is null")
                if (m.className.isNotWarn() || classObj.name.isNotWarn()) return
                // Detect missing method
                m.method.instrument(ExprEditor())
                // Visibility check
                if (!m.method.visibleFrom(classObj)) {
                    throw Exception("${m.method.name} is not visible from ${classObj.name}")
                }
            } catch (e: Exception) {
                errorInfo += "--Method analysis error: ${e.message}\n"
                isError = true
            }
        }
        override fun edit(f: FieldAccess?) {
            super.edit(f)
            try {
                if (f == null) throw Exception("FieldAccess is null")
                if (f.className.isNotWarn() || classObj.name.isNotWarn()) return
                val modifiers = f.field.modifiers
                if (!f.field.visibleFrom(classObj)) {
                    throw Exception("${f.field.name} is not visible from ${classObj.name}")
                }
            } catch (e: Exception) {
                errorInfo += "--Field analysis error: ${e.message}\n"
                isError = true
            }
        }
    })
}

Global variable initialization is also covered because static fields are placed in the class initializer ( clinit ) and instance fields in the constructor ( init ).

7. Class Reference Detection

// Class reference check (simplified)
if (classObj.packageName.isNeedCheck()) {
    classObj.refClasses?.forEach { refClassName ->
        try {
            if (refClassName.isNotWarn() || classObj.name.isNotWarn()) return@forEach
            val refClass = classPool.getCtClass(refClassName)
                ?: throw NotFoundException("Cannot find class: $refClassName")
            // Visibility check omitted for brevity
        } catch (e: Exception) {
            errorInfo += "--Class reference error: ${e.message}\n"
            isError = true
        }
    }
}

8. Independent Gradle Plugin – The detection logic is packaged as a standalone Gradle plugin that can be applied to any Android module. Configuration options include:

enable : turn detection on/off

strictMode : fail the build on detection

check : specify package prefixes to scan

notWarn : whitelist of packages/classes that should not raise errors

Example usage in build.gradle :

dependencies {
    classpath "com.byteace.refercheck:byteace-refercheck:35-SNAPSHOT"
}

apply plugin: 'com.byteace.refercheck'

referCheckConfig {
    enable true
    strictMode true
    check "com.abc.def"
    notWarn "org.apache.http,com.core.videocompressor.VideoController"
}

The plugin runs in about 2.3 seconds during the build, providing fast feedback without significantly increasing compile time.

9. Summary – Bytecode‑level reference detection is essential for large modular Android projects to prevent runtime crashes caused by missing methods, fields, or classes. By leveraging JavaAssist/ASM and integrating the logic into a Gradle Transform, developers gain automated, configurable checks that can halt CI builds when violations are found, improving overall code safety.

AndroidKotlinGradle Pluginbytecode analysisJavaassistreference detection
vivo Internet Technology
Written by

vivo Internet Technology

Sharing practical vivo Internet technology insights and salon events, plus the latest industry news and hot conferences.

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.