Improving Java Interop: Top-Level Functions and Properties

Kotlin has had top-level functions and properties from day one. They are very convenient in many cases: from basic utilities to extensions for standard APIs.

But Kotlin code is not the only client, and today I’m going to explain how we are planning to improve on the Java interop when it comes to calling top-level functions and properties.


Top-level functions are compiled to static methods in the byte code, so that


Or at least you can think of it this way. :)

Properties are very similar, only they are translated to a field and accessor(s):


Note the name of the class: BarPackage. It is derived from the short name of the package: bar. The rest is easy: static methods. So, we can refer to them from Java:

Package-parts and facades

In fact, it’s all a little trickier: top-level functions and properties become statics in Java classes, and we can access them through a class named after the package, yes, but that class is only a facade. The actual layout of the code is as follows:


Every source file is compiled into a separate class file. Even when they are in the same package. Those per-source-file classes are called package-parts. They contain all the actual byte code of methods and declare all the fields. So, all implementation resides in package-parts.

Then, a single package-facade class is generated that declares all the top-level functions and properties (again), and delegates implementations to the package-parts.


Why have a single facade. This is something we are going to change, but here’s the reasoning we followed a few years ago when we made this decision: having a single entry point class for Java clients seems to be as simple as it gets. Also, moving functions from one file to another doesn’t break anything since we refer to them only through the facade, don’t we? Win-win, isn’t it? Well, not quite in fact, but we’ll get to it later, and for now will just explain the rest of the design taking the need for a facade for granted.

Why package-parts. The main reason is initialization order for static fields. Indeed, consider these two files:



When we access a or b from Java, in what order should their initializers be called? In fact, it may be a very complicated question, because computeA() and computeB() may depend on one another (directly or indirectly, through other code). And they may have side-effects, so this actually matters.

So, Kotlin’s answer is:

  • inside a single file properties are initialized top-down,
  • upon the first access to any code in this file.

Loops may happen (and lead to errors), but this is inevitable and Java has it the same way with statics, doesn’t it? So the implementation piggybacks on the Java’s semantics for static class initializers: every file has its own package-part, which declares all the fields and initializes them in the <clinit> method (that corresponds to the static {...} initializer in the Java language). Thus fields are initialized upon first access. And we get thread-safety for free, which is a big plus. If not for package parts, we couldn’t make it work.

Package-part names

As you might have noticed in the picture above, package-parts tend to have weird names, such as BarPackage$file1$0fbe61c7.class. This consists, obviously, of a package-facade name (BarPackage), a short name of the source file (file1) and a hash-code of the absolute path to the source file. Yes, an ABSOLUTE path. There’s no other way to be sure that two package-part names won’t clash.

If you ever saw an exception stack trace from a Kotlin program, you probably noticed those hashes, they are just ugly. The bigger problem is that they may change when the project is built on another machine (which is not unlikely to have the source tree located in another directory). This may cause trouble, and it did, a few times.

Package-facade names, again

Now it’s time to talk about REAL trouble that keeps biting us and our users more or less all the time. Let’s face it: package-facade names do clash.

How it usually happens: you have two modules, a and b, and in a you have a top-level function declared inside the package. Everything is fine until you add another top-level function into the same package in another module, b. As soon as you do that, both modules generate class files with the same fully-qualified name:, and there’s no chance for the runtime to distinguish them. And you get a NoSuchMethodError, because only one of the two facades is loaded at run-time, and the function from the other one is not there.

(Compilation may break too, but it is not that bad.)

The new design

Well, it took me a while to explain how things work at the moment. But this was only to tell you that we are going to change it :)

So, the design described above has some problems:

  • package-facade clashes are painful and very likely in projects of considerable sizes,
  • package-part names are ugly because of hashes,
  • Java APIs are not that pretty with BarPackage all over them: those names are not very informative.

