gammanik
04/24/2020, 2:36 PMClassLoaders
and scriptEngine
.
Im creating a scriptEngine and adding my dsl rules in there from the outer scope
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:
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:
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?ilya.chernikov
04/27/2020, 9:42 AMjarNames
, 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.gammanik
04/29/2020, 9:52 PMthread.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:
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
)