loading a jar file at runtime java.lang.NoClassDefFoundError: kotlin/jvm/internal/markers/KMappedMarker

loading a jar file at runtime java.lang.NoClassDefFoundError: kotlin/jvm/internal/markers/KMappedMarker

我有 foo.jar 包含 Foo:

class Foo: Bar { ... }

bar.jar 包含小节:

abstract class Bar { ... }

然后我有 baz.jar 动态加载 Foo

val jarFile = JarFile("./foo.jar")
val e: Enumeration<JarEntry> = jarFile.entries()

val urls = arrayOf(URL("jar:file:foo.jar!/"))
val cl = URLClassLoader.newInstance(urls)

Thread.currentThread().contextClassLoader = cl // With or without same result.

val list = mutableListOf<Class<*>>()
while (e.hasMoreElements()) {
val je: JarEntry = e.nextElement()
...
cl.loadClass(className)

和运行如下:

java -cp ./bar.jar -jar ./baz.jar 

首先,我很困惑,即使 bar.jar 在类路径中,我也会收到“ClassNotFoundException”。 我通过在 ./foo.jar 之前动态加载 ./bar.jar 来解决这个问题,就像上面的代码一样。

然后现在我得到NoClassDefFoundError: kotlin/jvm/internal/markers/KMappedMarker

kotlin 运行time 已经打包在 foo.jar.

jar -xvf foo/build/libs/foo-1.0.jar | grep std
extracted: BOOT-INF/lib/kotlin-stdlib-1.4.10.jar

我还为 bar.jar 创建了一个 fat-jar,所以它包含 kotlin-stdlibkotlin-reflect 但我仍然遇到同样的错误。

谁能给我解释一下这是怎么回事?

对于任何感兴趣的人,我最终通过更改使其工作:

val cl = URLClassLoader.newInstance(urls)

对此:

val cl = URLClassLoader.newInstance(urls, this::class.java.classLoader)

不需要 fat-jar 也不需要额外的 -cp 选项。