ClassCastException because of different classloaders



In some place of my plugin I try to get class declared in a file by this way:

class MyCustomTestContributor: CompletionContributor() {
override fun fillCompletionVariants(parameters: CompletionParameters, result: CompletionResultSet) {
val aClass = parameters.originalFile.children[4] as KtClass //fails here

This code fails with

java.lang.ClassCastException: org.jetbrains.kotlin.psi.KtClass cannot be cast to org.jetbrains.kotlin.psi.KtClass

because of KtClass was loaded by different classloaders:
1. PluginClassLoader[org.jetbrains.kotlin, 1.3.30-release-IJ2018.3-1]
2. PluginClassLoader[, 1.0-SNAPSHOT]

I have <depends>org.jetbrains.kotlin</depends> in my plugin.xml.
I have com.github.cretz.kastree:kastree-ast-psi:0.4.0 in my gradle dependencies. Build script attached bellow.
Kastree uses kotlin-compiler-embedabble.jar, I thought it can clash with Kotlin plugin libraries, so I tried to exclude kotlin-compiler-embedabble from my classpath (as transitive depencency) and include it as compileOnly depenency, but in this case IDEA throws the exception on startup: 

java.lang.NoClassDefFoundError: org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment

I also tried to add kotlin-compiler-embedabble.jar into Intellij Platform SDK classpath but it doesn't work.

My gradle build script looks like: 

plugins {
id 'org.jetbrains.intellij' version '0.4.7'
id 'org.jetbrains.kotlin.jvm' version '1.3.30'

group ''
version '1.0-SNAPSHOT'

repositories {
flatDir {
dirs 'libs'

dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
compile 'com.fasterxml.jackson.core:jackson-core:2.9.8'
compile "org.jetbrains.kotlinx:kotlinx-html-jvm:0.6.12"
compile (name:'jfxrt', ext:'jar')

intellij {
version '2018.3.4'
plugins 'org.jetbrains.kotlin:1.3.30-release-IJ2018.3-1'
intellij.updateSinceUntilBuild false

patchPluginXml {
changeNotes """
Add change notes here.<br>
<em>most HTML tags may be used</em>"""

What would you suggest to resolve this issue? Thank you!

Comment actions Permalink

Can you shade your Kastree dependency in your plugin to avoid this classloading problem?

Comment actions Permalink

I tried to shade kotlin-compiler-embeddable, but it rise new problems.

If there is no other solutions than shading or moving packages from dependencies, then ok. I can continue without casting psi elements and do parse syntax tree only by kastree.

Thank you for your answer!

Comment actions Permalink

In general, it is a bad idea to use kotlin compiler jar in an idea plugin - it will be very difficult to avoid conflicts with kotlin plugin code. So, I would try to go compileOnly route instead.
But the exception "java.lang.NoClassDefFoundError: org/jetbrains/kotlin/cli/jvm/compiler/KotlinCoreEnvironment" puzzles me in that context. Could you, please, post the complete stacktrace.


Please sign in to leave a comment.