What's new in Kotlin 2.4.0-Beta2
The Kotlin 2.4.0-Beta2 release is out! Here are some details of this EAP release:
Standard library: Stable UUIDs and support for checking sorted order
Kotlin/JVM: Support for Java 26 and annotations in metadata enabled by default
Kotlin/Native: Support for Swift packages as dependencies, updates on Swift export, and default CMS GC
Kotlin/Wasm: Incremental compilation enabled by default and support for WebAssembly Component Model
Kotlin/JS: Support for value class export and ES2015 features in JS code inlining
Gradle: Compatibility with Gradle 9.4.1
Maven: Automatic alignment between Java and JVM target versions
Kotlin compiler: More consistent inline function behavior during
.klibcompilation
Update to Kotlin 2.4.0-Beta2
The latest version of Kotlin is included in the latest versions of IntelliJ IDEA and Android Studio.
To update to the new Kotlin version, make sure your IDE is updated to the latest version and change the Kotlin version to 2.4.0-Beta2 in your build scripts.
New features
In previous Kotlin releases, several new features were introduced as Experimental. The following features have now graduated to Stable in Kotlin 2.4.0-Beta2, so you no longer need to opt in to use them:
New features
Language
Kotlin 2.4.0-Beta2 promotes context parameters, explicit backing fields, and annotation use-site targets features to Stable. This release also introduces explicit context arguments for context parameters.
Stable features
Kotlin 2.2.0 introduced a few language features as Experimental. We're happy to announce that the following language features are now Stable in this release:
Context parameters, except for context arguments and callable references
See the full list of Kotlin language design features and proposals.
Explicit context arguments for context parameters
Kotlin 2.4.0-Beta2 introduces explicit context arguments for context parameters.
Kotlin 2.3.20 changed the overload resolution for context parameters. As a result, calls to overloads that differ only by context parameters can become ambiguous.
You can now resolve this ambiguity by passing an explicit context argument at the call site.
Here's an example:
You can also use explicit context arguments instead of the context() function to reduce nesting and make some calls easier to read. If you need to use the same context arguments in multiple calls, use the context() function instead.
This feature is Experimental. To opt in, add the following compiler option to your build file:
For more information, see the feature's KEEP.
Support for collection literals
Kotlin 2.4.0-Beta2 introduces experimental support for collection literals. You can now create collections in a simpler and more concise way using brackets [].
For example:
If the compiler doesn't have enough information to infer the collection type, it defaults to the List type:
You can also declare custom operator fun of functions to use bracket syntax with your own types. For example, if you have the following DoubleMatrix class:
You can create an identityMatrix class instance like this:
In this example, the compiler translates the nested collection literals into calls to the corresponding operator fun of functions. The compiler resolves these calls recursively and uses the expected types to choose the correct overloads.
This feature is Experimental. To opt in, add the following compiler option to your build file:
For more information, see the feature's KEEP.
Improved compile-time constants
Kotlin 2.4.0-Beta2 brings experimental improvements to compile-time constants, making support for numeric and string types more consistent and easier to use. These improvements include support for:
Unsigned type operations.
Standard library functions for strings, like
.lowercase(),.uppercase(), and.trim()functions.Evaluation of the
.nameproperty of enum constants and theKCallableinterface.
To make it clear which functions are evaluated at compile time, Kotlin 2.4.0-Beta2 introduces the IntrinsicConstEvaluation annotation. Some functions are evaluated at compile-time but don't have the annotation yet. Later releases will add the annotation to the remaining functions. For a list of supported functions, see the KEEP appendix.
This feature is Experimental. To opt in, add the following compiler option to your build file:
For more information, see the feature's KEEP.
Standard library
Kotlin 2.4.0-Beta2 stabilizes support for UUIDs in the common Kotlin standard library. It also adds new extension functions for converting unsigned integers to BigInteger on the JVM and support for checking sorted order.
Stable UUIDs in the common Kotlin standard library
Kotlin 2.0.20 introduced a class for generating UUIDs (universally unique identifiers) and added support for converting between Kotlin and Java UUIDs. Later releases gradually improved this experimental feature by adding support for:
In Kotlin 2.4.0-Beta2, the kotlin.uuid.Uuid API becomes Stable. The only exceptions are the functions for generating V4 and V7 UUIDs, which remain Experimental and still require opt-in.
Support for checking sorted order
Kotlin 2.4.0-Beta2 adds new extension functions for checking sorted order in iterables, arrays, and sequences.
This includes the following extension functions:
.isSorted().isSortedDescending().isSortedWith(comparator).isSortedBy(selector).isSortedByDescending(selector)
You can use these extension functions to check whether elements are already sorted without sorting them again or creating your own helper functions. They return true if the elements are in the specified order, or if there are fewer than two elements, and false otherwise. These functions stop as soon as they encounter an out-of-order pair, which makes them efficient for large inputs.
Here's an example of checking sorted order with .isSorted() and .isSortedBy() functions:
We would appreciate your feedback in YouTrack.
New API for converting unsigned integers to BigInteger on the JVM
Kotlin 2.4.0-Beta2 introduces the UInt.toBigInteger() and ULong.toBigInteger() extension functions on the JVM.
Previously, converting UInt and ULong values to BigInteger required string-based workarounds or custom conversion logic. Starting with Kotlin 2.4.0-Beta2, you can now use .toBigInteger() to convert unsigned integer values directly to BigInteger.
Here's an example:
We would appreciate your feedback in YouTrack.
Kotlin/JVM
Kotlin 2.4.0-Beta2 supports a new Java version and enables annotations in metadata by default.
Support for Java 26
Starting with Kotlin 2.4.0-Beta2, the compiler can generate classes containing Java 26 bytecode.
Annotations in metadata enabled by default
The Kotlin Metadata JVM library in Kotlin 2.2.0 introduced support for reading annotations stored in Kotlin metadata. With this support, the Kotlin compiler writes annotations into metadata alongside the JVM bytecode, making them accessible to the Kotlin Metadata JVM library. As a result, annotation processors and other tools can understand and manipulate these annotations at the metadata level without using reflection or modifying source code.
In Kotlin 2.4.0-Beta2, this support is enabled by default.
Kotlin/Native
Kotlin 2.4.0-Beta2 brings support for Swift package import, improved interoperability through Swift export, and default concurrent marking in the garbage collector.
Swift package import
Kotlin Multiplatform projects now can declare Swift packages as dependencies for an iOS app in their Gradle configuration:
For working samples and more detailed information, see SwiftPM import.
If your project relies on CocoaPods dependencies, you can migrate the current setup to use Swift packages. The KMP tooling accounts for this use case and helps you reconfigure the project automatically. For details, see our CocoaPods migration guide.
Swift export: Support for exporting coroutine flows
Kotlin 2.4.0-Beta2 further improves Kotlin's interoperability with Swift through Swift export by adding support for exporting kotlinx.coroutines flows to Swift.
Flows in kotlinx.coroutines represent an asynchronous stream of data that can be emitted and consumed concurrently. They are commonly used for reactive programming patterns, such as listening for database updates, network requests, or UI events.
Previously, the only way to expose the Flow interface from kotlinx.coroutines.flow to Swift was through third-party solutions. Now you can export flows out of the box into Swift's idiomatic counterpart: AsyncSequence.
The feature is enabled by default. You can export any public API with the Flow type to Swift while preserving type information. For example:
For more information about Swift export, see our documentation.
Default concurrent marking in garbage collector
In Kotlin 2.0.20, the Kotlin team introduced experimental support for the concurrent mark and sweep garbage collector (CMS GC). After processing user feedback and fixing regressions, we are now ready to enable CMS by default, starting with Kotlin 2.4.0-Beta2.
The previous default parallel mark concurrent sweep (PMCS) setup in the garbage collector had to pause application threads while the GC marked objects in the heap. In contrast, CMS allows the marking phase to run concurrently with application threads.
This significantly improves GC pause duration and app responsiveness, which is important for the performance of latency-critical applications. CMS has already demonstrated its effectiveness in benchmarks for UI applications built with Compose Multiplatform.
If you face problems, you can switch back to PMCS. To do that, set the following binary option in your gradle.properties file:
For more information on the Kotlin/Native garbage collector, see our documentation.
Kotlin/Wasm
Kotlin 2.4.0-Beta2 enables incremental compilation for Kotlin/Wasm by default and introduces support for the WebAssembly Component Model.
Incremental compilation enabled by default
Kotlin/Wasm introduced incremental compilation in 2.1.0. Starting with Kotlin 2.4.0-Beta2, it is Stable and enabled by default. With this feature, the compiler rebuilds only the files affected by recent changes, which significantly reduces build time.
To disable incremental compilation, add the following line to your project's local.properties or gradle.properties file:
If you run into any issues, report them in our YouTrack
Support for the WebAssembly Component Model
Kotlin/Wasm goes a step further in Kotlin 2.4.0-Beta2 by introducing experimental support for the WebAssembly Component Model. The proposal defines a way to build components from Wasm modules through standardized interfaces and types. This approach helps Wasm evolve from a low-level binary instruction format into a system for composing reusable, language-agnostic components. It enables Kotlin/Wasm to go beyond the browser. For example, Kotlin and WebAssembly are well suited for Function-as-a-Service, also known as FaaS or serverless, applications.
To try this feature, check out a simple server built with wasi:http.

