spierce7
08/05/2021, 10:35 PMval jarFile = File("<Path to downloaded jar>")
val classLoader = URLClassLoader(
arrayOf(jarFile.toURI().toURL()),
Thread.currentThread().contextClassLoader
)
val myMainClass = Class.forName("MyClass", true, classLoader)
val mainMethod = myMainClass.getDeclaredMethod("main")
mainMethod.invoke(null)
This works until the AWT loop starts and my class loader hasn’t been set on that thread so it can’t find the right class.
I’m sure there is a better way to do this. Can anyone point me in the right direction?spierce7
08/05/2021, 10:36 PMThread.currentThread().contextClassLoader = classLoader
Thread.getAllStackTraces().forEach { (t, _) ->
if (t.contextClassLoader != null) {
t.contextClassLoader = classLoader
}
}
Seems to work, but I imagine new threads that spawn won’t have the class loader. There has to be a better way to do this.jim
08/06/2021, 5:22 AMcontextClassLoader
feels very sketchy to me; you shouldn't need to set the contextClassLoader
.
I'm not sure I understood the issue with the AWT loop. AWT is always going to get loaded using the parent classloader because it is part of the java.
namespace which is special cased (for security reasons?). But this shouldn't matter, as long as all your classes are loaded using your custom ClassLoader. Any class referenced by MyClass
and which is only provided by jarFile
should be loaded by your classloader.
If you can elaborate on specifically what problem you were facing with your old approach, perhaps we can help. Although it is worth noting that we are venturing into purely java territory, and there is nothing compose-specific about these questions, so you might get more visibility in a place like StackOverflow.Casey Brooks
08/09/2021, 12:21 AMspierce7
08/09/2021, 3:21 AMSetting theThis all feels super sketchy to me lolfeels very sketchy to me; you shouldn’t need to set thecontextClassLoader
contextClassLoader
Any class referenced byI actually didn’t see that happening. Based on what I was seeing, I made the assumption that the classloader on the thread that’s running the code is what is used to load the new class.and which is only provided byMyClass
should be loaded by your classloader.jarFile
Thread.currentThread().contextClassLoader = classLoader
Thread.getAllStackTraces().forEach { (t, _) ->
if (t.contextClassLoader != null) {
t.contextClassLoader = classLoader
}
}
Actually did get my jar running.
I read a blog post about how resolving all memory leaks with an approach like this is almost completely impossible though. I think taking this approach for an auto-updating app seems bad.spierce7
08/09/2021, 3:35 AM