загрузка файла jar во время выполнения java.lang.NoClassDefFoundError: kotlin/jvm/internal/markers/KMappedMarker

#kotlin #plugins #jar #runtime #classloader

#котлин #Плагины #jar #время выполнения #загрузчик классов

Вопрос:

У меня есть 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 
 

Во-первых, меня смущает, что я получаю «ClassNotFoundException», хотя bar.jar он находится в пути к классу.
Я решаю эту проблему, загружая динамически ./bar.jar , ./foo.jar как в приведенном выше коде.

Тогда теперь я получаю NoClassDefFoundError: kotlin/jvm/internal/markers/KMappedMarker

Среда выполнения kotlin уже упакована в foo.jar .

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

Я также создал fat-jar для bar.jar so, чтобы он содержал kotlin-stdlib и kotlin-reflect , но я все еще получаю ту же ошибку.

Кто-нибудь может объяснить мне, что происходит?

Ответ №1:

Для всех, кому интересно, я, наконец, заставляю его работать, изменив:

 val cl = URLClassLoader.newInstance(urls)
 

для этого:

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

Нет необходимости в fat-jar или дополнительных -cp опциях.