0
# Compiled Scripts and Modules
1
2
JVM implementations of compiled scripts with serialization support, module management, and ClassLoader creation capabilities. The compiled script system provides efficient script storage, caching, and execution with proper metadata handling.
3
4
## Capabilities
5
6
### JVM Compiled Script
7
8
Core JVM implementation of compiled scripts with serialization support and metadata management.
9
10
```kotlin { .api }
11
/**
12
* JVM implementation of compiled script with serialization support
13
* Provides metadata about compiled script and manages execution context
14
*/
15
open class KJvmCompiledScript : CompiledScript, Serializable {
16
17
/** Source location identifier for debugging and error reporting */
18
override val sourceLocationId: String?
19
20
/** Configuration used during compilation */
21
override val compilationConfiguration: ScriptCompilationConfiguration
22
23
/** List of other scripts this script depends on */
24
override val otherScripts: List<CompiledScript>
25
26
/** Fully qualified name of the compiled script class */
27
val scriptClassFQName: String
28
29
/** Result field information if script produces a result */
30
override val resultField: Pair<String, KotlinType>?
31
32
/**
33
* Get the compiled script class for execution
34
* @param scriptEvaluationConfiguration Configuration for class loading
35
* @return Result containing the script class or diagnostics
36
*/
37
override suspend fun getClass(
38
scriptEvaluationConfiguration: ScriptEvaluationConfiguration?
39
): ResultWithDiagnostics<KClass<*>>
40
41
/**
42
* Get the compiled module containing this script
43
* @return KJvmCompiledModule or null if not available
44
*/
45
fun getCompiledModule(): KJvmCompiledModule?
46
}
47
```
48
49
**Usage Examples:**
50
51
```kotlin
52
import kotlin.script.experimental.jvm.impl.KJvmCompiledScript
53
import kotlin.script.experimental.api.*
54
55
// Access compiled script properties
56
val compiledScript: KJvmCompiledScript = // ... obtained from compilation
57
58
println("Script class: ${compiledScript.scriptClassFQName}")
59
println("Source location: ${compiledScript.sourceLocationId}")
60
println("Dependencies: ${compiledScript.otherScripts.size}")
61
62
// Get script class for execution
63
val evaluationConfig = ScriptEvaluationConfiguration {
64
// ... configuration
65
}
66
67
val classResult = compiledScript.getClass(evaluationConfig)
68
when (classResult) {
69
is ResultWithDiagnostics.Success -> {
70
val scriptClass = classResult.value
71
println("Successfully loaded class: ${scriptClass.qualifiedName}")
72
}
73
is ResultWithDiagnostics.Failure -> {
74
println("Failed to load class:")
75
classResult.reports.forEach { println(" ${it.message}") }
76
}
77
}
78
```
79
80
### Compiled Module Interface
81
82
Base interface for compiled JVM modules with ClassLoader management capabilities.
83
84
```kotlin { .api }
85
/**
86
* Represents a compiled JVM module
87
* Provides ClassLoader creation for script execution
88
*/
89
interface KJvmCompiledModule {
90
/**
91
* Create ClassLoader for this module
92
* @param baseClassLoader Parent ClassLoader (null for system ClassLoader)
93
* @return ClassLoader containing module classes and resources
94
*/
95
fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader
96
}
97
```
98
99
### In-Memory Compiled Module
100
101
Compiled module stored entirely in memory with bytecode management.
102
103
```kotlin { .api }
104
/**
105
* In-memory compiled module with bytecode storage
106
* Suitable for dynamic compilation and caching scenarios
107
*/
108
interface KJvmCompiledModuleInMemory : KJvmCompiledModule {
109
/** Map of class names to their compiled bytecode */
110
val compilerOutputFiles: Map<String, ByteArray>
111
}
112
```
113
114
**Usage Example:**
115
116
```kotlin
117
// Create in-memory module
118
val inMemoryModule = object : KJvmCompiledModuleInMemory {
119
override val compilerOutputFiles = mapOf(
120
"MyScript.class" to compiledBytecode,
121
"MyScript\$Helper.class" to helperClassBytecode
122
)
123
124
override fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader {
125
return InMemoryClassLoader(compilerOutputFiles, baseClassLoader)
126
}
127
}
128
129
// Use module ClassLoader
130
val moduleClassLoader = inMemoryModule.createClassLoader(
131
Thread.currentThread().contextClassLoader
132
)
133
```
134
135
### ClassPath-Based Compiled Module
136
137
Compiled module loaded from filesystem classpath entries.
138
139
```kotlin { .api }
140
/**
141
* Module loaded from classpath files
142
* @param classpath Collection of JAR files and directories containing compiled classes
143
*/
144
class KJvmCompiledModuleFromClassPath(
145
val classpath: Collection<File>
146
) : KJvmCompiledModule {
147
148
/**
149
* Create ClassLoader from classpath files
150
* @param baseClassLoader Parent ClassLoader
151
* @return URLClassLoader containing classpath entries
152
*/
153
override fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader
154
}
155
```
156
157
**Usage Examples:**
158
159
```kotlin
160
import java.io.File
161
162
// Create module from JAR files
163
val jarFiles = listOf(
164
File("/path/to/compiled-script.jar"),
165
File("/path/to/dependencies.jar")
166
)
167
168
val classpathModule = KJvmCompiledModuleFromClassPath(jarFiles)
169
170
// Create ClassLoader for execution
171
val classLoader = classpathModule.createClassLoader(
172
ClassLoader.getSystemClassLoader()
173
)
174
175
// Load and execute script class
176
val scriptClass = classLoader.loadClass("com.example.MyCompiledScript")
177
val scriptInstance = scriptClass.getDeclaredConstructor().newInstance()
178
```
179
180
### ClassLoader-Based Compiled Module
181
182
Compiled module that wraps an existing ClassLoader.
183
184
```kotlin { .api }
185
/**
186
* Module from existing ClassLoader
187
* @param moduleClassLoader Existing ClassLoader containing module classes
188
*/
189
class KJvmCompiledModuleFromClassLoader(
190
val moduleClassLoader: ClassLoader
191
) : KJvmCompiledModule {
192
193
/**
194
* Create ClassLoader using existing module ClassLoader as parent
195
* @param baseClassLoader Additional parent ClassLoader (optional)
196
* @return ClassLoader chain with proper delegation
197
*/
198
override fun createClassLoader(baseClassLoader: ClassLoader?): ClassLoader
199
}
200
```
201
202
**Usage Example:**
203
204
```kotlin
205
// Use existing plugin ClassLoader as module
206
val pluginClassLoader = MyPlugin::class.java.classLoader
207
val module = KJvmCompiledModuleFromClassLoader(pluginClassLoader)
208
209
// Create execution ClassLoader
210
val executionClassLoader = module.createClassLoader(
211
Thread.currentThread().contextClassLoader
212
)
213
```
214
215
### Dual ClassLoader Utility
216
217
Advanced ClassLoader implementation that combines multiple ClassLoader sources.
218
219
```kotlin { .api }
220
/**
221
* ClassLoader that combines fallback and parent loaders
222
* Provides sophisticated class loading delegation
223
* @param fallbackLoader Primary ClassLoader for class resolution
224
* @param parentLoader Secondary ClassLoader for delegation
225
*/
226
class DualClassLoader(
227
fallbackLoader: ClassLoader,
228
parentLoader: ClassLoader?
229
) : ClassLoader {
230
231
/** Find class in fallback loader */
232
override fun findClass(name: String): Class<*>
233
234
/** Get resource stream with fallback logic */
235
override fun getResourceAsStream(name: String): InputStream?
236
237
/** Find resources across both loaders */
238
override fun findResources(name: String): Enumeration<URL>
239
240
/** Find single resource with fallback */
241
override fun findResource(name: String): URL?
242
243
/**
244
* Wrapper ClassLoader for delegation
245
*/
246
class Wrapper(parent: ClassLoader) : ClassLoader(parent)
247
}
248
```
249
250
**Usage Example:**
251
252
```kotlin
253
// Create dual ClassLoader for complex scenarios
254
val applicationClassLoader = MyApp::class.java.classLoader
255
val pluginClassLoader = loadPluginClassLoader()
256
257
val dualClassLoader = DualClassLoader(
258
fallbackLoader = pluginClassLoader,
259
parentLoader = applicationClassLoader
260
)
261
262
// Use for script execution with access to both contexts
263
val module = KJvmCompiledModuleFromClassLoader(dualClassLoader)
264
```
265
266
### Script Management Extensions
267
268
Extension functions for compiled script management and serialization.
269
270
```kotlin { .api }
271
/**
272
* Get or create actual ClassLoader for script evaluation
273
* @param evaluationConfiguration Configuration for ClassLoader creation
274
* @return ClassLoader suitable for script execution
275
*/
276
fun KJvmCompiledScript.getOrCreateActualClassloader(
277
evaluationConfiguration: ScriptEvaluationConfiguration
278
): ClassLoader
279
280
/**
281
* Create copy of script without module information
282
* @return New KJvmCompiledScript instance without module reference
283
*/
284
fun KJvmCompiledScript.copyWithoutModule(): KJvmCompiledScript
285
286
/**
287
* Serialize compiled script to byte array
288
* @return Serialized script data
289
*/
290
fun KJvmCompiledScript.toBytes(): ByteArray
291
292
/**
293
* Create script from ClassLoader and class name
294
* @param scriptClassFQName Fully qualified script class name
295
* @param classLoader ClassLoader containing the script class
296
* @return KJvmCompiledScript instance
297
*/
298
fun createScriptFromClassLoader(
299
scriptClassFQName: String,
300
classLoader: ClassLoader
301
): KJvmCompiledScript
302
```
303
304
**Usage Examples:**
305
306
```kotlin
307
// Get execution ClassLoader
308
val executionClassLoader = compiledScript.getOrCreateActualClassloader(evaluationConfig)
309
310
// Create lightweight copy for caching
311
val cacheableScript = compiledScript.copyWithoutModule()
312
313
// Serialize for persistent storage
314
val serializedData = compiledScript.toBytes()
315
val restoredScript = deserializeScript(serializedData)
316
317
// Create script from existing compiled class
318
val scriptFromClassLoader = createScriptFromClassLoader(
319
"com.example.MyScript",
320
MyApp::class.java.classLoader
321
)
322
```
323
324
### Script Metadata Management
325
326
Constants and utilities for script metadata handling.
327
328
```kotlin { .api }
329
/** Path for script metadata in JAR files */
330
const val KOTLIN_SCRIPT_METADATA_PATH = "META-INF/kotlin/script"
331
332
/** File extension for Kotlin script metadata files */
333
const val KOTLIN_SCRIPT_METADATA_EXTENSION_WITH_DOT = ".kotlin_script"
334
335
/**
336
* Generate metadata path for script class
337
* @param scriptClassFQName Fully qualified script class name
338
* @return Metadata file path within JAR/directory structure
339
*/
340
fun scriptMetadataPath(scriptClassFQName: String): String
341
```
342
343
**Usage Example:**
344
345
```kotlin
346
// Generate metadata path for script
347
val scriptClassName = "com.example.MyScript"
348
val metadataPath = scriptMetadataPath(scriptClassName)
349
// Returns: "META-INF/kotlin/script/com/example/MyScript.kotlin_script"
350
351
// Use in JAR file creation
352
val jarEntry = JarEntry(metadataPath)
353
jarOutputStream.putNextEntry(jarEntry)
354
jarOutputStream.write(scriptMetadata)
355
```
356
357
## Integration Patterns
358
359
### Script Caching with Modules
360
361
```kotlin
362
class ScriptCacheManager {
363
private val compiledScripts = mutableMapOf<String, KJvmCompiledScript>()
364
365
fun cacheScript(sourceId: String, script: KJvmCompiledScript) {
366
// Cache lightweight version without module
367
compiledScripts[sourceId] = script.copyWithoutModule()
368
}
369
370
fun getScript(sourceId: String, evaluationConfig: ScriptEvaluationConfiguration): KJvmCompiledScript? {
371
return compiledScripts[sourceId]?.let { cached ->
372
// Recreate with proper ClassLoader
373
val classLoader = cached.getOrCreateActualClassloader(evaluationConfig)
374
createScriptFromClassLoader(cached.scriptClassFQName, classLoader)
375
}
376
}
377
}
378
```
379
380
### Hot Deployment Support
381
382
```kotlin
383
class HotDeploymentManager {
384
private var currentModule: KJvmCompiledModule? = null
385
386
fun deployNewVersion(compiledClassPath: Collection<File>) {
387
currentModule = KJvmCompiledModuleFromClassPath(compiledClassPath)
388
}
389
390
fun createExecutionClassLoader(): ClassLoader? {
391
return currentModule?.createClassLoader(
392
Thread.currentThread().contextClassLoader
393
)
394
}
395
}
396
```