> The existing huge mass of JVM libraries use null, so by embracing that rather than adding a new wrapper object like Scala's Option (or even JDK 8+'s Optional), Kotlin works smoothly with all those libraries.
Recent JVM libraries have (rightly) moved away from null. Using e.g. JDK8 streams from Kotlin is very cumbersome (noticeably more cumbersome than using them from Scala). The special treatment of interop also creates a bunch of special cases in the language that break your usual assumptions: extracting a common method call won't always work, adding explicit types can change behaviour. It's one of those things that looks like a good idea in the small but creates more problems in the large.
> And with some annotations, Kotlin's nullability support can be applied to those existing libraries.
Again this is a case of Kotlin refusing to learn from history. Look at what happened with the JSR308 checker and adding nullness annotations to existing libraries. Someone adds the annotations and everything seems great, then other people make changes to the library and don't maintain the annotations and they become lies.
> As for zero overhead, an Option or Optional is another object, and the overhead of that object can't be completely optimized away by the JIT.
People who care about zero overhead wouldn't be using Kotlin in the first place. The raison d'etre of the JVM is safer programming with fewer crashes, even if that means a little performance overhead some of the time. (For the record you're wrong: in the cases where the JVM stack-allocates an option or optional the memory pattern is exactly the same as if you'd used a nullable value instead. But that's not the point).