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:
final
always- Same visibility with the original function
Note: All the bridges in a final
class are final.
Features of generated bridges:
open
always- 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:
open
always- With
default
implementations - 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
,protected
or@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
private
or insideprivate
orinternal
class - is
internal
without@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
inline
class - has parameter types or return type that is
inline
classes
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
private
classes, interfaces, enums or objects.
(TODO)
Reported when overriding generated bridges from Java or Kotlin.