LinkageError: loader constraint violation: loader (instance of com/intellij/ide/plugins/cl/PluginClassLoader) previously initiated loading for a different type with name "scala/concurrent/Future"
Good afternoon! I have the following problem.
The configuration of the plugin contains the following dependence
<depends optional="false">org.intellij.scala</depends>
and when I trying to execute the following code:
import scala.concurrent.Future
import org.jetbrains.sbt.shell.SbtShellCommunication
import scala.concurrent.ExecutionContext.Implicits.global
.....
val f = SbtShellCommunication.forProject(anActionEvent.getProject).command("clean", true)
// " returned type is Future[String]
f.map(println(_))
The next error appeared:
2019-09-25 23:37:25,803 [ 16538] ERROR - llij.ide.plugins.PluginManager - While loading class scala.concurrent.Future: loader constraint violation: loader (instance of com/intellij/ide/plugins/cl/PluginClassLoader) previously initiated loading for a different type with name "scala/concurrent/Future" [Plugin: com.your.company.unique.plugin.id]
com.intellij.diagnostic.PluginException: While loading class scala.concurrent.Future: loader constraint violation: loader (instance of com/intellij/ide/plugins/cl/PluginClassLoader) previously initiated loading for a different type with name "scala/concurrent/Future" [Plugin: com.your.company.unique.plugin.id]
I understand the reason for this error, first "org.intellij.scala" loads Future using ClassLoader, and then my plugin does it.
I understand that if I cut out the Future.class, the problem will disappear.
The question is, how is this the easiest way to do it? I don't really want to build my own jar for Scala-library. Maybe I can configure it through the plugin configuration?
Unfortunately, I have not been able to find any solutions on the Internet.
I hope for your help
P.S Additional Information:
idea-version - 192.0
Scala Version - 2.12.4
I can't cut out the whole library on my side because in this case the other part of the functionality will stop working
Please sign in to leave a comment.
That's a rather complicated situation you have and I'm afraid, there's no easy way to do this.
If the Scala plugin dependency wasn't optional, you could just have unbundled scala-librarary from your plugin distribution and delegate all scala-related classloading to the Scala plugin(just like all the other plugins that depend on Scala plugin do).
The following might do the trick:
- extract Scala plugin interop into a separate module with java surface api
- in runtime extract Scala plugin's classloader from `PluginManagerCore.getPlugin(...).getPluginClassLoader()`
- create a custom classloader that doesn't load your plugin's bundled scala-library, and set Scala plugin's classloader as a parent
- dynamically instantiate your extracted module within the newly created classloader
- from your main plugin use the java API of the extracted module
This way you'll basically create a dynamically loaded mini-plugin for IJ