# R8

Published articles for R8.

This is one page of public article previews, not the complete archive. Follow Next page to continue. Summaries are not the original full articles.

## AI Can Write My Kotlin. Who's Going to Debug It at 2 AM?

DevFeed: [AI Can Write My Kotlin. Who's Going to Debug It at 2 AM?](<https://devfeed.tech/articles/ai-can-write-my-kotlin-who-s-going-to-debug-it-at-2-am-108418.md>)

Original publisher: [Read original article](<https://proandroiddev.com/ai-can-write-my-kotlin-whos-going-to-debug-it-at-2-am-a329bd3d7978?source=rss----c72404660798---4>)

Author: Mayank Kumar

Published: 2026-10-30T13:51:50Z

Content type: article

Language: en

Sources: [ProAndroidDev](<https://devfeed.tech/sources/proandroiddev-medium.md>)

Topics: [AI tools for developers](<https://devfeed.tech/topics/ai-tools-for-developers.md>), [human review](<https://devfeed.tech/topics/human-review.md>), [Code review](<https://devfeed.tech/topics/code-review.md>), [ai slop pull requests](<https://devfeed.tech/topics/ai-slop-pull-requests.md>), [Multi-step AI processes](<https://devfeed.tech/topics/multi-step-ai-processes.md>), [adb](<https://devfeed.tech/topics/adb.md>), [Crashlytics](<https://devfeed.tech/topics/crashlytics.md>)

Tags: [agent](<https://devfeed.tech/tags/agent.md>), [ai](<https://devfeed.tech/tags/ai.md>), [ai-tools](<https://devfeed.tech/tags/ai-tools.md>), [android](<https://devfeed.tech/tags/android.md>), [android-app-development](<https://devfeed.tech/tags/android-app-development.md>), [android-bench](<https://devfeed.tech/tags/android-bench.md>), [android-studio](<https://devfeed.tech/tags/android-studio.md>), [androiddev](<https://devfeed.tech/tags/androiddev.md>), [app-quality](<https://devfeed.tech/tags/app-quality.md>), [artificial-intelligence](<https://devfeed.tech/tags/artificial-intelligence.md>), [code](<https://devfeed.tech/tags/code.md>), [crashlytics](<https://devfeed.tech/tags/crashlytics.md>), [death](<https://devfeed.tech/tags/death.md>), [delivery](<https://devfeed.tech/tags/delivery.md>), [dora](<https://devfeed.tech/tags/dora.md>), [emulator](<https://devfeed.tech/tags/emulator.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [main-thread](<https://devfeed.tech/tags/main-thread.md>), [models](<https://devfeed.tech/tags/models.md>), [oem](<https://devfeed.tech/tags/oem.md>), [process](<https://devfeed.tech/tags/process.md>), [r8](<https://devfeed.tech/tags/r8.md>), [recomposition](<https://devfeed.tech/tags/recomposition.md>), [release](<https://devfeed.tech/tags/release.md>)

### AI overview

AI tools can write and debug Android code, but passing repository tests does not establish that a change works on a device. Android failures can depend on process death, OEM battery management, release-build R8, recomposition, or low-memory performance; benchmarks and tests cover only what they check. The article recommends making verification routine: test process death by killing and reopening the app, smoke-test critical flows on a minified release build, use a Macrobenchmark for startup or scrolling, keep agent changes small and inspect edited tests, and read Perfetto traces or heap dumps to check causes. Agents can speed up diagnosis, but developers remain responsible for validating fixes and owning releases. It also notes that Android 16's experimental AppFunctions lets apps expose agent-callable functions, whose KDoc descriptions and inputs require careful treatment.

### Source excerpt

Image by the author It's 2:07 AM, and Crashlytics has opinions. The crash is in a ViewModel that git blame says you wrote. You didn't. An agent did, and its pull request said "all tests pass." They do. The agent updated the expected values to match its new behaviour. That's a composite, not a confession. But it points at a real shift in Android work. This post covers what AI tools can do on Android today, why "the tests pass" is not the same as "it works" on a phone, and what to get better at. Short answer: AI can now write and fix Android code, but proving it works on a real device is still your job. What can AI tools do on Android today? Quite a lot. Android Studio's May 2026 release includes an agent that plans multi-step work and fixes its own build errors, "Fix with AI" for crashes in App Quality Insights, and an option to hand LeakCanary traces to an agent. Google also runs Android Bench, which gives models real issues from public Android repos and checks each fix with tests. At its March 2026 launch, models solved between 16% and 72% of tasks. So writing Android code is no longer the slow part. Checking it is. Why is "almost right" the expensive part? Because it compiles, looks fine in review, and fails later. In Stack Overflow's 2025 survey, 66% of developers named "AI solutions that are almost right, but not quite" as their top frustration. Google's DORA 2025 report found that AI adoption goes with higher delivery throughput, but it's still linked to less stable delivery. When changes get cheap to produce, teams produce more of them. The limit becomes how much change you can verify. Why is this harder on Android? Because an agent works on the repository, but Android correctness depends on the device at runtime. Image by the author Process death, OEM battery managers, R8 in release builds, unexpected recomposition, and main-thread work on low-memory devices rarely show up in a diff. Most don't show up on a flagship emulator either. Here's what "almost right"

## Grab Reduces ANRs by 32% and improves startup time by 35% with R8 and Profile guided optimization

DevFeed: [Grab Reduces ANRs by 32% and improves startup time by 35% with R8 and Profile guided optimization](<https://devfeed.tech/articles/grab-reduces-anrs-by-32-and-improves-startup-time-by-35-with-r8-and-profile-guided-optimization-90205.md>)

Original publisher: [Read original article](<https://developer.android.com/blog/posts/grab-r8-profile-guided-optimization-anr-startup-time>)

Author: Tracy Agyemang

Published: 2026-10-19T00:00:00Z

Content type: article

Language: en

Sources: [Android Developers](<https://devfeed.tech/sources/android-developers-blog.md>)

Topics: [R8](<https://devfeed.tech/topics/r8.md>), [app startup](<https://devfeed.tech/topics/app-startup.md>), [CI/CD](<https://devfeed.tech/topics/cicd.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [anr](<https://devfeed.tech/tags/anr.md>), [app-size](<https://devfeed.tech/tags/app-size.md>), [build-system](<https://devfeed.tech/tags/build-system.md>), [case-studies](<https://devfeed.tech/tags/case-studies.md>), [ci-cd](<https://devfeed.tech/tags/ci-cd.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [r8](<https://devfeed.tech/tags/r8.md>), [startup](<https://devfeed.tech/tags/startup.md>)

### AI overview

Grab describes optimizing its Android app with R8, Baseline Profiles, and Startup Profiles to reduce startup time, app size, and user-perceived ANRs. The case study outlines a phased migration, targeted keep-rule changes, and CI guardrails for preserving optimization gains.

### Source excerpt

Grab is Southeast Asia's leading superapp, offering deliveries, mobility, and financial services to millions of users across eight countries through a single app.

## R8 code shrinking now works with the Appwrite Android SDK

DevFeed: [R8 code shrinking now works with the Appwrite Android SDK](<https://devfeed.tech/articles/r8-code-shrinking-now-works-with-the-appwrite-android-sdk-66880.md>)

Original publisher: [Read original article](<https://appwrite.io/blog/post/android-sdk-r8-support>)

Author: Chirag Aggarwal

Published: 2026-10-07T00:00:00Z

Content type: article

Language: en

Sources: [Appwrite Blog](<https://devfeed.tech/sources/appwrite-blog.md>)

Topics: [Android](<https://devfeed.tech/topics/android.md>), [Appwrite](<https://devfeed.tech/topics/appwrite.md>), [IntelliJ IDEA](<https://devfeed.tech/topics/intellij-idea.md>)

Tags: [android-gradle-plugin](<https://devfeed.tech/tags/android-gradle-plugin.md>), [android-vitals](<https://devfeed.tech/tags/android-vitals.md>), [api](<https://devfeed.tech/tags/api.md>), [bugs](<https://devfeed.tech/tags/bugs.md>), [build](<https://devfeed.tech/tags/build.md>), [products](<https://devfeed.tech/tags/products.md>), [r8](<https://devfeed.tech/tags/r8.md>), [realtime](<https://devfeed.tech/tags/realtime.md>), [sessions](<https://devfeed.tech/tags/sessions.md>)

### AI overview

Appwrite Android SDK 29.0.0 adds support for R8 full mode, addressing release-build failures in query serialization, Realtime event handling, and saved sessions. The article explains the changes, upgrade requirements, and how to test shrinking in an app, including annotating application models that Gson populates with @Keep. The SDK ships consumer R8 rules and raises the minimum Android SDK version to 24.

### Source excerpt

Appwrite Android SDK 29.0.0 works with R8 full mode, fixing queries, Realtime, and saved sessions in release builds ahead of Google Play's 2027 DEX rule.

## Obfuscation Fundamentals: Applying ProGuard and R8 Protections to Android Code

DevFeed: [Obfuscation Fundamentals: Applying ProGuard and R8 Protections to Android Code](<https://devfeed.tech/articles/obfuscation-32342.md>)

Original publisher: [Read original article](<https://dustn.dev/page/presentations/2019-07-24-obfuscation-fundamentals/>)

Author: dustin@dustn.dev (Dustin Summers)

Published: 2026-09-17T04:13:15.404035Z

Content type: tutorial

Language: en

Sources: [Dustin Summers](<https://devfeed.tech/sources/dustin-summers.md>)

Topics: [obfuscation](<https://devfeed.tech/topics/obfuscation.md>), [Android](<https://devfeed.tech/topics/android.md>), [R8](<https://devfeed.tech/topics/r8.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [meetup](<https://devfeed.tech/tags/meetup.md>), [obfuscation](<https://devfeed.tech/tags/obfuscation.md>), [proguard](<https://devfeed.tech/tags/proguard.md>), [r8](<https://devfeed.tech/tags/r8.md>), [video](<https://devfeed.tech/tags/video.md>)

### AI overview

A presentation introducing obfuscation with ProGuard and R8, focused on applying protections to Android code. It explains how to diagnose the code entering and leaving these build tools.

### Source excerpt

This presentation was given at a MeetUp in DC. It corresponds to this series of blog posts, which is the first in a series to teach about Obfuscation/ProGuard/R8, and will primarily be centered around applying protections to Android Code. Tools such as R8 and ProGuard are available, but to many they are a black box that code goes into and stuff comes out. The following will demystify the black box, and teach developers how to properly diagnose the code going into and coming out of these build tools.

## Tinder cuts app cold starts by 47% with new R8 Configuration Analyzer

DevFeed: [Tinder cuts app cold starts by 47% with new R8 Configuration Analyzer](<https://devfeed.tech/articles/tinder-cuts-app-cold-starts-by-47-with-new-r8-configuration-analyzer-4241.md>)

Original publisher: [Read original article](<https://android-developers.googleblog.com/2026/08/tinder-app-cold-start-r8-configuration-analyzer.html>)

Author: Android Developers (noreply@blogger.com)

Published: 2026-08-18T18:00:00Z

Content type: article

Language: en

Sources: [Android Developers](<https://devfeed.tech/sources/android-developers-blog.md>)

Topics: [R8](<https://devfeed.tech/topics/r8.md>), [Android](<https://devfeed.tech/topics/android.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [configuration](<https://devfeed.tech/topics/configuration.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [agentic](<https://devfeed.tech/tags/agentic.md>), [android](<https://devfeed.tech/tags/android.md>), [development](<https://devfeed.tech/tags/development.md>), [errors](<https://devfeed.tech/tags/errors.md>), [obfuscation](<https://devfeed.tech/tags/obfuscation.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [r8](<https://devfeed.tech/tags/r8.md>), [startup](<https://devfeed.tech/tags/startup.md>), [time](<https://devfeed.tech/tags/time.md>)

### AI overview

The article describes how Tinder used the R8 Configuration Analyzer to identify and remove keep-rule blockers in its Android application. The effort reduced cold-start time by 47%, app download size by 28.98% to 61.5 MB, and user-perceived ANRs by 28%.

### Source excerpt

Posted by Ajesh R Pai, Developer Relations Engineer, Ulises Uriel Verduzco Diaz, Software Engineer, Tinder, and Tracy Agyemang, Product Marketing Manager Tinder is on a mission to power and inspire real connections by making meeting easy and fun for every new generation of singles. However, as their Android application codebase grew in size, so did its complexity. Prior to their latest optimization efforts, approximately 70% of the application was not optimized, carrying 17 dex files,including three dedicated just to startup. Although they had enabled R8, much of its optimization potential was blocked due to keep rules, and the team was unable to identify which specific rules were preventing optimization. To reduce startup time and decrease user-perceived Application Not Responding (ANR) errors, Tinder turned to the new R8 Configuration Analyzer to tackle these challenges. By utilizing the R8 Configuration Analyzer, Tinder successfully identified and removed unintentional optimization blockers. The results were immediate and impactful: Tinder achieved a 47% reduction in app cold starts, shrank their app download size by 28.98% (down to 61.5 MB), and reduced user-perceived ANRs by 28%. Configuration analyzer The R8 Configuration Analyzer shows R8 optimization by tracking shrinking, optimization, and obfuscation scores to show available refinement areas. It shows the broad, redundant, or obsolete keep rules, including those from external libraries so that you can analyse the keep rule impact and refine the keep rules. Key metrics shown in Configuration Analyzer include: Shrinking Score: Code percentage available for R8 shrinking. Optimization Score: Code percentage open to optimization (for example, method inlining, horizontal class merging). Obfuscation Score: Percentage of classes, methods and fields that can be renamed by R8 to decrease size. Use the analyzer to audit keep rules and their impacts: Find broad rules: Narrow the scope of package-wide rules that restri

## Tinder cuts app cold starts by 47% with new R8 Configuration Analyzer

DevFeed: [Tinder cuts app cold starts by 47% with new R8 Configuration Analyzer](<https://devfeed.tech/articles/tinder-cuts-app-cold-starts-by-47-with-new-r8-configuration-analyzer-88704.md>)

Original publisher: [Read original article](<https://developer.android.com/blog/posts/tinder-cuts-app-cold-starts-by-47-with-new-r8-configuration-analyzer>)

Author: Tracy Agyemang

Published: 2026-08-18T00:00:00Z

Content type: article

Language: en

Sources: [Android Developers](<https://devfeed.tech/sources/android-developers-blog.md>)

Topics: [IntelliJ IDEA](<https://devfeed.tech/topics/intellij-idea.md>), [CI/CD](<https://devfeed.tech/topics/cicd.md>)

Tags: [anr](<https://devfeed.tech/tags/anr.md>), [app-startup](<https://devfeed.tech/tags/app-startup.md>), [case-studies](<https://devfeed.tech/tags/case-studies.md>), [ci](<https://devfeed.tech/tags/ci.md>), [ci-cd](<https://devfeed.tech/tags/ci-cd.md>), [code](<https://devfeed.tech/tags/code.md>), [continuous-integration](<https://devfeed.tech/tags/continuous-integration.md>), [developers](<https://devfeed.tech/tags/developers.md>), [development](<https://devfeed.tech/tags/development.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

Tinder used the R8 Configuration Analyzer to identify a broad keep rule that was limiting optimization in its Android app. After refining the rule, the team reported 47% fewer slow cold starts, a 28.98% reduction in download size, and 28% fewer user-perceived ANRs. It also added optimization monitoring to its CI/CD pipeline.

### Source excerpt

Tinder is on a mission to power and inspire real connections by making meeting easy and fun for every new generation of singles.

## App Hardening: One Obfuscation Pipeline Across Every Port

DevFeed: [App Hardening: One Obfuscation Pipeline Across Every Port](<https://devfeed.tech/articles/app-hardening-one-obfuscation-pipeline-across-every-port-19196.md>)

Original publisher: [Read original article](<https://www.codenameone.com/blog/app-hardening-cross-platform/>)

Author: Shai Almog

Published: 2026-08-15T00:00:00Z

Content type: article

Language: en

Sources: [CodeName One](<https://devfeed.tech/sources/codename-one.md>)

Topics: [obfuscation](<https://devfeed.tech/topics/obfuscation.md>), [cross-platform](<https://devfeed.tech/topics/cross-platform.md>), [Encryption](<https://devfeed.tech/topics/encryption.md>), [Security](<https://devfeed.tech/topics/security.md>), [Reverse Engineering](<https://devfeed.tech/topics/reverse-engineering.md>), [App](<https://devfeed.tech/topics/app.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [app](<https://devfeed.tech/tags/app.md>), [cross-platform](<https://devfeed.tech/tags/cross-platform.md>), [encryption](<https://devfeed.tech/tags/encryption.md>), [hardening](<https://devfeed.tech/tags/hardening.md>), [ios](<https://devfeed.tech/tags/ios.md>), [javascript](<https://devfeed.tech/tags/javascript.md>), [native](<https://devfeed.tech/tags/native.md>), [obfuscation](<https://devfeed.tech/tags/obfuscation.md>), [platform](<https://devfeed.tech/tags/platform.md>), [r8](<https://devfeed.tech/tags/r8.md>), [reverse-engineering](<https://devfeed.tech/tags/reverse-engineering.md>), [security](<https://devfeed.tech/tags/security.md>)

### AI overview

Codename One App Hardening applies one pre-build protection pipeline to a merged cross-platform application before it is split into Android, iOS, JavaScript, Windows, Linux, and desktop builds. It supports renaming, eligible string encryption, selected control-flow transformations, verification, and crash-report retracing, while acknowledging that reverse engineering cannot be made impossible.

### Source excerpt

Codename One App Hardening applies class and member renaming, string encryption, and platform-safe control-flow transforms before one application becomes Android, iOS, JavaScript, or native desktop output.

## How R8 made Kotlin Coroutines on Android 2x faster

DevFeed: [How R8 made Kotlin Coroutines on Android 2x faster](<https://devfeed.tech/articles/how-r8-made-kotlin-coroutines-on-android-2x-faster-4227.md>)

Original publisher: [Read original article](<https://android-developers.googleblog.com/2026/07/how-r8-made-kotlin-coroutines-2x-faster.html>)

Author: Android Developers (noreply@blogger.com)

Published: 2026-07-27T13:00:00Z

Content type: article

Language: en

Sources: [Android Developers](<https://devfeed.tech/sources/android-developers-blog.md>)

Topics: [Coroutines](<https://devfeed.tech/topics/coroutines.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [R8](<https://devfeed.tech/topics/r8.md>), [Android](<https://devfeed.tech/topics/android.md>), [Jetpack Compose](<https://devfeed.tech/topics/jetpack-compose.md>), [Programming](<https://devfeed.tech/topics/programming.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [android-gradle-plugin](<https://devfeed.tech/tags/android-gradle-plugin.md>), [app-performance](<https://devfeed.tech/tags/app-performance.md>), [atomic](<https://devfeed.tech/tags/atomic.md>), [compose](<https://devfeed.tech/tags/compose.md>), [coroutines](<https://devfeed.tech/tags/coroutines.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [performance](<https://devfeed.tech/tags/performance.md>), [programming](<https://devfeed.tech/tags/programming.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

This article explains how R8 optimization in AGP 9.2.0 improves Kotlin coroutines performance on Android. By optimizing AtomicFieldUpdater calls, the change makes launching and cancelling coroutines up to twice as fast, addressing coroutine-related bottlenecks in Jetpack Compose and other Android operations.

### Source excerpt

Posted by Andrei Shikov, Senior Software Engineer, Android Toolkit and Jonathan Starup, Software Engineer, R8 Team Starting from AGP 9.2.0, R8 optimizes most Atomic*FieldUpdater calls into Unsafe variants that perform 2x to 4x better on common operations. This has a particularly large impact on the kotlinx.atomicfu library that implements atomics for kotlinx.coroutines, making launching and cancelling coroutines up to 2x faster. In order to get the benefits, update your AGP to 9.2.0 or above. With the majority of Android apps adopting Kotlin as their main language of choice, kotlinx.coroutines has become a de-facto standard for asynchronous programming. The library offers a well-designed and structured way of managing concurrent flows that is native to Kotlin. Jetpack Compose was no exception, adopting coroutines for managing pointer events, animations and other interactions. At the time of writing, most concurrent APIs in Compose call suspend functions under the hood and are launching and/or cancelling coroutines to handle updates. As the Compose team started to investigate performance, coroutines were discovered to be a bottleneck for many operations that happen outside of composition. As an example, 80% of the time spent on creating and updating Modifier.clickable was consumed by launching and cancelling internal coroutines that handled InteractionSource updates. Based on those observations, much of early performance work was focused on removing coroutines from the default path and delaying initialization until necessary. The cost of a coroutine The easiest way to analyze a function's internal behavior on Android is to capture an Android Runtime (ART) method trace. An ART method trace is a tool that records the execution flow of an app, showing exactly which methods are called, their order, and how much time is spent in each, allowing developers to identify performance bottlenecks. For an empty LaunchedEffect { } call, it would look something like this: LaunchedE

## My Network Agent Lives in My Pocket Now -- And Nobody Is in the Middle

DevFeed: [My Network Agent Lives in My Pocket Now -- And Nobody Is in the Middle](<https://devfeed.tech/articles/my-network-agent-lives-in-my-pocket-now-and-nobody-is-in-the-middle-60894.md>)

Original publisher: [Read original article](<https://automateyournetwork.com/uncategorized/my-network-agent-lives-in-my-pocket-now-and-nobody-is-in-the-middle/>)

Author: John Capobianco

Published: 2026-07-26T12:00:00Z

Content type: article

Language: en

Sources: [Automate Your Network](<https://devfeed.tech/sources/automate-your-network.md>)

Topics: [Claude Code](<https://devfeed.tech/topics/claude-code.md>), [Expo](<https://devfeed.tech/topics/expo.md>), [Termux](<https://devfeed.tech/topics/termux.md>), [android-app-bundle](<https://devfeed.tech/topics/android-app-bundle.md>), [tor](<https://devfeed.tech/topics/tor.md>)

Tags: [ai](<https://devfeed.tech/tags/ai.md>), [android](<https://devfeed.tech/tags/android.md>), [apk](<https://devfeed.tech/tags/apk.md>), [article](<https://devfeed.tech/tags/article.md>), [camera](<https://devfeed.tech/tags/camera.md>), [cellular](<https://devfeed.tech/tags/cellular.md>), [claude-code](<https://devfeed.tech/tags/claude-code.md>), [cml](<https://devfeed.tech/tags/cml.md>), [dart](<https://devfeed.tech/tags/dart.md>), [discord](<https://devfeed.tech/tags/discord.md>), [hardware](<https://devfeed.tech/tags/hardware.md>), [netclaw](<https://devfeed.tech/tags/netclaw.md>), [outage](<https://devfeed.tech/tags/outage.md>), [photo](<https://devfeed.tech/tags/photo.md>), [post-mortems](<https://devfeed.tech/tags/post-mortems.md>), [proguard](<https://devfeed.tech/tags/proguard.md>), [prompt](<https://devfeed.tech/tags/prompt.md>), [r8](<https://devfeed.tech/tags/r8.md>), [room](<https://devfeed.tech/tags/room.md>), [slack](<https://devfeed.tech/tags/slack.md>), [webex](<https://devfeed.tech/tags/webex.md>)

### AI overview

The article recounts building NetClaw Mobile, a private network automation agent accessed through phones. It describes Claude Code testing an Android app in an emulator, then moving to real-device testing and connecting an iPhone with an Android phone to a CML lab without routing conversations through third-party chat services.

### Source excerpt

From an emulator Claude Code drove itself, to a real Android phone in someone else's hands, to an iPhone talking to that Android through my own Border -- voice, photos, and a live CML lab, all over NCFED. No Slack, no Discord, no Webex, no t

## Obfuscation Deep Dive: Enhancing R8 and ProGuard for Robust Android Code Protection

DevFeed: [Obfuscation Deep Dive: Enhancing R8 and ProGuard for Robust Android Code Protection](<https://devfeed.tech/articles/obfuscation-deep-dive-enhancing-r8-and-proguard-for-robust-android-code-protection-25958.md>)

Original publisher: [Read original article](<https://kirillr.medium.com/proguard-r8-obfuscation-dictionary-b4541a898eb8?source=rss-7a0a233f88a2------2>)

Author: Kirill Rozov

Published: 2025-05-19T07:40:40Z

Content type: article

Language: en

Sources: [Kirill Rozov](<https://devfeed.tech/sources/stories-by-kirill-rozov-on-medium.md>)

Topics: [obfuscation](<https://devfeed.tech/topics/obfuscation.md>), [proguard](<https://devfeed.tech/topics/proguard.md>), [R8](<https://devfeed.tech/topics/r8.md>), [Android](<https://devfeed.tech/topics/android.md>)

Tags: [advanced](<https://devfeed.tech/tags/advanced.md>), [android](<https://devfeed.tech/tags/android.md>), [app](<https://devfeed.tech/tags/app.md>), [app-size](<https://devfeed.tech/tags/app-size.md>), [applications](<https://devfeed.tech/tags/applications.md>), [approach](<https://devfeed.tech/tags/approach.md>), [article](<https://devfeed.tech/tags/article.md>), [aspect](<https://devfeed.tech/tags/aspect.md>), [builds](<https://devfeed.tech/tags/builds.md>), [but](<https://devfeed.tech/tags/but.md>), [code](<https://devfeed.tech/tags/code.md>), [deep](<https://devfeed.tech/tags/deep.md>), [deep-dive](<https://devfeed.tech/tags/deep-dive.md>), [dive](<https://devfeed.tech/tags/dive.md>), [enhancing](<https://devfeed.tech/tags/enhancing.md>), [java](<https://devfeed.tech/tags/java.md>), [obfuscation](<https://devfeed.tech/tags/obfuscation.md>), [proguard](<https://devfeed.tech/tags/proguard.md>), [protection](<https://devfeed.tech/tags/protection.md>), [r8](<https://devfeed.tech/tags/r8.md>), [robust](<https://devfeed.tech/tags/robust.md>), [security](<https://devfeed.tech/tags/security.md>)

### AI overview

R8 and ProGuard's default short-letter naming can make obfuscated identifiers predictable across builds, which the excerpt says may aid reverse engineering. It recommends supplying custom class, package, and general obfuscation dictionaries, with a new randomized dictionary for each build to vary names. It also describes Java reserved keywords as bytecode names that can confuse decompilers, though the resulting code will not compile as Java, and warns that Windows-restricted names may cause reverse-engineering errors on Windows. The excerpt advises testing across environments; its final randomization-script description is cut off.

### Source excerpt

Obfuscation is a crucial aspect of securing Android applications. While tools like R8 and ProGuard are commonly used, their default configurations primarily aim to reduce app size rather than fortify code against reverse engineering. This article delves into advanced obfuscation techniques to make reverse engineering harder. Understanding Obfuscation Obfuscation transforms readable code into a form that's difficult to interpret. For instance, UserManager might become a, and getUser() could be renamed to b(). R8 and ProGuard perform obfuscation alongside code shrinking and optimization. # R8/ProGuard default dictionary a b c ... z These tools use dictionaries to generate new names, typically starting with single letters (a to z) and progressing to combinations like aa, ab, etc. While this approach minimizes file size, it has drawbacks: Predictable Naming: Limited name variations make it easier to deduce original identifiers. Consistent Builds: Repeated builds produce identical obfuscated names, aiding pattern recognition. Simplified Reverse Engineering: Tools can exploit naming patterns across builds. To counter these issues, customizing the obfuscation dictionary is essential. Implementing Custom Dictionaries R8 and ProGuard allow the use of custom dictionaries via configuration files: # proguard-rules.txt # Add to R8/ProGuard config file -obfuscationdictionary obfuscation-dictionary.tx -classobfuscationdictionary class-dictionary.txt -packageobfuscationdictionary package-dictionary.txt By providing unique dictionaries, you can generate diverse and unpredictable obfuscated names. Advanced Dictionary StrategiesJava Reserved Keywords Using Java's reserved keywords (e.g., if, for, class) as obfuscated names can confuse decompilers, as these are invalid identifiers in source code but acceptable in bytecode. # Java Reserved Keywords dictionary do if for int new ... instanceof synchronized Example of deobfucated Java code with java reserved keywords dictionary package cla

## Optimizing Rectangle-Overlap Tests by Removing Conditional Branches

DevFeed: [Optimizing Rectangle-Overlap Tests by Removing Conditional Branches](<https://devfeed.tech/articles/down-a-rabbit-hole-25596.md>)

Original publisher: [Read original article](<https://www.romainguy.dev/posts/2024/down-a-rabbit-hole/>)

Author: Romain Guy

Published: 2024-05-18T00:00:00Z

Content type: tutorial

Language: en

Sources: [Posts on Romain Guy](<https://devfeed.tech/sources/posts-on-romain-guy.md>)

Topics: [Optimization](<https://devfeed.tech/topics/optimization.md>), [Code](<https://devfeed.tech/topics/code.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [R8](<https://devfeed.tech/topics/r8.md>), [Benchmark](<https://devfeed.tech/topics/benchmark.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [assembly](<https://devfeed.tech/tags/assembly.md>), [benchmark](<https://devfeed.tech/tags/benchmark.md>), [code](<https://devfeed.tech/tags/code.md>), [developer](<https://devfeed.tech/tags/developer.md>), [graphics](<https://devfeed.tech/tags/graphics.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [performance](<https://devfeed.tech/tags/performance.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

This article examines optimizing rectangle-overlap tests in Kotlin. It compares generated assembly, replaces logical operators with bitwise operators to remove conditional branches, and reports a 1.7x speedup in a benchmark on a Google Pixel 6.

### Source excerpt

I recently discussed an optimization that I worked on following Leland's successful nerd snipe. That, however, was not the end of it. He also needed to test for intersecting/overlapping rectangles. The most obvious way to achieve this is pretty straightforward: 1// A rectangle is defined by its left (l), top (t), 2// right (r), and bottom (b) coordinates 3data class Rect(val l: Int, val t: Int, val r: Int, val b: Int) { 4 fun overlaps(other: Rect) = 5 l < other.r && other.l < r && t < other.b && other.t < b 6} The source code is nice and tidy, but the generated assembly is less than ideal (as always, the code was optimized with R8 first):

## Crafting Android bytecode analysis tooling using a secret ingredient (Part 1)

DevFeed: [Crafting Android bytecode analysis tooling using a secret ingredient (Part 1)](<https://devfeed.tech/articles/crafting-android-bytecode-analysis-tooling-using-a-secret-ingredient-part-1-22597.md>)

Original publisher: [Read original article](<https://medium.com/bumble-tech/crafting-android-bytecode-analysis-tooling-using-a-secret-ingredient-part-1-13e2d5a65113?source=rss----6353b5325b1a---4>)

Author: Konstantin Zolotov

Published: 2024-02-09T11:50:19Z

Content type: article

Language: en

Sources: [Bumble Tech](<https://devfeed.tech/sources/bumble-tech.md>)

Topics: [R8](<https://devfeed.tech/topics/r8.md>), [Developer Tools](<https://devfeed.tech/topics/developer-tools.md>), [Android](<https://devfeed.tech/topics/android.md>), [obfuscation](<https://devfeed.tech/topics/obfuscation.md>), [Compilers and Linkers](<https://devfeed.tech/topics/compilers-and-linkers.md>), [APK](<https://devfeed.tech/topics/apk.md>)

Tags: [analysis](<https://devfeed.tech/tags/analysis.md>), [andriod-app-development](<https://devfeed.tech/tags/andriod-app-development.md>), [android](<https://devfeed.tech/tags/android.md>), [annotation](<https://devfeed.tech/tags/annotation.md>), [apk](<https://devfeed.tech/tags/apk.md>), [apt](<https://devfeed.tech/tags/apt.md>), [bytecode](<https://devfeed.tech/tags/bytecode.md>), [compilation](<https://devfeed.tech/tags/compilation.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [dagger](<https://devfeed.tech/tags/dagger.md>), [debug](<https://devfeed.tech/tags/debug.md>), [dependencies](<https://devfeed.tech/tags/dependencies.md>), [inspection](<https://devfeed.tech/tags/inspection.md>), [java](<https://devfeed.tech/tags/java.md>), [jvm](<https://devfeed.tech/tags/jvm.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [map](<https://devfeed.tech/tags/map.md>), [obfuscation](<https://devfeed.tech/tags/obfuscation.md>), [r8](<https://devfeed.tech/tags/r8.md>), [source-code](<https://devfeed.tech/tags/source-code.md>), [tooling](<https://devfeed.tech/tags/tooling.md>)

### AI overview

Inspecting compiled Dex output can reveal how source changes and dependency-provided R8 rules affect an Android app's binary, including whether debug code remains. Java or Kotlin source first becomes JVM .class files; annotation processors and Kotlin compiler plugins may generate or alter code at that stage. D8 converts classes and JAR/AAR dependencies into .dex files. When obfuscation or minification is enabled, R8 optimizes and obfuscates the bytecode and produces a mapping file recording name changes. The excerpt introduces tree shaking, which removes unused or unreachable code, and mentions inlining and outlining as structural optimizations.

### Source excerpt

During the development process, we often focus on the source code but rarely inspect the compiled bytecode. This means we're missing out on a valuable source of information and data for analysis. How? Let's delve into Dex file inspection and build a tool that demonstrates how source code changes impact the compiled binary. Have you ever set R8 rules to obfuscate your app? Have you used an APK analyzer or a diffuse tool to understand how the code is compiled? Are you confident that debug code hasn't leaked into production? There's another potential pitfall: libraries may provide obfuscation rules (e.g., Gson) that merge with the ones in your project. This means third-party dependencies can alter configurations for the entire app. We often assume everything is fine and that we'll notice if something isn't right. But will we? Does this make you feel uneasy? Does it concern you? Because it certainly concerns me. Here, we'll attempt to enhance the situation and enable you to see precisely how your code changes impact the compiled binary. To better comprehend this, let's start with the code compilation process: It all begins with the Java and/or Kotlin source code, which is then compiled into JVM .class files. Note that at this stage, Java and Kotlin compilers can execute annotation processing tools (APT/KAPT) to generate source code (e.g., Dagger), and Kotlin compiler can run plugins to modify the internal code representation. Then, the D8 compiler takes these compiled classes, third-party libraries (JARs, AARs), and converts them into .dex files. However, if obfuscation and/or minification are enabled (which is almost always the case for release builds), R8 comes into play after D8. R8 obfuscates and optimises the bytecode, and additionally, R8 produces a source map file -- a special file listing all the changes and replacements. Obfuscation replaces human-readable names of various entities (classes, functions, fields, etc.) with very short, yet still unique names, for e

## How to break your Android App with proguard / R8

DevFeed: [How to break your Android App with proguard / R8](<https://devfeed.tech/articles/how-to-break-your-android-app-with-proguard-r8-24744.md>)

Original publisher: [Read original article](<https://medium.com/yazio-engineering/how-to-break-your-android-app-with-proguard-r8-6566bc387b63?source=rss----65bd178b00af---4>)

Author: Paul Woitaschek

Published: 2021-03-02T15:19:22Z

Content type: article

Language: en

Sources: [YAZIO](<https://devfeed.tech/sources/yazio-engineering-medium.md>)

Topics: [R8](<https://devfeed.tech/topics/r8.md>), [proguard](<https://devfeed.tech/topics/proguard.md>), [Android Testing](<https://devfeed.tech/topics/android-testing.md>), [Android](<https://devfeed.tech/topics/android.md>), [Android Gradle Plugin](<https://devfeed.tech/topics/android-gradle-plugin.md>), [Software Testing](<https://devfeed.tech/topics/software-testing.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [android-app-development](<https://devfeed.tech/tags/android-app-development.md>), [androiddev](<https://devfeed.tech/tags/androiddev.md>), [app](<https://devfeed.tech/tags/app.md>), [proguard](<https://devfeed.tech/tags/proguard.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

A broad R8/ProGuard rule, `-assumenosideeffects class android.util.Log { public *; }`, can affect inherited public methods as well as logging calls. The article reports that this includes synchronization methods on `Object`, such as `notify`, potentially breaking app synchronization and causing hangs. It recommends avoiding `*` wildcards with `-assumenosideeffects` and specifying the logging signatures explicitly (`v`, `d`, `i`, `w`, `e`, and `println`) when removing production log calls. The author also warns that the issue can enter an app through a library's consumer ProGuard rules.

### Source excerpt

I recently updated the android gradle plugin to 4.0.0. While developing, everything went smoothly and at some point I was ready to cut a release. The very last manual testing of the release app bundle was also fine so no Proguard / R8 issues on the first sight either. Then I thought: Let me check the CI results again. Everything was fine, but: The instrumentation tests. Almost all of them were timing out. After inspecting the logs, they all hang at the end of the on-boarding. Strangely the loading spinner was loading for way longer than the timeout should be. So I tested it on my phone and faced the same results. At that time I had no idea it was caused by updating AGP, so I did a 2 hours long git bisect. Okay, now lets create a minimal self reproducible bug report because I found a huge bug in AGP, everyone should know about immediately. I created a Hello World project that was making a single network call and printed it results into a TextView. Strangely here it did not reproduce. After experimenting with the OkHttp configuration and testing if it was related to some gradle plugin, I finally had the idea that it might be related to R8. So I added my proguard configuration and now the network call hang! Let's locate the issue further. I was step by step removing lines from my proguard configuration until only a single line was left: -assumenosideeffects class android.util.Log { public * ; } Now what is this? How is that even slightly related to anything? It should remove the log spam of some third party libraries we're using. So I was asking Mads Ager. (he works on D8/R8) you have to be very careful with -assumenosideeffects The problem is that in order for -assumenosideeffects to have the effect of actually removing calls, it matches up the class hierarchy. Therefore, this rule says that anything public in android.util.Log and its superclasses has no side-effects. That include the synchronization methods defined on Object. So, please don't use * wildcards in conne

## How to break your Android App with proguard / R8

DevFeed: [How to break your Android App with proguard / R8](<https://devfeed.tech/articles/how-to-break-your-android-app-with-proguard-r8-26006.md>)

Original publisher: [Read original article](<https://medium.com/yazio-engineering/how-to-break-your-android-app-with-proguard-r8-6566bc387b63?source=rss-fbf9b6d94e65------2>)

Author: Paul Woitaschek

Published: 2020-06-08T05:52:07Z

Content type: article

Language: en

Sources: [Paul Woitaschek](<https://devfeed.tech/sources/stories-by-paul-woitaschek-on-medium.md>)

Topics: [R8](<https://devfeed.tech/topics/r8.md>), [proguard](<https://devfeed.tech/topics/proguard.md>), [Android](<https://devfeed.tech/topics/android.md>), [Android Testing](<https://devfeed.tech/topics/android-testing.md>), [Software Testing](<https://devfeed.tech/topics/software-testing.md>), [Concurrency](<https://devfeed.tech/topics/concurrency.md>), [Android Gradle Plugin](<https://devfeed.tech/topics/android-gradle-plugin.md>), [Test automation](<https://devfeed.tech/topics/test-automation.md>), [CI/CD](<https://devfeed.tech/topics/cicd.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [android-app-development](<https://devfeed.tech/tags/android-app-development.md>), [androiddev](<https://devfeed.tech/tags/androiddev.md>), [proguard](<https://devfeed.tech/tags/proguard.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

After updating Android Gradle Plugin 4.0.0, the author traced hanging network calls and instrumentation-test timeouts to a ProGuard/R8 rule: `-assumenosideeffects class android.util.Log { public *; }`. The wildcard matched public methods through the class hierarchy, including synchronization methods inherited from `Object`; treating those as side-effect-free could remove essential synchronization. The proposed replacement lists logging signatures explicitly (`v`, `d`, `i`, `w`, `e`, and `println`) instead of using `public *`. The excerpt cautions that the rule can also arrive through a library's consumer ProGuard rules.

### Source excerpt

I recently updated the android gradle plugin to 4.0.0. While developing, everything went smoothly and at some point I was ready to cut a release. The very last manual testing of the release app bundle was also fine so no Proguard / R8 issues on the first sight either. Then I thought: Let me check the CI results again. Everything was fine, but: The instrumentation tests. Almost all of them were timing out. After inspecting the logs, they all hang at the end of the on-boarding. Strangely the loading spinner was loading for way longer than the timeout should be. So I tested it on my phone and faced the same results. At that time I had no idea it was caused by updating AGP, so I did a 2 hours long git bisect. Okay, now lets create a minimal self reproducible bug report because I found a huge bug in AGP, everyone should know about immediately. I created a Hello World project that was making a single network call and printed it results into a TextView. Strangely here it did not reproduce. After experimenting with the OkHttp configuration and testing if it was related to some gradle plugin, I finally had the idea that it might be related to R8. So I added my proguard configuration and now the network call hang! Let's locate the issue further. I was step by step removing lines from my proguard configuration until only a single line was left: -assumenosideeffects class android.util.Log { public * ; } Now what is this? How is that even slightly related to anything? It should remove the log spam of some third party libraries we're using. So I was asking Mads Ager. (he works on D8/R8) you have to be very careful with -assumenosideeffects The problem is that in order for -assumenosideeffects to have the effect of actually removing calls, it matches up the class hierarchy. Therefore, this rule says that anything public in android.util.Log and its superclasses has no side-effects. That include the synchronization methods defined on Object. So, please don't use * wildcards in conne

## R8 Optimization: Lambda Groups

DevFeed: [R8 Optimization: Lambda Groups](<https://devfeed.tech/articles/r8-optimization-lambda-groups-20959.md>)

Original publisher: [Read original article](<https://jakewharton.com/r8-optimization-lambda-groups/>)

Published: 2020-04-30T00:00:00Z

Content type: article

Language: en

Sources: [Jake Wharton](<https://devfeed.tech/sources/jake-wharton.md>)

Topics: [R8](<https://devfeed.tech/topics/r8.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [Android](<https://devfeed.tech/topics/android.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Java](<https://devfeed.tech/topics/java.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [apk](<https://devfeed.tech/tags/apk.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [lambda](<https://devfeed.tech/tags/lambda.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

An analysis of how R8 optimizes Kotlin lambda groups in Android applications, using compiled examples to compare the generated classes before and after optimization.

### Source excerpt

Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". Lambda usage in Kotlin feels more pervasive than Java because of the functional nature of the Kotlin standard library. Some lambdas are merely syntactic constructs that are eliminated at compile-time through the use of inline functions. The rest materialize into whole classes for use at runtime. The mechanisms by which lambdas work was covered in the Android Java 8 support post, but here's a quick refresher: javac hoists lambda bodies to a package-private method and writes an invoke-dynamic bytecode for the target lambda type at the call-site. The JVM spins a class at runtime of the desired type and invokes the package-private method in the method body. Android does not ship this runtime support, so D8 performs a compile-time transformation to a class which implements the desired type and which invokes the package-private method. kotlinc skips the invoke-dynamic bytecode (even when targeting Java 8+) and generates full classes directly. Here's two Kotlin classes and some lambda usage that we can experiment with. class Employee( val id: String, val joined: LocalDate, val managerId: String? ) class EmployeeRepository(val allEmployees: () -> Sequence<Employee>) { fun joinedAfter(date: LocalDate) = allEmployees() .filter { it.joined >= date } .toList() fun reports(manager: Employee) = allEmployees() .filter { it.managerId == manager.id } .toList() } The EmployeeRepository class accepts a lambda which produces a sequence of employees and exposes two functions for listing the employees who joined after a particular date and those who report to a particular employee. Both functions use a lambda to filter the sequence to the desired items before converting to a list. Kotlin's approach to lambdas is immediately visible after compiling this class. $ kotlinc EmployeeRepos

## Which is better on Android: divide by 2 or shift by 1?

DevFeed: [Which is better on Android: divide by 2 or shift by 1?](<https://devfeed.tech/articles/which-is-better-on-android-divide-by-2-or-shift-by-1-20983.md>)

Original publisher: [Read original article](<https://jakewharton.com/which-is-better-on-android-divide-by-two-or-shift-by-one/>)

Published: 2020-04-23T00:00:00Z

Content type: tutorial

Language: en

Sources: [Jake Wharton](<https://devfeed.tech/sources/jake-wharton.md>)

Topics: [Android](<https://devfeed.tech/topics/android.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [Java](<https://devfeed.tech/topics/java.md>), [R8](<https://devfeed.tech/topics/r8.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [kotlin-multiplatform](<https://devfeed.tech/tags/kotlin-multiplatform.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [r8](<https://devfeed.tech/tags/r8.md>), [writing](<https://devfeed.tech/tags/writing.md>)

### AI overview

This article investigates whether dividing by 2 or shifting by 1 is better on Android. It examines how Java and Kotlin source code is transformed by javac or kotlinc, D8/R8, and ART, using bytecode and Dalvik bytecode examples. The discussion is motivated by work porting the AndroidX collection library to Kotlin Multiplatform and by concerns about performance, readability, and compiler optimization.

### Source excerpt

I've been porting the AndroidX collection library to Kotlin multiplatform to experiment with binary compatibility, performance, tooling, and the different memory models. Some of the data structures in the library use array-based binary trees to store elements. The Java code has a lot of shifts to replace power-of-two multiplications and divides. When ported to Kotlin, these turn into the slightly-awkward infix operators which further obfuscate the intent of the code. I sampled a few people about bitwise shifts vs. multiplication/division and many had heard anecdotal claims of shifts having better performance, but everyone remained skeptical of whether it was true. Some assumed that one of the compilers seen before the code ran on a CPU would handle optimizing this case. In an effort to satisfy my curiosity (and partially to avoid Kotlin's infix bitwise operators) I set out to answer which is better and some other related questions. Let's go! Does anyone optimize this? There are three major compilers that code passes through before it hits the CPU: javac/kotlinc, D8/R8, and ART. Each of these has the opportunity to optimize. But do they? javac class Example { static int multiply(int value) { return value * 2; } static int divide(int value) { return value / 2; } static int shiftLeft(int value) { return value << 1; } static int shiftRight(int value) { return value >> 1; } } This Java can be compiled with javac from JDK 14 and the resulting bytecode can be displayed with javap. $ javac Example.java $ javap -c Example Compiled from "Example.java" class Example { static int multiply(int); Code: 0: iload_0 1: iconst_2 2: imul 3: ireturn static int divide(int); Code: 0: iload_0 1: iconst_2 2: idiv 3: ireturn static int shiftLeft(int); Code: 0: iload_0 1: iconst_1 2: ishl 3: ireturn static int shiftRight(int); Code: 0: iload_0 1: iconst_1 2: ishr 3: ireturn } Every method starts with iload_0 which loads the first argument value. The multiply and divide methods both then have

## D8 Optimization: Assertions

DevFeed: [D8 Optimization: Assertions](<https://devfeed.tech/articles/d8-optimization-assertions-20929.md>)

Original publisher: [Read original article](<https://jakewharton.com/d8-optimization-assertions/>)

Published: 2020-03-25T00:00:00Z

Content type: article

Language: en

Sources: [Jake Wharton](<https://devfeed.tech/sources/jake-wharton.md>)

Topics: [Android](<https://devfeed.tech/topics/android.md>), [R8](<https://devfeed.tech/topics/r8.md>), [Java](<https://devfeed.tech/topics/java.md>), [Concurrency](<https://devfeed.tech/topics/concurrency.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [java](<https://devfeed.tech/tags/java.md>), [jvm](<https://devfeed.tech/tags/jvm.md>), [main-thread](<https://devfeed.tech/tags/main-thread.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [r8](<https://devfeed.tech/tags/r8.md>), [thread](<https://devfeed.tech/tags/thread.md>)

### AI overview

This article explains how D8 and R8 optimize Java assert statements in Android applications. Because Android does not support enabling Java assertions, D8 can remove the assertion check and its dependent expressions, allowing dead-code elimination. The example uses an assertion to enforce main-thread access when generating unique IDs, and the article connects this optimization to R8's SSA-based analysis.

### Source excerpt

Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". The assert keyword is quirky Java language syntax used for testing invariants. That is: things you expect to always be true. Its syntax has two forms: assert <bool-expression>; assert <bool-expression> : <expression>; The first expression will only be evaluated at runtime if the -ea (enable assertions) flag is set on the JVM. The second expression, if present, is used as the argument to the AssertionError constructor that's thrown if the first expression returns false. As an Android developer you might not be too familiar with assert. This is because every Android app runs on a VM which is forked from a shared "zygote" process which has assertions disabled. Thus, even if you put an assert in your code, there is no way to actually enable it. So why bother talking about it? Well it turns out they're about to become useful on Android for the first time! Today's behavior assert statements guard things which must always be true in order for your program to execute correctly. Let's write one. class IdGenerator { private int id = 0; int next() { assert Thread.currentThread() == Looper.getMainLooper().getThread(); return id++; } } This class creates unique IDs and guarantees they're unique by only allowing calls from the main thread. If this class was called concurrently from multiple threads you might see duplicate values. Sure it's a little contrived and there's things like @MainThread which is checked by Lint but we're focusing on assert so roll with it. The Null Data Flow Analysis post introduced the SSA form that R8 uses to eliminate branches of code which it can prove will never be executed. The SSA for the next() method when parsed from Java bytecode looks very roughly like this: D8 knows that Android does not support Java assertions. It will remove the check an

## Diving deep into Android Dex bytecode

DevFeed: [Diving deep into Android Dex bytecode](<https://devfeed.tech/articles/diving-deep-into-android-dex-bytecode-38625.md>)

Original publisher: [Read original article](<https://krossovochkin.com/posts/2020_02_02_diving_deep_into_android_dex_bytecode/>)

Published: 2020-02-02T00:00:00Z

Content type: tutorial

Language: en

Sources: [Vasya Drobushkov](<https://devfeed.tech/sources/vasya-drobushkov.md>)

Topics: [Android](<https://devfeed.tech/topics/android.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [R8](<https://devfeed.tech/topics/r8.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [Java](<https://devfeed.tech/topics/java.md>), [Mobile](<https://devfeed.tech/topics/mobile.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [bytecode](<https://devfeed.tech/tags/bytecode.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [inlining](<https://devfeed.tech/tags/inlining.md>), [java](<https://devfeed.tech/tags/java.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [memory](<https://devfeed.tech/tags/memory.md>), [performance](<https://devfeed.tech/tags/performance.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

This practical guide explains how Kotlin and Java code is transformed into Android DEX bytecode. It describes examining Java bytecode, the role of the Dalvik bytecode format and Android Runtime, and the compilation tools kotlinc, javac, d8, and R8, with attention to possible memory and performance effects.

### Source excerpt

Source Introduction Modern Android development is based on Kotlin, which is interoperable with Java. Whenever we use some cool feature from Kotlin (say High-order functions) under the hood (when running on JVM) the feature is implemented in terms of Java bytecode. This might lead to some overheads in memory and performance if used without caution (for example excessive usage of lambdas with parameters without inlining might produce a lot of anonymous classes and put additional pressure on GC).

## Fixing the Initial Dispatchers.Main Delay in Kotlin Coroutines

DevFeed: [Fixing the Initial Dispatchers.Main Delay in Kotlin Coroutines](<https://devfeed.tech/articles/a-dispatcher-of-many-threads-37550.md>)

Original publisher: [Read original article](<https://colintheshots.com/writing/a-dispatcher-of-many-threads-part-1-2/>)

Published: 2019-12-19T03:02:18Z

Content type: tutorial

Language: en

Sources: [Colin The Shots](<https://devfeed.tech/sources/colin-the-shots.md>)

Topics: [Coroutines](<https://devfeed.tech/topics/coroutines.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>), [Android](<https://devfeed.tech/topics/android.md>), [R8](<https://devfeed.tech/topics/r8.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [Android Studio](<https://devfeed.tech/topics/android-studio.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [android-studio](<https://devfeed.tech/tags/android-studio.md>), [builds](<https://devfeed.tech/tags/builds.md>), [coroutines](<https://devfeed.tech/tags/coroutines.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [kotlin-coroutines](<https://devfeed.tech/tags/kotlin-coroutines.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

This article explains an initial delay of up to a quarter second when Android apps first use Kotlin Coroutines' Dispatchers.Main. It attributes the delay to ServiceLoader triggering a checksum of the entire JAR inside the APK and describes a stable fix using Kotlin coroutines 1.3.3 or higher, required Proguard rules, and R8 optimization.

### Source excerpt

Kotlin Coroutines have been almost unanimously received with applause by the Android software development community. However, there are some significant issues I have noticed in practice that are

## ProGuard & R8: Part 2

DevFeed: [ProGuard & R8: Part 2](<https://devfeed.tech/articles/proguard-r8-part-2-32346.md>)

Original publisher: [Read original article](<https://dustn.dev/post/2019-11-20-android-build-pipeline-hands-on/>)

Author: dustin@dustn.dev (Dustin Summers)

Published: 2019-11-20T09:00:00Z

Content type: tutorial

Language: en

Sources: [Dustin Summers](<https://devfeed.tech/sources/dustin-summers.md>)

Topics: [R8](<https://devfeed.tech/topics/r8.md>), [Android](<https://devfeed.tech/topics/android.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [Android Studio](<https://devfeed.tech/topics/android-studio.md>), [Java](<https://devfeed.tech/topics/java.md>), [Kotlin](<https://devfeed.tech/topics/kotlin.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [android-studio](<https://devfeed.tech/tags/android-studio.md>), [code](<https://devfeed.tech/tags/code.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [java](<https://devfeed.tech/tags/java.md>), [kotlin](<https://devfeed.tech/tags/kotlin.md>), [proguard](<https://devfeed.tech/tags/proguard.md>), [proguard-android-r8-smali-dalvik-jvm-kotlin-art-gradle-java](<https://devfeed.tech/tags/proguard-android-r8-smali-dalvik-jvm-kotlin-art-gradle-java.md>), [r8](<https://devfeed.tech/tags/r8.md>), [sdk](<https://devfeed.tech/tags/sdk.md>), [terminal](<https://devfeed.tech/tags/terminal.md>)

### AI overview

A hands-on tutorial covering the Android build pipeline with ProGuard and R8. It walks through compiling Java or Kotlin source code, using Android Build Tools, and examining generated bytecode.

### Source excerpt

This blog post is the second in a series to teach about the build tools ProGuard and R8, and the first in the hands-on portion of the series. In the first post I talked about the Android Build Pipeline. In this blog, I would like to actually reinforce those concepts with hands on exercises. If you haven't read the first blog on this topic, this is part two in that series, so I highly suggest going back and understanding that material first.

## Understanding the Android Build Pipeline with ProGuard and R8

DevFeed: [Understanding the Android Build Pipeline with ProGuard and R8](<https://devfeed.tech/articles/proguard-r8-part-1-32347.md>)

Original publisher: [Read original article](<https://dustn.dev/post/2019-11-6-understanding-the-android-build-pipeline/>)

Author: dustin@dustn.dev (Dustin Summers)

Published: 2019-11-06T12:08:40Z

Content type: tutorial

Language: en

Sources: [Dustin Summers](<https://devfeed.tech/sources/dustin-summers.md>)

Topics: [R8](<https://devfeed.tech/topics/r8.md>), [Code](<https://devfeed.tech/topics/code.md>), [obfuscation](<https://devfeed.tech/topics/obfuscation.md>), [software-development](<https://devfeed.tech/topics/software-development.md>), [Software](<https://devfeed.tech/topics/software.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [compilation](<https://devfeed.tech/tags/compilation.md>), [obfuscation](<https://devfeed.tech/tags/obfuscation.md>), [proguard](<https://devfeed.tech/tags/proguard.md>), [proguard-android-r8-smali-dalvik-jvm-kotlin-art-gradle-java](<https://devfeed.tech/tags/proguard-android-r8-smali-dalvik-jvm-kotlin-art-gradle-java.md>), [r8](<https://devfeed.tech/tags/r8.md>), [software-development](<https://devfeed.tech/tags/software-development.md>), [tutorials](<https://devfeed.tech/tags/tutorials.md>)

### AI overview

A tutorial explaining the Android build pipeline and where ProGuard and R8 fit into it. It introduces compilation stages, optimization, shrinking, and code obfuscation, with an emphasis on understanding and diagnosing how these tools transform source code into bytecode.

### Source excerpt

Tools such as R8 and ProGuard are available for free, but to many they are a black box that code goes into and stuff comes out. My goal is to demystify the black box and teach developers how to properly diagnose the code going into and coming out of these build tools. It will also explain why you should care and why applying these tools should be a priority before shipping any code into the wild.

## D8 Optimizations

DevFeed: [D8 Optimizations](<https://devfeed.tech/articles/d8-optimizations-20930.md>)

Original publisher: [Read original article](<https://jakewharton.com/d8-optimizations/>)

Published: 2019-10-30T00:00:00Z

Content type: article

Language: en

Sources: [Jake Wharton](<https://devfeed.tech/sources/jake-wharton.md>)

Topics: [Android](<https://devfeed.tech/topics/android.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [Java](<https://devfeed.tech/topics/java.md>), [R8](<https://devfeed.tech/topics/r8.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [code](<https://devfeed.tech/tags/code.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [java](<https://devfeed.tech/tags/java.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [performance](<https://devfeed.tech/tags/performance.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

D8 Optimizations explains how D8, Android's Java-to-Dalvik bytecode compiler, performs local optimizations in addition to Java language backporting and platform bug workarounds. It discusses rewriting switch statements when the resulting Dalvik bytecode is smaller and evaluating certain constant method calls at compile time.

### Source excerpt

Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". No, that's not a typo! While the optimizations in this series so far have been done by R8 during whole-program optimization, D8 can also perform some simple optimizations. D8 was introduced as the new Java-to-Dalvik bytecode compiler for Android. It handles backporting of Java 8 language features to work on Android (as well as those of Java 9 and beyond). It also works around vendor- and version-specific bugs in the platform. That's what we've seen from D8 so far in the series, but it has two other responsibilities that we'll cover in this post and the next: Backporting methods to work on older API levels where they didn't exist. Performing local optimizations to reduce bytecode size and/or improve performance. We'll cover API backporting in the next post in the series. For now, let's look at some of the local optimizations that D8 might perform. Switch Rewriting The last two posts (1, 2) have dealt with optimizing switch statements. Both have slightly lied about the bytecode that D8 and R8 produce for certain switch statements. Let's look at one of those examples again. enum Greeting { FORMAL, INFORMAL; static String greetingType(Greeting greeting) { switch (greeting) { case FORMAL: return "formal"; case INFORMAL: return "informal"; default: throw new AssertionError(); } } } The full Java bytecode that was shown for greetingType used the lookupswitch bytecode which has offsets for where to jump when a value is matched. static java.lang.String greetingType(Greeting); Code: 0: getstatic #2 // Field Main$1.$SwitchMap$Greeting:[I 3: aload_0 4: invokevirtual #3 // Method Greeting.ordinal:()I 7: iaload 8: lookupswitch { 1: 36 2: 39 default: 42 } 36: ldc #4 // String formal 38: areturn 39: ldc #5 // String informal 41: areturn 42: new #6 // class java/lang/AssertionE

## R8 Optimization: Enum Switch Maps

DevFeed: [R8 Optimization: Enum Switch Maps](<https://devfeed.tech/articles/r8-optimization-enum-switch-maps-20958.md>)

Original publisher: [Read original article](<https://jakewharton.com/r8-optimization-enum-switch-maps/>)

Published: 2019-10-16T00:00:00Z

Content type: tutorial

Language: en

Sources: [Jake Wharton](<https://devfeed.tech/sources/jake-wharton.md>)

Topics: [R8](<https://devfeed.tech/topics/r8.md>), [Optimization](<https://devfeed.tech/topics/optimization.md>), [Android](<https://devfeed.tech/topics/android.md>), [Java](<https://devfeed.tech/topics/java.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [Code](<https://devfeed.tech/topics/code.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [code](<https://devfeed.tech/tags/code.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [java](<https://devfeed.tech/tags/java.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [r8](<https://devfeed.tech/tags/r8.md>)

### AI overview

This article explains how Java enum switch statements are compiled and how R8 optimizes them. It describes the generated switch-map array that translates enum ordinals into stable branch values, allowing the application to continue working when enum constants are reordered and only part of the code is recompiled.

### Source excerpt

Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". The previous post on R8 covered enum ordinals which then allowed branch elimination to apply to a switch statement. In that post, the full bytecode for switch on an enum was omitted because there's actually more to the optimization. Let's start with a simple enum and a switch over its contents in two separate source files (this will be important later). enum Greeting { FORMAL, INFORMAL } class Main { static String greetingType(Greeting greeting) { switch (greeting) { case FORMAL: return "formal"; case INFORMAL: return "informal"; default: throw new AssertionError(); } } public static void main(String... args) { System.out.println(greetingType(Greeting.INFORMAL)); } } If we compile and run these files the output is as expected. $ javac Greeting.java Main.java $ java -cp . Main informal The bytecode in the previous post showed that the compiler produces a call to ordinal() which is then used in the switch. But if that was all that the compiler did, re-ordering the constants of Greeting would break the output of Main. enum Greeting { - FORMAL, INFORMAL + INFORMAL, FORMAL } After changing the constant order, we can recompile only Greeting.java and yet the application still produces the correct output. $ javac Greeting.java $ java -cp . Main informal If the bytecode was only relying on the value of ordinal(), this code would have produced "formal". Into The Bytecode To understand how this works we can look at the Java bytecode of greetingType. $ javap -c Main.class class Main { static java.lang.String greetingType(Greeting); Code: 0: getstatic #2 // Field Main$1.$SwitchMap$Greeting:[I 3: aload_0 4: invokevirtual #3 // Method Greeting.ordinal:()I 7: iaload 8: lookupswitch { 1: 36 2: 39 default: 42 } 36: ldc #4 // String formal 38: areturn 39: ldc #5 // String informa

## R8 Optimization: Enum Ordinals and Names

DevFeed: [R8 Optimization: Enum Ordinals and Names](<https://devfeed.tech/articles/r8-optimization-enum-ordinals-and-names-20957.md>)

Original publisher: [Read original article](<https://jakewharton.com/r8-optimization-enum-ordinals-and-names/>)

Published: 2019-10-09T00:00:00Z

Content type: article

Language: en

Sources: [Jake Wharton](<https://devfeed.tech/sources/jake-wharton.md>)

Topics: [Optimization](<https://devfeed.tech/topics/optimization.md>), [R8](<https://devfeed.tech/topics/r8.md>), [Java](<https://devfeed.tech/topics/java.md>), [Android](<https://devfeed.tech/topics/android.md>), [Compiler](<https://devfeed.tech/topics/compiler.md>), [Data structures](<https://devfeed.tech/topics/data-structures.md>)

Tags: [android](<https://devfeed.tech/tags/android.md>), [compiler](<https://devfeed.tech/tags/compiler.md>), [display](<https://devfeed.tech/tags/display.md>), [enum](<https://devfeed.tech/tags/enum.md>), [java](<https://devfeed.tech/tags/java.md>), [optimization](<https://devfeed.tech/tags/optimization.md>), [r8](<https://devfeed.tech/tags/r8.md>), [serialization](<https://devfeed.tech/tags/serialization.md>)

### AI overview

This article explains how R8 optimizes Java enums in Android applications. It focuses on replacing compile-time-known enum ordinal lookups with integer values, enabling switch-branch elimination, and inlining enum name access when appropriate.

### Source excerpt

Note: This post is part of a series on D8 and R8, Android's new dexer and optimizer, respectively. For an intro to D8 read "Android's Java 8 support". For an intro to R8 read "R8 Optimization: Staticization". Enums are (and have always been!) a recommended way to model a fixed set of constants. Most commonly an enum only provides a set of possible constants and nothing more. But being full classes, enums can also carry helper methods and fields (both instance and static) or even implement interfaces. A common optimization for enums in tools that perform whole-program optimization is to replace simple occurrences (i.e., those which don't have fields, methods, or interfaces) with integer values. However, there are other optimizations which are applicable to all enums that are still available. Ordinal Each enum constant has an ordinal() which returns its position in the list of all constants. Since the ordinal range is always [0, N), it can be used for indexing into other zero-based data structures such as arrays or even bits. The most common usage is actually by the Java compiler itself for switch statements over enums. enum Greeting { FORMAL { @Override String greet(String name) { return "Hello, " + name; } }, INFORMAL { @Override String greet(String name) { return "Hey " + name + '!'; } }; abstract String greet(String name); static String type(Greeting greeting) { switch (greeting) { case FORMAL: return "formal"; case INFORMAL: return "informal"; default: throw new AssertionError(); } } } The compiled bytecode reveals the hidden call to ordinal(). [000a34] Greeting.type:(LGreeting;)Ljava/lang/String; 0000: invoke-virtual {v1}, LGreeting;.ordinal:()I 0003: move-result v1 ⋮ If we call this method with one of the constants, an opportunity for optimization presents itself. public static void main(String... args) { System.out.println(Greeting.type(Greeting.INFORMAL)); } As this is the only usage of type in our whole application, R8 inlines the method. [000b60] Greeter.ma

[Next page](<https://devfeed.tech/tags/r8.md?cursor=WyIyMDE5LTEwLTA5VDAwOjAwOjAwKzAwOjAwIiwgIjQ4ZWE1MGZlLTEyOGMtNGMwMy05YzBmLTdhY2NlZjA4YmJkNyJd>)