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"

Answered

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

 

1 comment
Comment actions Permalink

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

0

Please sign in to leave a comment.