Plugin dependency/class loading problem
Hi,
I'm trying to develop a small plugin that depends on the Scala plugin. The basics seem to be fine, I can call Scala plugin code, I can run the plugin etc. But there seems to be some classloading issues that I can't figure out. The problem occurs when calling following code:
val sc: ScObject...
sc.functions // throws!
The Error is: java.lang.LinkageError: loader constraint violation: when resolving interface method "org.jetbrains.plugins.scala.lang.psi.api.toplevel.typedef.ScTypeDefinition.functions()Lscala/Seq;" the class loader (instance of com/intellij/ide/plugins/cl/PluginClassLoader) of the current class, com/saynomoo/runner/ScalaRunnerProducer$$anonfun$locateRunnable$1, and the class loader (instance of com/intellij/ide/plugins/cl/PluginClassLoader) for resolved class, org/jetbrains/plugins/scala/lang/psi/api/toplevel/typedef/ScTypeDefinition, have different Class objects for the type scala/Seq used in the signature
The problem sounds like I have two different versions of scala library classes in the classpath. I have tried using 2.7.1.final and 2.7.2.RC3. I'm not 100% sure how to set up the project dependencies in the first place, I have added the scala plugin dependencies (Scala.jar) in the SDK part, since there were some classloading issues if i defined the dependency as a normal (deployable) module dependency.
Any suggestions are welcome,
Tuomas
Please sign in to leave a comment.
Hello, Tuomas.
The problem is that you use Scala.jar in your plugin to develop it and deploy it with your plugin. By the hierarchy of Idea classloaders there are tow different PluginClassLoaders and each of them loads it's own ScTypeDefinition interface. That's why we have a conflict on a level of their parent classloader.
To avoid this you have to use dependency in your plugin descriptor (plugin.xml) as below:
Where "org.intellij.scala" is our Scala plugin id. This will linearize class loader hierarchy. You can use jars of Scala plugin in your development project, but you should not deploy them with your plugin.
With best regards,
Ilya
Is there some way to define what dependencies are packaged/deployed and what are not? Only way I have managed the dependent jars not to deploy is to add them to the intellij idea sdk jars of my project. I did that for the Scala.jar, but the scala library jars still do deploy, since the scala facet of my plugin project adds them as dependency. And anyway it seems a little hacky to add the dependencies directly to the sdk lib.
Tuomas,
I'm afraid, that's the only way, because Scala plugin is not bundled and you have to point it as part of your project SDK.
Do you have some suggested workaround to get scala library classes as a dependency but not deployed? If I select scala facet for the plugin, the libraries appear as plugin dependencies and the get deployed. If I remove the scala library jars from plugin dependencies, the scala facet itself gets removed/invalid. Can I create some dummy scala sdk that does not contain the actual jars and put the lib jars to the sdk path?
I tried the dummy scala lib, but it did not work out. My current workaround is to run simple ant task to delete the scala lib jars from the plugin sandbox.