Share your feedback in YouTrack.
Kotlin/JS
Kotlin 2.4.0-Beta2 adds support for value class export to JavaScript/TypeScript and ES2015 features when inlining JS code.
Support for value class export to JavaScript/TypeScript
Previously, only regular Kotlin classes could be exported to JavaScript/TypeScript. Kotlin 2.4.0-Beta2 lifts that limitation. You can now export Kotlin's inline value classes as regular TypeScript classes.
To export a value class, mark it with the @JsExport annotation on the Kotlin side:
From the TypeScript side, it looks like a regular class:
For more information, see @JsExport annotation.
Support for ES2015 features when inlining JS code
Starting with Kotlin 2.4.0-Beta2, JavaScript code inlining has full support for ES2015 features.
It's useful for interoperability with third-party libraries, as well as for direct control over automatic application code generation.
Now you can use modern JS features inside js() calls, including:
Lambdas (arrow functions)
ES classes
Template strings
Spread operators
constandletvariable declarationsGenerators
Remember that the parameter of the js() function should be a string constant because it's parsed at compile time and translated to JavaScript code "as-is". For example, for the spread operator, use:
For more information on inlining inline JavaScript code, see our documentation.
Gradle
Kotlin 2.4.0-Beta2 is fully compatible with Gradle 7.6.3 through 9.4.1. You can also use Gradle versions up to the latest Gradle release. However, be aware that doing so may result in deprecation warnings, and some new Gradle features might not work.
Maven
Kotlin 2.4.0-Beta2 makes project configuration even easier with automatic alignment between Java and JVM target versions.
Automatic alignment between Java and JVM target versions
To simplify project configuration and prevent compatibility issues, the Kotlin Maven plugin now automatically aligns the JVM target version with the Java compiler version configured in the project.
This ensures that the Kotlin and Maven compilers target the same bytecode version, avoiding issues where Kotlin-generated bytecode is incompatible with the rest of the project or the intended deployment environment.
With the <extensions> option enabled, you don't need the kotlin.compiler.jvmTarget property. If it's not already defined, the Kotlin Maven plugin automatically resolves the JVM target version in the following order:
As the
maven.compiler.releaseversion defined either as a project property or within themaven-compiler-pluginconfiguration.In this case, both
jvmTargetandjdkReleasecompiler options are set for the Kotlin compiler, limiting the API to a specific JDK version.As the
maven.compiler.targetversion in case the Maven release version is not set. The compiler target can be defined either as a project property or within themaven-compiler-pluginconfiguration.In this case, only Kotlin's
jvmTargetis set and the API is not limited to a specific JDK version.
This greatly simplifies your Kotlin project configuration, so your pom.xml file can look like this:
During the build, the plugin outputs a similar message:
For more information about automatic project configuration, see our documentation.
Kotlin compiler
Kotlin 2.4.0-Beta2 includes more consistent behavior for inline functions declared in the same module during .klib compilation.
Consistent intra-module function inlining during klib compilation
Previously, function inlining behaved inconsistently on different Kotlin platforms. The JetBrains team is working to unify it across all supported platforms to ensure the same compatibility guarantees.
On the Kotlin/JVM, function inlining happens at compile time. So, when Kotlin sources are compiled with the Kotlin/JVM compiler, the resulting class files have no inline function calls in the bytecode because the bodies of inline functions are inlined into their call sites, so their behavior is fixed during compilation.
On the contrary, on Kotlin/Native, Kotlin/JS, and Kotlin/Wasm, function inlining did not happen during source-to-klib compilation, only during binary generation. As a result, the behavior of inline functions wasn't fixed during .klib compilation, and .klib libraries didn't provide the same compatibility guarantees for inline functions as Kotlin/JVM does.
Kotlin 2.4.0-Beta2 takes the first step in unifying the behavior of inline functions by enabling intra-module inlining when generating .klib artifacts:
When compiled to a .klib, the code looks something like:
This means only inline functions declared in the same module are inlined during .klib compilation. Other functions, in this case, are inlined during the generation of platform-specific binaries.
How to enable
Starting with 2.4.0-Beta2, the intra-module inlining is enabled by default for Kotlin/Native, Kotlin/JS, and Kotlin/Wasm.
If you face unexpected problems with this feature, you can disable it using the following compiler option in the command line:
The next step is to enable cross-module inlining to ensure all inline functions in the project are consistently inlined. This change is planned for future Kotlin releases, but you can already try it out using the following compiler option in the command line:
Please share your feedback and report any problems in YouTrack.