This file describes the behavior that compiler shows when dealing with @JvmBlockingBridge.
For functions that are capable to have blocking bridges (with the following strategies),
the Kotlin Blocking Bridge compiler plugin will generate an additional function, with the same method signature,
but without suspend modifier, to make it callable from Java.
Features of generated bridges:
finalalways- Same visibility with the original function
Note: All the bridges in a final class are final.
Features of generated bridges:
openalways- Same visibility with the original function
If a superclass have bridge functions, blocking bridges will not generate in child classes unless explicitly specified @JvmBlockingBridge.
Example:
abstract class A {
@JvmBlockingBridge
abstract suspend fun test()
@JvmBlockingBridge
abstract suspend fun test2()
}
class B : A() {
@JvmBlockingBridge
override suspend fun test()
override suspend fun test2()
}Compilation result:
abstract class A {
@JvmBlockingBridge
abstract suspend fun test()
@JvmBlockingBridge
abstract suspend fun test2()
@GeneratedBlockingBridge
open fun test()
@GeneratedBlockingBridge
open fun test2()
}
class B : A() {
@JvmBlockingBridge
override suspend fun test()
override suspend fun test2()
@GeneratedBlockingBridge
open override fun test() // because `test` declared in `B` has explicit `@JvmBlockingBridge`
// `test2` absent, because `test2` in `B` doesn't have explicit `@JvmBlockingBridge`
}Available only when targeting JVM 8 or higher
Features of generated bridges:
openalways- With
defaultimplementations - Same visibility with the original function
- Following inheritance rules with Function inheritance
Example:
interface A {
@JvmBlockingBridge
suspend fun test()
@JvmBlockingBridge
suspend fun test2()
}
class B : A() {
@JvmBlockingBridge
override suspend fun test()
override suspend fun test2()
}Compilation result:
interface A {
@JvmBlockingBridge
suspend fun test()
@JvmBlockingBridge
suspend fun test2()
@GeneratedBlockingBridge
fun test() { /* call suspend test() */ } // 'default' implementation, which is supported by Java 8+
@GeneratedBlockingBridge
fun test2() { /* call suspend test2() */ } // 'default' implementation, which is supported by Java 8+
}
class B : A() {
@JvmBlockingBridge
override suspend fun test()
override suspend fun test2()
@GeneratedBlockingBridge
open override fun test() // because `test` declared in `B` has explicit `@JvmBlockingBridge`
// `test2` absent, because `test2` in `B` doesn't have explicit `@JvmBlockingBridge`
}When function is annotated with @JvmSynthetic, no blocking bridge will be generated for it.
@JvmOverloads and @JvmName is useful to blocking bridges.
When @JvmBlockingBridge is applied on classes, all the suspend functions will be checked about capability of having blocking bridges, which is:
- effectively public:
public,protectedor@PublishedApi - not
@JvmSynthetic
@JvmBlockingBridge
class A {
suspend fun test()
}Compilation result:
@JvmBlockingBridge
class A {
@GeneratedBlockingBridge
fun test()
}IntelliJ plugin will add an inlay hint of @JvmBlockingBridge onto the functions that is going to have blocking bridges generated.
When enabled in build.gradle by
blockingBridge {
enableForModule = true
}all suspend functions will be compiled with a blocking bridge if possible.
This is practically like adding @JvmBlockingBridge to every suspend functions and suppress errors if not applicable.
In other words, if function has the following characteristics, they do not have blocking bridges. Otherwise, they do.
- is not
suspend - is local (e.g., inside another function)
- is
privateor insideprivateorinternalclass - is
internalwithout@PublishedApi - has
@JvmSynthetic(invisible from Java) - is top-level but not using IR compiler
- uses inline classes as parameter or return type but not using IR compiler
- is inside interface but JVM target is below 8 (default implementation in interface not supported)
IntelliJ plugin will show you an inlay hint on the capable functions that may be 'inferred' a @JvmBlockingBridge.
| Name | Values | Description |
|---|---|---|
unit-coercion |
VOID, COMPATIBILITY |
Strategy on mapping from Unit to void in JVM backend. VOID by default (recommended). |
enableForModule |
true, false |
Generate blocking bridges for all suspend functions in the module where possible. |
Reported when @JvmBlockingBridge is applied to a function which is either:
- not
suspend - declared in Java class
Reported when @JvmBlockingBridge is applied to a function which either:
- is in
inlineclass - has parameter types or return type that is
inlineclasses
Reported when @JvmBlockingBridge is applied to a function in an interface, and the JVM target is below 8
(Since 1.1.0)
Codegen extensions for top-level functions are not available in the old JVM backend. The compiler plugin generate bridges for top-level functions only if using IR backend, otherwise, an error TOP_LEVEL_FUNCTIONS_NOT_SUPPORTED will be reported.
Reported when @JvmBlockingBridge is applied to a function which is either:
private- in
privateclasses, interfaces, enums or objects.
(TODO)
Reported when overriding generated bridges from Java or Kotlin.