What's new in Kotlin 2.2.20-Beta1
The Kotlin 2.2.20-Beta1 release is out! Here are some details of this EAP release:
Kotlin/Native: support for stack canaries in binaries, smaller binary size for iOS targets, and improved debugger object summaries.
IDE support
The Kotlin plugins that support 2.2.20-Beta1 are bundled in the latest versions of IntelliJ IDEA and Android Studio. You don't need to update the Kotlin plugin in your IDE. All you need to do is change the Kotlin version to 2.2.20-Beta1 in your build scripts.
See Update to a new release for details.
Kotlin/JVM: support invokedynamic with when expressions
In Kotlin 2.2.20-Beta1, you can now compile when
expressions with invokedynamic
. Previously, when
expressions with multiple type checks compiled to a long chain of instanceof
checks in the bytecode.
Now you can use invokedynamic
with when
expressions to generate smaller bytecode, similar to the bytecode produced by Java switch
statements, when the following conditions are met:
All conditions except for
else
areis
ornull
checks.The expression doesn't contain guard conditions (
if
).The conditions don't include types that can't be type-checked directly, such as mutable Kotlin collections (
MutableList
) or function types (kotlin.Function1
,kotlin.Function2
, and so on).There are at least two conditions besides
else
.All branches check the same subject of the
when
expression.
For example:
With the new feature enabled, the when
expression in this example compiles to a single invokedynamic
type switch instead of multiple instanceof
checks.
To enable this feature, compile your Kotlin code with JVM target 21 or above and add the following compiler option:
Or add it to the compilerOptions {}
block of your build.gradle.kts
file:
This feature is Experimental. If you have any feedback or questions, share them in YouTrack.
Kotlin/Native
Kotlin 2.2.20-Beta1 brings improvements for Kotlin/Native binaries and debugging.
Support for stack canaries in binaries
Starting with 2.2.20-Beta1, Kotlin adds support for stack canaries in the resulting Kotlin/Native binaries. As part of stack protection, this security feature protects against stack smashing, mitigating some common application vulnerabilities. Already available in Swift and Objective-C, it's now supported in Kotlin as well.
How to enable stack canaries
The implementation of stack protection in Kotlin/Native follows the behavior of the stack protector in Clang.
To enable stack canaries, add the following property to your gradle.properties
file:
The property enables the feature for all the Kotlin functions that are vulnerable to stack smashing. Alternative modes are:
kotlin.native.binary.stackProtector=strong
, which uses a stronger heuristic for the functions vulnerable to stack smashing.kotlin.native.binary.stackProtector=all
, which enables stack protectors for all functions.
Note that in some cases, stack protection might come with a performance cost.
Smaller binary size for iOS targets
Kotlin 2.2.20-Beta1 introduces the smallBinary
option that can help you decrease the binary size for iOS targets. The new option effectively sets -Oz
as the default optimization argument for the compiler during the LLVM compilation phase.
With the smallBinary
option enabled, you can make release binaries smaller and improve build time. However, it might affect runtime performance in some cases.
How to enable smaller binary size
The new feature is currently Experimental. To try it out in your project, use the -Xbinary=smallBinary=true
compiler option or update your gradle.properties
file with:
For a specific binary, set the binaryOption("smallBinary", "true")
in your build.gradle.kts
file. For example:
The Kotlin team is grateful to Troels Lund for his help in implementing this feature.
Improved debugger object summaries
Kotlin/Native now generates clearer object summaries for debugger tools like LLDB and GDB. This improves the readability of the produced debug information and streamlines your debugging experience.
Previously, if you inspected an object such as:
You'd see limited information, including a pointer to the memory address:
With Kotlin 2.2.20-Beta1, the debugger shows richer details, including the actual values:
For more information on debugging in Kotlin/Native, see the documentation.
Kotlin/Wasm: separated npm dependencies
Previously, in your Kotlin/Wasm projects, all npm dependencies were installed together in your project folder. It included both your own dependencies and Kotlin tooling dependencies. These dependencies were also recorded together in your project's lock files (package-lock.json
or yarn.lock
).
As a result, whenever Kotlin tooling dependencies were updated, you had to update your lock files even if you didn't add or change anything.
Starting from Kotlin 2.2.20-Beta1, the Kotlin tooling npm dependencies are installed outside your project. Now, the tooling and the user dependencies have separate directories:
Tooling dependencies' directory:
<kotlin-user-home>/kotlin-npm-tooling/<yarn|npm>/hash/node_modules
User dependencies' directory:
build/wasm/node_modules
Also, the lock files inside the project directory contain only user-defined dependencies.
This improvement keeps your lock files focused only on your own dependencies, helps maintain a cleaner project, and reduces unnecessary changes to your files.
This change is enabled by default for the wasm-js
target. The change is not yet implemented for the js
target. While there are plans to implement it in future releases, the behavior of the npm dependencies remains the same for the js
target in Kotlin 2.2.20-Beta1.
Kotlin/JS: new DSL function for cleaner arguments
When running a Kotlin/JS application with Node.js, the arguments passed to your program (args
) used to include:
The path to the executable
Node
.The path to your script.
The actual command-line arguments you provided.
However, the expected behavior for args
was to include only the command-line arguments. To achieve this, you had to manually skip the first two arguments using the drop()
function inside your build.gradle.kts
file or in your Kotlin code:
This workaround was repetitive, error-prone, and didn't work well when sharing code between platforms.
To fix this issue, Kotlin 2.2.20-Beta1 introduces a new DSL function called passCliArgumentsToMainFunction()
.
With this function, the arguments only include the command-line arguments and exclude the Node
and script paths:
This change reduces boilerplate code, avoids mistakes caused by manually dropping arguments, and improves cross-platform compatibility.
To enable this feature, add the following DSL function inside your build.gradle.kts
file: