Hello. I have a problem with `ClassLoaders` and `s...
# scripting
g
Hello. I have a problem with
ClassLoaders
and
scriptEngine
. Im creating a scriptEngine and adding my dsl rules in there from the outer scope
Copy code
File("/Users/Nikita/Documents/lib-support/dsl-lib-support/build/libs/dsl-lib-support.jar")
My script returns me Map<String, MethodToMark>. MethodToMark is a part of my dsl rules:
Copy code
val res: Map<String, MethodToMark>? = engine.eval(script) as Map<String, MethodToMark>?
println(res!!["lib.LibClassOne.method1"] as MethodToMark)
But this code doesn’t work. When I’m calling
res!!["lib.LibClassOne.method1"] as MethodToMark
it gives me an error:
Copy code
java.lang.ClassCastException: class MethodToMark cannot be cast to class MethodToMark (MethodToMark is in unnamed module of loader <http://java.net|java.net>.URLClassLoader @79609006; MethodToMark is in unnamed module of loader <http://com.intellij.ide.plugins.cl|com.intellij.ide.plugins.cl>.PluginClassLoader @67f6ebd8)
So the problem is that I cannot cast cast the same class to itself because of the fifferent class loaders I guess. Here is a come Image where I’m creating my scriptEngine and adding my dsl rules: How do I solve it?
i
Most likely that means that MethodToMark is accessible by the two paths. E.g. it is part of the context classloader which is used for the plugin loading, and separately by the classloader created from your
jarNames
, wich has context one as a parent. If your
dsl-lib-support.jar
is loaded with the plugin, I'd try to remove it from
jarNames
first. Or at least move it after the classpath extracted from context. The engine uses the classloader with parent taken from
Thread.contextClassLoader
to load classes, so another thing to try is to set it to the CL you need before creating the engine. And if nothing helps, you probably need to debug it to understand where these incompatible classes are loaded from. Please note, that this is the kotlin plugin internals , it is not meant to be a public API. The public API for scripting and REPL is in the development, but unfortunately there is no variant yet that will work in the IntelliJ plugin, so you don't have much choice at the moment.
g
My dsl-jar have beel loading with
thread.contextClassLoader
which is
UrlClassLoader
at runtime. But all of plugin’s classes are loaded with
PluginClassLoader
(which is a inherited from
UrlClassLoader
) So I manually set:
Copy code
Thread.currentThread().contextClassLoader = this.javaClass.classLoader
And it accidentally solved the problem. Not sure if it’s a right thing to do but at least I made it finally work (without
ClassCastException
)