I have foo.jar
that contains Foo
:
class Foo: Bar { ... }
bar.jar
that contains Bar:
abstract class Bar { ... }
Then I have baz.jar
that loads Foo
dynamically:
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)
And run it as follow:
java -cp ./bar.jar -jar ./baz.jar
First, I'm confused that I get a "ClassNotFoundException" even though bar.jar
is in the classpath.
I get around this problem by loading dynamically ./bar.jar
before ./foo.jar
as in the code above.
Then now I get NoClassDefFoundError: kotlin/jvm/internal/markers/KMappedMarker
The kotlin runtime is already packed in the foo.jar
.
jar -xvf foo/build/libs/foo-1.0.jar | grep std
extracted: BOOT-INF/lib/kotlin-stdlib-1.4.10.jar
I've also created a fat-jar for bar.jar
so it contains kotlin-stdlib
and kotlin-reflect
but I'm still getting the same error.
Can anyone explain me what's going on?
For anyone interested I finally make it working by changing:
val cl = URLClassLoader.newInstance(urls)
to this:
val cl = URLClassLoader.newInstance(urls, this::class.java.classLoader)
No need for fat-jar nor additional -cp
options.