How Meta Spent 4.5 Years Automating Java‑to‑Kotlin Migration and What Lies Ahead
Meta has spent four and a half years building a custom, six‑stage Kotlinator pipeline to automatically translate its massive Android Java codebase to Kotlin, tackling null‑safety, build‑time, and headless J2K challenges, and now reports that only half the work is complete while the hardest problems remain.
Since 2020 Meta has made Kotlin the primary language for Android development, but most of its existing Java code remained untouched. To fully exploit Kotlin’s productivity and null‑safety benefits, Meta decided to rewrite roughly ten million lines of well‑functioning Java code.
The goal is to translate virtually all actively developed code and core dependency‑graph code, because any legacy Java that lacks null‑safety can introduce NPEs. Meta also wants to reduce the drawbacks of a mixed Java/Kotlin codebase, such as slower builds and the need to maintain parallel toolchains.
Manual use of IntelliJ’s J2K button proved impossible at Meta’s scale—each click required minutes and would need to be repeated tens of thousands of times. Consequently, Meta built an automated pipeline called Kotlinator , which consists of six stages:
Deep build : a full build so the IDE can resolve all symbols, including third‑party dependencies.
Pre‑processing : a custom Editus tool runs about 50 steps handling nullability, J2K work‑arounds, and custom DI framework changes.
Headless J2K : a server‑friendly version of the familiar J2K converter.
Post‑processing : roughly 150 Android‑specific steps plus additional nullability adjustments to make the generated Kotlin code natural.
Linter testing : automatic lint fixes that bridge conversion diffs with regular diffs.
Error‑based repair : after a conversion, Kotlinator parses build errors and applies further fixes.
Creating a headless J2K required an IntelliJ plugin that extends ApplicationStarter and directly invokes JavaToKotlinConverter. This approach allows remote, batch conversion without blocking developers’ IDEs and reduces overall developer time despite a typical remote conversion taking about 30 minutes.
Meta also built an internal cron‑style system that generates daily diffs (Meta‑style pull requests), selects reviewers, and provides a web UI for on‑demand remote conversion. The system does not enforce a strict order; it processes any file that meets the active‑development or core‑dependency criteria.
Because the original J2K output often produced unbuildable diffs, Meta added custom pre‑ and post‑processing stages—over 200 steps in total—implemented on top of internal metaprogramming tools that use JetBrains’ Java and Kotlin PSI libraries. These steps can analyze and transform both Java‑to‑Java and Kotlin‑to‑Kotlin code, but they sometimes give up when type information from third‑party libraries is unavailable.
Meta discovered that leaving subtle conversions to machines is safer; many automatic fixes reduce human error. For example, a null‑safe Java method annotated with @Nullsafe can be safely dereferenced after conversion because the Kotlin bytecode inserts an invisible checkNotNull(s) call:
@Nullsafe
public class MyNullsafeClass {
void doThing(String s) {
// can we safely add this dereference?
// s.length;
}
} class MyNullsafeClass {
fun doThing(s: String) {
// there's an invisible `checkNotNull(s)` here in the bytecode
// so adding this dereference is now risk‑free!
// s.length
}
}However, adding unnecessary non‑null assertions (e.g., !!) can still cause NPEs, so Meta runs dozens of complementary modules that scan for missing @Nullable annotations and suggest safer types.
Beyond null‑safety, Meta identified dozens of other pitfalls—such as confusing initialization with getters or handling nullable booleans—and encoded fixes for them. After more than 40 000 conversions, Meta reports that over half of its Android Java code has been successfully migrated, but the remaining half is considerably more complex.
Meta’s future work focuses on extending custom steps, contributing back to the open‑source J2K project, and achieving fully automated, safe conversion for the remaining thousands of code paths.
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.
Java Tech Enthusiast
Sharing computer programming language knowledge, focusing on Java fundamentals, data structures, related tools, Spring Cloud, IntelliJ IDEA... Book giveaways, red‑packet rewards and other perks await!
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.