To mitigate these problems, we decided to:

  • get rid of the single-facade paradigm,
  • name package-parts after file names (Foo.kt -> Foo.class),
  • provide a file-level annotation to customize Java class names,
  • allow multiple files to have the same custom name for the cases where facades are actually relevant.


  • you can not have files with the same name if they declare members of the same package (e.g. both have package at the top),
  • you can refer to top-level functions from Java by the file name (,
  • renaming a file requires the clients to be recompiled, unless you have customized the class name with the annotation.

Example 1. By default, each file is compiled to a class named after it:



Example 2. We can change the name of the class by providing a file-level annotation:


regardless of the source file name.

Example 3. We can hide many package-parts generated for individual files behind a facade by specifying the same JVM name for many files:



generates File1.class and File2.class containing implementations and a facade:

A small bit on metadata

When we had a single package-facade, we could look into it and find all members of the package at once. Now there’s no single place to look into, and this may affect the compilation performance, so, for each module, the compiler will generate a special file META-INF/<module name>.kotlin_module and store a mapping from packages to package-parts there. This will facilitate rapid discovery of top-level members.


The new scheme liberates us from the issues of the old one. Class name clashes are still possible, but no more probable than they are for normal classes.

This blog post describes the design we are going to implement soon.
If you have feedback, it is very welcome!

About Andrey Breslav

Andrey is the lead language designer of Kotlin at JetBrains.
This entry was posted in Language design. Bookmark the permalink.

18 Responses to Improving Java Interop: Top-Level Functions and Properties

  1. Alex says:

    I especially like that libraries developed in Kotlin can now have clear static Java API like;

  2. An excellent post by Kotlin language lead Andrey Breslav and demonstrates very forward thinking with Java re-scheming.
    This exposition, however, should not diminish the importance of the most pressing issue to address in Project Kotlin, that being that in respect of the static (compile-time) type system.
    Everything else, even in pragmatic goodness, is really a side issue and likely a distraction.
    Let me emphasize that I am not an academic nor an ivory tower language priest but rather a pragmatist with scars-to-show-on-the-back experience of safety-critical software engineering systems. As such I subscribe vehemently to the safety afforded by static type systems* in programming languages (though they () are not the be-all and end-all silver bullet solution to all risks in software engineering).
    So much for the preamble, it is high-time that a new-coming programming language in the static-type/JVM-platform space puts a Silver Bullet through the very heart of java.lang.Object.
    Kotlin already has mechanism to mapping java.lang.Object to kotlin.Any.
    Now deprecate equals, hashCode and toString methods and reformulate these as interface methods pertaining to immutable types only.
    Figure out the dichotomy of mutable types versus immutable types.
    Invent some method that “prints out” an instance of a type *FOR DEBUGGING PURPOSES ONLY” but do not call it *toString
    Making this post with the best wishes for the success of Project Kotlin and also to provide an idea for the Kotlin team, to not only to improve upon Java syntax, but to strive for a level of pragmatism that seems to elude Scala.
    Justin Johansson
    (@MartianOdyssey on Twitter)

    That’s not all I have to say, but let’s start with tin-tacks in the first instance &
    definitely not wanting to wander into “creeping elegance” territory.

    • Andreas Sinz says:

      What are the benefits of pertaining equals/hashCode/toString only to immutable types?

      • Rob says:

        No equals/hashCode on mutable objects would generally imply that you could not use those mutable objects in Set’s or as keys in Map’s. Perhaps Justin is suggesting to ban it as opposed to being careful implementing equals/hashCode on mutable objects? Maybe Justin got burnt with that?

        Justin, do you have more explanation?

        • Justin Johansson says:

          Thanks Andreas & Rob for comments and sorry for delay in follow up. To clarify, my issue with toString has nothing to do with immutability (or equals or hashCode); just that the semantics of toString is so so ill-defined. e.g. Things like Thread.toString, File.toString etc just don’t make sense. However it would seem to be sensical to have a debug method on such things .. so perhaps Kotlin.Any.toDebugString or something like that would be an improvement. Just an idea.

          Regarding equals & hashCode methods, Rob captured my idea precisely. It makes little sense for x.equals(y) to return true at one moment in time and false at some other time if either x or y are mutated. Certainly I have seen nasty bugs arise in projects when people have used mutable instances as keys in Maps; just being careful is not good enough. Can we do any better?

          Now I don’t claim to have the best answer to the above issues but definitely the problems are well-known and well-defined. At this point in Kotlin language evolution, before the concrete sets, would it be fruitful to have a constructive debate on the mutable/immutable/equals/hashCode conundrum?


          • Andreas Sinz says:

            I never encountered a problem like that,
            but it sounds reasonable.

            How should kotlin keep the interop with java after this change? I mean java expects every object to have equals/hashCode/toString.

            • Justin Johansson says:

              My understanding is that kotlin.Any is not quite the same thing as java.lang.Object; that Kotlin performs a mapping between the Kotlin type and the (Java) platform type. If my understanding is correct, then plausibly Kotlin may be able to use slight-of-hand to deprecate and refactor “legacy” methods present in kotlin.Any and relegate these to a new subtype of kotlin.Any with better defined semantics. Just a suggestion. The Kotlin compiler team would be in the best position to comment further I suppose.

    • Thanks for the comment and sorry for the late reply. Unfortunately, I am not aware of a design that would be both Java-compatible enough and have the properties you are seeking. If you have any concrete implementation ideas, we are open for discussion

  3. Justin Johansson says:

    Ignore this comment. WordPress application problem. I want to subscribe to my posts here. Posted to get another email to confirm subscription.

  4. TB says:

    This is a great news, thanks.

    But, I also wish that it can be more simple like Swift’s extension which is much like partial class in C# but in a lot more powerful way.

    Why I need this so much is because, I prefer to code in a more like scripting-like codes.
    Top-Level function did that. I can separate logic in any file that I wanted rather than traditional Java-like code where everything must fit in a single file which is hard to read and manage.

    But, to do inheritance, top-level function can’t. Which I think is a missing feature.

    • You can either use inheritance OR free functions. There’s no sane way of combining the two. When you need inheritance simple use classes or object declarations.

  5. Ian Mackenzie says:

    What happens if I have a class named Something and one or more top-level functions in a file something.kt? Do the top-level functions and Something class itself get merged into a single generated Something.class, or is this a conflict that has to be avoided using @file:jvmName? If it’s a conflict, does it still exist if there are no top-level functions or in that case can the file name and class name match? What if the Something class has @platformStatic members in its companion object? Does everything just get happily merged into a Something class with some static members from the @platformStatic members and some from the file’s top-level functions?

    I apologize if I’m missing something fundamental here – I’ve played around with some code online and in IntelliJ IDEA but haven’t done any ‘real work’ in it.

    • When a class name of a declared class clashes with the package-part name derived from the same source file (the file has to have free functions, no functions => no package part), the package-part will be automatically renamed to Something_. If the source files are different, e.g. the class sits in Something_class.kt and the functions in something.kt, it is an error, and must be resolved by renaming something (one option is to use the jvmName annotation).

      @platformStatic does not affect naming in any way and can not interfere.

  6. Rob says:

    For what it’s worth I think the explanation of the change is clear and solution seems very good (simple and effective). No I would personally not go further in terms of name clashing – people need to have some level of sensible.

  7. Mano says:

    Awesome thanks, this was something we always wondered on the way it was done. It makes lot of sense now.

    We are using kotlin in our startup for everything except the web(Java 8 with spark framework) and it has been awesome so far.

    A few improvements/suggestions for kotlin:
    Map, List and Set Literal:
    I believe I saw it in some other blog post comment and you had asked what is the issue with using mapOf, listOf, etc.

    mapOf, setOf works well as long as we use them for a simple map or set. However providing a literal gives more freedom of expressing them.

    Consider for e.g.
    { name: “Mano”, gender: “M”, languages: [“Java”, “Kotlin”, “C#” }
    compared to
    mapOf(“name” to “Mano”, “gender” to “M”, “languages” to listOf(“Java”, “Kotlin”))

    Languages that provide literals tend to use them more often than languages that dont e.g. Clojure, Ruby, Javascript. In languages like kotlin, C#, java, Scala – due to the lack of expressiveness (may be wrong here just an assumption) users resort to classes instead of a place where a simple map would have been sufficient.

    Stack trace not having correct line numbers
    When an exception happens the line numbers are completely messed up. We have a module with lot of functions in it. If an exception happens in any of the method, the stack trace has the last line of the module and then next trace as the first line of the module. It does tell the correct method name but messes up the line numbers.

    This is the part that scares us a bit since it may be tough to find errors when we go live (whenever that is).

    KDoc is not appearing in Java code
    When I press F1 from kotlin code I can see the doc. However when I press F1 for the same class from Java I dont see any doc.

    Async/await (like in C#) to enable devs to start writing async code in a comfortable way

    Waiting for version 1.0 release of Kotlin. Thanks for a clean and well thought out language.

    • Dmitry Jemerov says:

      Thanks for your feedback! I’ve filed for the KDoc issue. I’ll let my colleagues address the other points.

      • Nicolas says:

        Map and List literals would definitely be a great addition. This is especially useful when manipulating JSON data and it is what makes Javascript a perfect fit for that.
        Groovy supports this as well:

        def map = [
        name: “someone”,
        age: 40,
        info: [1,2,3]

Comments are closed.