CONCEPT Cited by 1 source
Interlanguage null safety¶
Definition¶
Interlanguage null safety is the set of mechanisms —
annotations, static analysers, and runtime checks — that
keep null-related invariants intact when control crosses
a language boundary (e.g. Java ↔ Kotlin). The load-bearing
observation is that static-analysis-only null safety is
100% effective only at 100% coverage, which is infeasible
on any real codebase; every boundary crossing to unannotated
or third-party code is a potential NPE entry point.
Why it matters¶
Two languages in the same binary don't share a null-safety story unless the boundary enforces one. Three failure modes appear at interlanguage edges:
- Annotation absence. A Java method that forgot
@Nullablepassesnullto a Kotlin non-nullable parameter — translation-inferred nullability was wrong because the source annotation was wrong. - Coverage gap. Even 99%-
@NullsafeJava is not 100%: the remaining 1% dependents can silently injectnullinto a "safe" method. NPE risk is unbounded in the non-coverage. - Static analyser divergence. Kotlin's compiler is
stricter than Java's Nullsafe in certain cases (e.g.
class-level properties potentially nulled by another
thread), so translations legitimately need more
!!than the source had.
Kotlin's distinctive contribution: runtime checkNotNull¶
The biggest difference between null-safe Java and Kotlin is
that Kotlin inserts implicit checkNotNull calls at the
interlanguage boundary in bytecode, transforming null
safety from a static-only property into a runtime-enforced
one:
"The biggest difference between null-safe Java and Kotlin is the presence of runtime validation in Kotlin bytecode at the interlanguage boundary. This validation is invisible but powerful because it allows developers to trust the stated nullability annotations in any code they're modifying or calling." (Meta, 2024-12-18.)
After translation, a Kotlin fun doThing(s: String) carries
an "invisible checkNotNull(s) at the start of doThing's
body, so we can safely add a dereference to s, because if s
were nullable, this code would already be crashing." This
operationalises nullability: the runtime fails fast at
the boundary, so Kotlin code downstream can trust the type.
Java's static-analysis-only tools (@Nullsafe, NullAway)
don't have this property — a lie in an annotation can
silently propagate through a whole Java call chain.
The translation risk¶
When Meta translates Java doThing(String s) to Kotlin
doThing(s: String), someone has to take the initial
risk of inserting the implicit nonnull assertion. If the
Java s is actually sometimes null (because a dependent
forgot @Nullable), translation creates an NPE. Meta's
defences:
- Err toward nullable on inference. When context clues
are ambiguous, the Kotlinator picks
String?notString. - Scrutinise new
!!. Reviewers pay extra attention to!!inserted outside pre-existing dereferences —someMethodDefinedInJava(foo!!)is particularly suspicious because it combines a potentially-missing@Nullablewith an assertion that turns absence into a crash. - Runtime nullability telemetry. The long tail —
unannotated parameters + return types at interop
boundaries — is closed with a
javac plugin that collects actual null flows in
production and feeds codemods that backfill
@Nullable. See [[concepts/runtime-nullability- telemetry]].
Canonical wiki reference¶
sources/2024-12-18-meta-translating-10m-lines-of-java-to-kotlin — the 2024-12-18 Meta post is the wiki's canonical statement of interlanguage null safety as the load-bearing concept under any Java-to-Kotlin migration of scale.
Related¶
- concepts/kotlin-platform-type — Kotlin's type-system representation of values coming from unannotated Java.
- concepts/runtime-nullability-telemetry — the dynamic complement to static analysis.
- systems/nullsafe + systems/nullaway — the Java- side static analysers.
- systems/javac-plugin — the runtime-telemetry vehicle.
- systems/kotlinator — the Meta pipeline whose primary risk is this concept.
- concepts/bot-safer-than-human — how Meta mitigates the reviewer-error failure mode around this risk.