or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

channels.mdcoroutine-builders.mddispatchers.mdexception-handling.mdflow-api.mdindex.mdjob-management.mdjvm-integration.mdsynchronization.md

jvm-integration.mddocs/

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

```