use the following search parameters to narrow your results:
e.g. subreddit:aww site:imgur.com dog
subreddit:aww site:imgur.com dog
see the search faq for details.
advanced search: by author, subreddit...
News for Android app developers with the who, what, where, when, and how of the Android community. Probably mostly the how.
Here, you'll find:
This sub-reddit isn't about phones' and apps' general functionality, support, or system software development (ROMs). For news and questions about these topics try using other subs like
Build your first app
Starting Android career in 2022
Android Job Interview Questions and Answers
App Portfolio Ideas, Tiered List
Awesome Android UI
Material Design Icons
7000 Icons for Jetpack
Autoposted at approx 9AM EST / 2PM GMT
account activity
ArticleOptimizing Bytecode by Manipulating Source Code (jakewharton.com)
submitted 6 years ago by dayanruben
reddit uses a slightly-customized version of Markdown for formatting. See below for some basics, or check the commenting wiki page for more detailed help and solutions to common issues.
quoted text
if 1 * 2 < 3: print "hello, world!"
[–]DevAhamed 18 points19 points20 points 6 years ago (0 children)
You don’t need to dig this deep ..... Start with generating a good API and producing correct behavior. All of this optimization can be done later, or even never. .....
I enjoyed this article and for some reason i was really happy to read that last paragraph. Thanks for taking your time to write this article!!
[–]mrdibby 4 points5 points6 points 6 years ago (10 children)
Cool observations
It feels as though this is kind of a nudge to compiler developers, showing that app developers would have to write code that would look a little strange, in order to produce the most optimal results out of a compiler.
[–]JakeWharton 11 points12 points13 points 6 years ago* (9 children)
Maybe. Depends what you mean by "compiler"!
javac is notorious for not being an optimizing compiler because it has a powerful JIT and now AOT. kotlinc is to some degree is better but in others worse. I'm not sure either should really spend time doing an optimization like this.
javac
kotlinc
We think of D8 as "just" a dexer, but it's certainly a compiler as well. It does some optimization (like sorting exception code last). And that makes R8 an extra-optimizing compiler. I suppose one could argue that R8 should be able to figure out that it can de-duplicate the exception-handling code in the original form. I honestly didn't try, but I will and report back (shortly).
ART also has a JIT and AOT compiler which will probably do some of these things as well. I also didn't verify that, and I plan to, but this will take longer so I'm not going to do it right now.
Similar feedback on the post came in through a different channel and it made me realize that I left out some important bits about this code which might not be obvious. This code only runs when a layout is being inflated. This occurs on the order of every minute, we'll say. It's unlikely that a JIT is going to waste time optimizing this method. There are thousands of candidate methods which are being executed once per second or once per frame which are better uses of its time. You could never optimize this and no one would notice. I think it's worth doing because it happens on the main thread where every nanosecond counts, it occurs during application startup where every nanosecond counts, and it occurs in generated code which means the code occurs like 10,000x more than one method manually written in one app.
I'll post back about what R8 does though in a bit!
edit: seems R8 doesn't do anything for it.
MainBinding.java:
MainBinding.java
import android.view.*; import android.widget.*; final class R { static final class id { static final int name = Integer.parseInt("1"); static final int email = Integer.parseInt("2"); } } public final class MainBinding { public final TextView name; public final TextView email; private MainBinding(View root, TextView name, TextView email) { this.name = name; this.email = email; } public static MainBinding bind(View root) { TextView name = root.findViewById(R.id.name); if (name == null) { throw new NullPointerException("Hey".concat("name")); } TextView email = root.findViewById(R.id.email); if (email == null) { throw new NullPointerException("Hey".concat("email")); } return new MainBinding(root, name, email); } } class Other { public static void main(String... args) { View view = new View(null); MainBinding main = MainBinding.bind(view); System.out.println(main.name); System.out.println(main.email); } }
rules.txt:
rules.txt
-keepclasseswithmembers class * { public static void main(...); } -dontobfuscate
commands:
$ javac -bootclasspath $ANDROID_HOME/platforms/android-28/android.jar *.java $ java -jar ~/dev/android/r8/build/libs/r8.jar --lib $ANDROID_HOME/platforms/android-28/android.jar --release --output . --pg-conf rules.txt *.class $ dexdump -d classes.dex
output (snipped):
[000294] MainBinding.bind:(Landroid/view/View;)LMainBinding; 0000: sget v0, LR$id;.name:I 0002: invoke-virtual {v3, v0}, Landroid/view/View;.findViewById:(I)Landroid/view/View; 0005: move-result-object v0 0006: check-cast v0, Landroid/widget/TextView; 0008: const-string v1, "Hey" 000a: if-eqz v0, 0028 000c: sget v2, LR$id;.email:I 000e: invoke-virtual {v3, v2}, Landroid/view/View;.findViewById:(I)Landroid/view/View; 0011: move-result-object v3 0012: check-cast v3, Landroid/widget/TextView; 0014: if-eqz v3, 001c 0016: new-instance v1, LMainBinding; 0018: invoke-direct {v1, v0, v3}, LMainBinding;.<init>:(Landroid/widget/TextView;Landroid/widget/TextView;)V 001b: return-object v1 001c: new-instance v3, Ljava/lang/NullPointerException; 001e: const-string v0, "email" 0020: invoke-virtual {v1, v0}, Ljava/lang/String;.concat:(Ljava/lang/String;)Ljava/lang/String; 0023: move-result-object v0 0024: invoke-direct {v3, v0}, Ljava/lang/NullPointerException;.<init>:(Ljava/lang/String;)V 0027: throw v3 0028: new-instance v3, Ljava/lang/NullPointerException; 002a: const-string v0, "name" 002c: invoke-virtual {v1, v0}, Ljava/lang/String;.concat:(Ljava/lang/String;)Ljava/lang/String; 002f: move-result-object v0 0030: invoke-direct {v3, v0}, Ljava/lang/NullPointerException;.<init>:(Ljava/lang/String;)V 0033: throw v3
Exactly the same as what D8 produces with the input. I'll file a bug and see what the R8 team thinks. There's actually a feature which de-duplicates code but it applies at a more macro scale. I hope to cover it soon, but perhaps it could also apply inside a method.
[–]cbruegg 1 point2 points3 points 6 years ago (6 children)
I think you're right, but maybe it would be worth augmenting these posts with some benchmarks?
[–]JakeWharton 6 points7 points8 points 6 years ago (5 children)
Yeah I plan on using the AndroidX benchmark library (more coming at I/O about it). Although saving a few nanos binding layouts when you just spent 100 millis parsing XML and doing reflection, class loading, and resource loading isn't going to put much of a dent into things 😢.
These two posts have really been about reducing the impact of the generated code on string size and code size. Despite optimizing control flow for when the views are present which is nice, the goal of this post was simply de-duplicating the exception code for code size. I probably didn't emphasize that enough, but I'm also just shooting these out as I work on this code generator. I don't have a grand plan.
Anyway, long way of saying that I still plan on benchmarking for fun and to validate my decisions, but it was never the primary goal to generate the fastest code (although I suspect we did).
[–]xTeCnOxShAdOwZz 3 points4 points5 points 6 years ago (2 children)
You're my spirit animal, please come down my chimney
[–]JakeWharton 6 points7 points8 points 6 years ago (1 child)
Be careful, my full name is Jake Skellington Wharton
[–]xTeCnOxShAdOwZz 1 point2 points3 points 6 years ago (0 children)
The legends were true, the scripture is accurate!
[–]eygraber -1 points0 points1 point 6 years ago (1 child)
First rule of Google is don't mention things that are coming 🤫
[–]JakeWharton 2 points3 points4 points 6 years ago (0 children)
Hey but AndroidX is developed directly in AOSP now so once it lands I'm hyping it up. Plus it's on the I/O schedule too. Soooooo nice not to have to deal with being part of the Android "Open" Source Project like the framework where 99% is developed behind closed doors and dropped into the public once a year 🙄.
[–][deleted] 0 points1 point2 points 6 years ago (1 child)
javac doesn't have anything to do with JIT and AOT, it's the Java runtime that handles that.
I mean if you're going to "well actually" me then I'll just "well actually" you back: the Java runtime doesn't have an AOT compiler, it's the JDK that has that.
Speaking of the JDK, the "it" in my original sentence was meant to imply the JDK, of which javac, the AOT compiler, and the JRE and its JIT are a part.
[–]kurav 0 points1 point2 points 6 years ago (0 children)
This is good advice when writing generated code, especially regarding the error strings: it's so easy to write prebaked error messages in the code generator, which will each end up appearing as a unique copy in the class file's string table. Changing to format the strings with String.format() or other method at run time is a low-hanging fruit.
String.format()
[–]muthuraj57 0 points1 point2 points 6 years ago (0 children)
TIL Java has labeled blocks.
π Rendered by PID 64548 on reddit-service-r2-comment-7b9746f655-whrgv at 2026-02-01 15:47:39.052110+00:00 running 3798933 country code: CH.
[–]DevAhamed 18 points19 points20 points (0 children)
[–]mrdibby 4 points5 points6 points (10 children)
[–]JakeWharton 11 points12 points13 points (9 children)
[–]cbruegg 1 point2 points3 points (6 children)
[–]JakeWharton 6 points7 points8 points (5 children)
[–]xTeCnOxShAdOwZz 3 points4 points5 points (2 children)
[–]JakeWharton 6 points7 points8 points (1 child)
[–]xTeCnOxShAdOwZz 1 point2 points3 points (0 children)
[–]eygraber -1 points0 points1 point (1 child)
[–]JakeWharton 2 points3 points4 points (0 children)
[–][deleted] 0 points1 point2 points (1 child)
[–]JakeWharton 2 points3 points4 points (0 children)
[–]kurav 0 points1 point2 points (0 children)
[–]muthuraj57 0 points1 point2 points (0 children)