Automated Patch Generation for the Robust Android Hot‑Update System
The open‑source Robust hot‑update system now includes an automated patch‑generation tool that scans original methods, rewrites field and method accesses to reflective calls, and creates hook classes to overcome ProGuard’s obfuscation, optimization, and inner‑class challenges, cutting patch creation time from a day to minutes.
We announced that the Robust hot‑update system is now open‑source at https://github.com/Meituan-Dianping/Robust .
Robust implements a real‑time hot‑update mechanism inspired by Instant Run. At the entry of a method it inserts a jump to a patch method; if a bug is detected the patch code is executed, otherwise the original method runs.
Initially patches were created manually, which could take a whole day and became a bottleneck. An automated patch‑generation tool was therefore built and is now part of the open‑source repository.
Automation Principle
The tool generates patch code by scanning the original method body and converting field accesses and method calls to reflective calls, because many members become inaccessible after ProGuard obfuscation.
Original Java method:
public int multiple(int number) {
if (number < 0) {
return -1;
}
number = changeInputs(number);
return times * number;
}
public int changeInputs(int number) {
return number * 2;
}After Robust instrumentation:
public static ChangeQuickRedirect changeQuickRedirect;
public int multiple(int number) {
if (changeQuickRedirect != null) {
if (PatchProxy.isSupport(new Object[]{new Integer(number)}, this, changeQuickRedirect, false, 627)) {
return ((Integer) PatchProxy.accessDispatch(new Object[]{new Integer(number)}, this, changeQuickRedirect, false, 627)).intValue();
}
}
if (number < 0) {
return -1;
} else {
number = this.changeInputs(number);
return this.times * number;
}
}
// this method is not processed by Robust
public int changeInputs(int number) {
return number * 2;
}Example of an automatically generated patch that modifies multiple(int) to handle negative numbers without the original if check:
SampleClass originClass;
public int multiple(int number) {
Object var5 = ((SampleClassPatch) this).originClass;
Object[] var6 = new Object[]{new Integer(number)};
int var8 = ((Integer) EnhancedRobustUtils.invokeReflectMethod("b", var5, var6, new Class[]{Integer.TYPE}, SampleClass.class)).intValue();
Log.d("robust", "invoke method is No: 19 changeInputs");
number = var8;
Object var9 = ((SampleClassPatch) this).originClass;
int var7 = ((Integer) EnhancedRobustUtils.getFieldValue("c", var9, SampleClass.class)).intValue();
Log.d("robust", "get value is times No: 20");
return var7 * number;
} EnhancedRobustUtilsis a helper that wraps Java reflection to invoke methods or get field values on obfuscated classes.
Implementation Details
Automating patch generation faces three major challenges caused by ProGuard:
Mapping consistency (applymapping).
ProGuard optimization that changes method signatures, removes methods, or inlines code.
Obfuscation of inner classes and synthetic members.
1. applymapping – Using a fixed mapping file can keep class and member names stable, but in practice the mapping may diverge between builds, making patches unreliable.
2. No‑op (minimal changes) – Keeping build changes tiny (e.g., only modifying method bodies) can preserve mapping, but any addition of new classes or methods may still break the mapping.
3. DIY approach – The team built a multi‑stage pipeline:
For fields/methods that become inaccessible, the patch makes them public via byte‑code manipulation before reflection.
When ProGuard renames inner‑class constructors, the patch forces the constructor to be public and reflects it directly.
Inline methods that disappear after optimization are re‑created in a separate “inline hook” class; the original call sites are rewritten to invoke the hook.
Example of an inner class generated by the Java compiler:
public class Sample {
public int multiple(int number) {
Children pair = new Children("1");
pair.setFirst("asdad");
number = changeInputs(number);
return times * number;
}
class Children {
private String first = null;
private Children(String fir) {
this.first = fir;
setFirst("1");
}
public void setFirst(String fir) {
this.first = fir;
}
}
}After compilation the synthetic constructor Children(Sample, String, Sample$1) appears, and ProGuard may rename or remove it. The patch therefore makes the constructor public and accesses it via reflection.
ProGuard can also inline methods or change signatures, causing the original method to disappear. The solution is to generate a “hook” class that contains a stub of the inlined method, rewrite the call site to the hook, and later fill the stub with the original implementation.
Pitfalls Encountered
Java compiler‑generated bridge methods and lambda synthetic methods that lose annotations required for patching.
ProGuard’s aggressive optimization that removes or renames members, leading to reflection failures.
Multiple levels of inlining that can create circular dependencies.
Summary
Automating Robust patch generation is far more complex than it appears. The team tackled ProGuard’s obfuscation, optimization, and inlining by combining reflection, byte‑code rewriting, and hook classes. The resulting tool can now reliably generate patches for a wide range of code styles, dramatically reducing the time from a day to a few minutes.
Robust and its automated patch tool are available at https://github.com/Meituan-Dianping/Robust . Contributions and feedback are welcome.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Meituan Technology Team
Over 10,000 engineers powering China’s leading lifestyle services e‑commerce platform. Supporting hundreds of millions of consumers, millions of merchants across 2,000+ industries. This is the public channel for the tech teams behind Meituan, Dianping, Meituan Waimai, Meituan Select, and related services.
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.
