0
# JVM Integration
1
2
Platform-specific features for JVM including executor integration, CompletableFuture interoperability, thread-local context elements, and Java ecosystem integration.
3
4
## Capabilities
5
6
### Executor Integration
7
8
Converting Java executors to coroutine dispatchers and vice versa.
9
10
```kotlin { .api }
11
/** Converts Executor to CoroutineDispatcher */
12
fun Executor.asCoroutineDispatcher(): ExecutorCoroutineDispatcher
13
14
/** Converts CoroutineDispatcher to Executor */
15
fun CoroutineDispatcher.asExecutor(): Executor
16
17
/** ExecutorCoroutineDispatcher with close capability */
18
abstract class ExecutorCoroutineDispatcher : CoroutineDispatcher(), Closeable {
19
abstract val executor: Executor
20
abstract override fun close()
21
}
22
23
/** Creates single-threaded dispatcher */
24
fun newSingleThreadContext(name: String): ExecutorCoroutineDispatcher
25
26
/** Creates fixed thread pool dispatcher */
27
fun newFixedThreadPoolContext(nThreads: Int, name: String): ExecutorCoroutineDispatcher
28
```
29
30
**Usage Examples:**
31
32
```kotlin
33
import kotlinx.coroutines.*
34
import java.util.concurrent.*
35
36
fun main() = runBlocking {
37
// Convert existing Executor to CoroutineDispatcher
38
val executor = Executors.newFixedThreadPool(4)
39
val dispatcher = executor.asCoroutineDispatcher()
40
41
val job = launch(dispatcher) {
42
println("Running on executor thread: ${Thread.currentThread().name}")
43
delay(100)
44
println("Coroutine completed on: ${Thread.currentThread().name}")
45
}
46
47
job.join()
48
dispatcher.close() // Important: close custom dispatchers
49
50
// Create coroutine dispatchers with specific thread pools
51
val singleThreadDispatcher = newSingleThreadContext("SingleThread")
52
val fixedPoolDispatcher = newFixedThreadPoolContext(8, "FixedPool")
53
54
launch(singleThreadDispatcher) {
55
repeat(3) { i ->
56
println("Single thread task $i: ${Thread.currentThread().name}")
57
delay(100)
58
}
59
}
60
61
List(10) { i ->
62
launch(fixedPoolDispatcher) {
63
println("Pool task $i: ${Thread.currentThread().name}")
64
delay(50)
65
}
66
}.forEach { it.join() }
67
68
// Cleanup
69
singleThreadDispatcher.close()
70
fixedPoolDispatcher.close()
71
}
72
73
// Custom executor example
74
fun customExecutorExample() = runBlocking {
75
val customExecutor = ThreadPoolExecutor(
76
2, 4, 60L, TimeUnit.SECONDS,
77
LinkedBlockingQueue(),
78
ThreadFactory { r -> Thread(r, "CustomThread-${System.currentTimeMillis()}") }
79
)
80
81
val customDispatcher = customExecutor.asCoroutineDispatcher()
82
83
repeat(6) { i ->
84
launch(customDispatcher) {
85
println("Custom executor task $i: ${Thread.currentThread().name}")
86
delay(200)
87
}
88
}
89
90
delay(1000)
91
customDispatcher.close()
92
}
93
```
94
95
### CompletableFuture Integration
96
97
Seamless interoperability with Java's CompletableFuture API.
98
99
```kotlin { .api }
100
/** Converts CompletableFuture to Deferred */
101
fun <T> CompletableFuture<T>.asDeferred(): Deferred<T>
102
103
/** Suspends until CompletableFuture completes */
104
suspend fun <T> CompletableFuture<T>.await(): T
105
106
/** Converts Deferred to CompletableFuture */
107
fun <T> Deferred<T>.asCompletableFuture(): CompletableFuture<T>
108
109
/** Converts Job to CompletableFuture<Unit> */
110
fun Job.asCompletableFuture(): CompletableFuture<Unit>
111
112
/** Creates CompletableDeferred that can be converted to CompletableFuture */
113
fun <T> CompletableDeferred<T>.asCompletableFuture(): CompletableFuture<T>
114
```
115
116
**Usage Examples:**
117
118
```kotlin
119
import kotlinx.coroutines.*
120
import kotlinx.coroutines.future.*
121
import java.util.concurrent.CompletableFuture
122
123
fun main() = runBlocking {
124
// CompletableFuture to Coroutines
125
val future = CompletableFuture.supplyAsync {
126
Thread.sleep(500)
127
"Future result"
128
}
129
130
// Convert to Deferred
131
val deferred = future.asDeferred()
132
println("Deferred result: ${deferred.await()}")
133
134
// Direct await
135
val anotherFuture = CompletableFuture.supplyAsync {
136
Thread.sleep(200)
137
42
138
}
139
140
val result = anotherFuture.await()
141
println("Awaited result: $result")
142
143
// Coroutines to CompletableFuture
144
val coroutineDeferred = async {
145
delay(300)
146
"Coroutine result"
147
}
148
149
val convertedFuture = coroutineDeferred.asCompletableFuture()
150
println("Converted future result: ${convertedFuture.get()}")
151
152
// Job to CompletableFuture
153
val job = launch {
154
delay(100)
155
println("Job completed")
156
}
157
158
val jobFuture = job.asCompletableFuture()
159
jobFuture.get() // Wait for job completion
160
}
161
162
// Integration with existing Java APIs
163
class LegacyService {
164
fun fetchDataAsync(): CompletableFuture<String> {
165
return CompletableFuture.supplyAsync {
166
Thread.sleep(1000)
167
"Legacy data"
168
}
169
}
170
171
fun processDataAsync(data: String): CompletableFuture<String> {
172
return CompletableFuture.supplyAsync {
173
Thread.sleep(500)
174
"Processed: $data"
175
}
176
}
177
}
178
179
suspend fun modernServiceIntegration() {
180
val legacyService = LegacyService()
181
182
// Use legacy services with coroutines
183
val data = legacyService.fetchDataAsync().await()
184
val processedData = legacyService.processDataAsync(data).await()
185
186
println("Modern integration result: $processedData")
187
}
188
189
// Exposing coroutines to Java clients
190
class ModernService {
191
// Expose coroutine as CompletableFuture for Java clients
192
fun fetchUserDataAsync(userId: String): CompletableFuture<String> {
193
return GlobalScope.async {
194
delay(300) // Simulate async operation
195
"User data for $userId"
196
}.asCompletableFuture()
197
}
198
199
fun processMultipleAsync(items: List<String>): CompletableFuture<List<String>> {
200
return GlobalScope.async {
201
items.map { item ->
202
async {
203
delay(100)
204
"Processed $item"
205
}
206
}.awaitAll()
207
}.asCompletableFuture()
208
}
209
}
210
```
211
212
### Thread-Local Context Elements
213
214
Integration with Java ThreadLocal variables in coroutine contexts.
215
216
```kotlin { .api }
217
/** Converts ThreadLocal to CoroutineContext.Element */
218
fun <T> ThreadLocal<T>.asContextElement(value: T? = null): ThreadContextElement<T>
219
220
/** ThreadLocal context element interface */
221
interface ThreadContextElement<T> : CoroutineContext.Element {
222
val threadLocal: ThreadLocal<T>
223
val value: T
224
}
225
226
/** Copies current ThreadLocal values to context */
227
fun copyableThreadLocalContext(): CoroutineContext
228
```
229
230
**Usage Examples:**
231
232
```kotlin
233
import kotlinx.coroutines.*
234
import java.util.concurrent.ThreadLocalRandom
235
236
// ThreadLocal variables
237
val userContext = ThreadLocal<String>()
238
val requestId = ThreadLocal<String>()
239
240
fun main() = runBlocking {
241
// Set ThreadLocal values
242
userContext.set("Alice")
243
requestId.set("REQ-123")
244
245
println("Main thread context: ${userContext.get()}, ${requestId.get()}")
246
247
// Without context element - ThreadLocal is lost
248
launch {
249
println("Child coroutine (no context): ${userContext.get()}, ${requestId.get()}")
250
}.join()
251
252
// With context element - ThreadLocal is preserved
253
launch(userContext.asContextElement() + requestId.asContextElement()) {
254
println("Child coroutine (with context): ${userContext.get()}, ${requestId.get()}")
255
256
// Modify in child
257
userContext.set("Bob")
258
println("Modified in child: ${userContext.get()}")
259
260
launch {
261
println("Grandchild: ${userContext.get()}, ${requestId.get()}")
262
}.join()
263
}.join()
264
265
// Original thread still has original values
266
println("Back to main: ${userContext.get()}, ${requestId.get()}")
267
}
268
269
// Web request context example
270
class RequestContext {
271
companion object {
272
private val userId = ThreadLocal<String>()
273
private val sessionId = ThreadLocal<String>()
274
275
fun setUser(id: String) = userId.set(id)
276
fun getUser(): String? = userId.get()
277
278
fun setSession(id: String) = sessionId.set(id)
279
fun getSession(): String? = sessionId.get()
280
281
fun asCoroutineContext(): CoroutineContext {
282
return userId.asContextElement() + sessionId.asContextElement()
283
}
284
}
285
}
286
287
suspend fun handleRequest(userId: String, sessionId: String) {
288
// Set request context
289
RequestContext.setUser(userId)
290
RequestContext.setSession(sessionId)
291
292
// Process with context preservation
293
withContext(RequestContext.asCoroutineContext()) {
294
processUserData()
295
auditUserAction()
296
}
297
}
298
299
suspend fun processUserData() {
300
println("Processing data for user: ${RequestContext.getUser()}")
301
delay(100)
302
303
// Context is preserved across suspend points
304
println("Session: ${RequestContext.getSession()}")
305
}
306
307
suspend fun auditUserAction() {
308
println("Auditing action for user: ${RequestContext.getUser()}, session: ${RequestContext.getSession()}")
309
}
310
```
311
312
### Java Interoperability
313
314
Features for seamless Java-Kotlin coroutine interoperability.
315
316
```kotlin { .api }
317
/** Runs blocking coroutine for Java interop */
318
@JvmName("runBlocking")
319
fun <T> runBlocking(block: suspend CoroutineScope.() -> T): T
320
321
/** Global scope for fire-and-forget coroutines */
322
@DelicateCoroutinesApi
323
object GlobalScope : CoroutineScope
324
325
/** Annotation for JVM static members */
326
@JvmStatic
327
328
/** Annotation for JVM method name */
329
@JvmName("methodName")
330
331
/** Annotation for JVM overloads */
332
@JvmOverloads
333
```
334
335
**Usage Examples:**
336
337
```kotlin
338
import kotlinx.coroutines.*
339
import kotlinx.coroutines.future.*
340
import java.util.concurrent.CompletableFuture
341
342
// Java-friendly coroutine wrapper
343
class CoroutineService {
344
345
// Expose as CompletableFuture for Java clients
346
@JvmName("fetchDataAsync")
347
fun fetchDataForJava(id: String): CompletableFuture<String> {
348
return GlobalScope.async {
349
delay(500)
350
"Data for $id"
351
}.asCompletableFuture()
352
}
353
354
// Blocking wrapper for Java clients that prefer blocking APIs
355
@JvmName("fetchDataBlocking")
356
@JvmOverloads
357
fun fetchDataBlocking(id: String, timeoutMs: Long = 5000): String = runBlocking {
358
withTimeout(timeoutMs) {
359
delay(500)
360
"Blocking data for $id"
361
}
362
}
363
364
// Static methods for utility functions
365
companion object {
366
@JvmStatic
367
fun createService(): CoroutineService = CoroutineService()
368
369
@JvmStatic
370
@JvmName("delay")
371
fun delayBlocking(ms: Long) = runBlocking {
372
delay(ms)
373
}
374
}
375
}
376
377
// Bridge between Java callbacks and coroutines
378
suspend fun <T> CompletableFuture<T>.awaitWithTimeout(timeoutMs: Long): T {
379
return withTimeout(timeoutMs) {
380
this@awaitWithTimeout.await()
381
}
382
}
383
384
fun <T> suspendFunctionAsCompletableFuture(
385
block: suspend () -> T
386
): CompletableFuture<T> {
387
return GlobalScope.async { block() }.asCompletableFuture()
388
}
389
390
// Example Java integration patterns
391
fun main() = runBlocking {
392
val service = CoroutineService.createService()
393
394
// Use from Kotlin
395
val kotlinResult = service.fetchDataForJava("kotlin-client").await()
396
println("Kotlin result: $kotlinResult")
397
398
val blockingResult = service.fetchDataBlocking("blocking-client")
399
println("Blocking result: $blockingResult")
400
401
// Timeout handling
402
try {
403
val future = CompletableFuture.supplyAsync {
404
Thread.sleep(2000)
405
"Slow result"
406
}
407
408
val result = future.awaitWithTimeout(1000)
409
println("Fast result: $result")
410
} catch (e: TimeoutCancellationException) {
411
println("Operation timed out")
412
}
413
}
414
```
415
416
### JVM-Specific System Properties
417
418
Configuration properties for tuning JVM-specific behavior.
419
420
```kotlin { .api }
421
/** IO dispatcher parallelism property */
422
const val IO_PARALLELISM_PROPERTY_NAME = "kotlinx.coroutines.io.parallelism"
423
424
/** Debug mode property */
425
const val DEBUG_PROPERTY_NAME = "kotlinx.coroutines.debug"
426
427
/** Stacktrace recovery property */
428
const val STACKTRACE_RECOVERY_PROPERTY_NAME = "kotlinx.coroutines.stacktrace.recovery"
429
```
430
431
**Configuration Examples:**
432
433
```kotlin
434
// JVM startup arguments
435
// -Dkotlinx.coroutines.io.parallelism=128
436
// -Dkotlinx.coroutines.debug=on
437
// -Dkotlinx.coroutines.stacktrace.recovery=on
438
439
// Programmatic configuration
440
fun configureCoroutines() {
441
// Set IO parallelism
442
System.setProperty("kotlinx.coroutines.io.parallelism", "64")
443
444
// Enable debug mode
445
System.setProperty("kotlinx.coroutines.debug", "on")
446
447
// Enable stacktrace recovery
448
System.setProperty("kotlinx.coroutines.stacktrace.recovery", "on")
449
}
450
451
// Runtime configuration check
452
fun checkConfiguration() {
453
val ioParallelism = System.getProperty("kotlinx.coroutines.io.parallelism")
454
val debugMode = System.getProperty("kotlinx.coroutines.debug")
455
456
println("IO Parallelism: ${ioParallelism ?: "default"}")
457
println("Debug Mode: ${debugMode ?: "off"}")
458
}
459
```
460
461
## Types
462
463
### JVM-Specific Interfaces
464
465
Interfaces specific to JVM platform integration.
466
467
```kotlin { .api }
468
/** Closeable coroutine dispatcher */
469
interface Closeable {
470
fun close()
471
}
472
473
/** Executor-based coroutine dispatcher */
474
abstract class ExecutorCoroutineDispatcher : CoroutineDispatcher(), Closeable {
475
abstract val executor: Executor
476
}
477
478
/** Thread context element for ThreadLocal integration */
479
interface ThreadContextElement<T> : CoroutineContext.Element {
480
val threadLocal: ThreadLocal<T>
481
val value: T
482
483
fun updateThreadContext(context: CoroutineContext): T
484
fun restoreThreadContext(context: CoroutineContext, oldState: T)
485
}
486
```
487
488
### Java Integration Types
489
490
Types for seamless Java interoperability.
491
492
```kotlin { .api }
493
/** Java-compatible future conversion */
494
typealias JavaCompletableFuture<T> = java.util.concurrent.CompletableFuture<T>
495
496
/** Java executor types */
497
typealias JavaExecutor = java.util.concurrent.Executor
498
typealias JavaExecutorService = java.util.concurrent.ExecutorService
499
```