Separation between gradle classpath and the compiled classpath

plugins

(Ned Twigg) #1

I’ve got a library called durian-swt. I’ve got a plugin called goomph, which uses durian-swt.

I’d like to use goomph to compile new versions of durian-swt, but I get NoClassDefFoundError when goomph tries to use a durian-swt class. Code which demonstrates problem here, and failed build output here.

It appears that there’s less separation between the gradle classpath and the compiled artifacts than I thought. Any tips?


(Stefan Oehme) #2

Gradle does not leak plugins into the compile classpath or vice-versa.

What is happening in the project you linked is that the project is trying to depend on itself. The reason is probably a dynamic version in the pom.xml of Goomph which matches the durian-swt version currently under development.


(Ned Twigg) #3

durian-swt 2.0.0 is published to maven central. I built goomph, which has this little snippet in its POM

<dependency>
    <groupId>com.diffplug.durian</groupId>
    <artifactId>durian-swt</artifactId>
    <version>2.0.0</version>
    <scope>runtime</scope>
</dependency>

For developing durian-swt 2.1.0-SNAPSHOT, I’m seeing the error. I also tried 3.0.0-SNAPSHOT, same error.

Is there something I can change to the POM snippet above?


(Stefan Oehme) #4

I just thought about my own projects that also have this situation and work. I thought it was just the version, but in fact we ignore versions for project dependencies. Just group and name are enough to make it match.

The reason it works for my projects is probably that I set the group in build.gradle, so it gets executed after the buildscript block. You set the group in gradle.properties where it gets executed before. Can you try changing that?


(Ned Twigg) #5

You’re a miracle worker! That fixed it, which exposed a next error:

java.lang.LinkageError: loader constraint violation in interface itable initialization

I was able to track it down to having two jars which each have an org/eclipse/core/runtime/IStatus.class. Luckily it’s possible to move that plugin to a separate project, so it’s a relatively easy fix.

It would be cool if Gradle plugins offered a higher level of classloader isolation. It’s hard to have plugins interoperate and be isolated without reinventing all the tangle of OSGi. But there are shortcuts you could take, maybe something like this:

plugins {
    id "myplugin" isolated
}

When supplying the “isolated” flag, that plugin gets its own classloader, with exactly the dependencies in its pom and no dependency mediation between it and the other plugins.

This would mean that no other plugins could cooperate with it. But for cases where plugins are “accidentally cooperating” by smashing each other’s classes when they’re supposed to be independent, it would be a quick and convenient fix.

Just a thought, thanks a ton for your help :slight_smile:


(Stefan Oehme) #6

Plugin isolation is definitely something we want to do. Our plan is to do it on the plugin side: Plugins would specify what other plugins they depend on and what API they expose. Not as complicated as OSGi, but still Jigsaw-level complexity.

Your suggestion could be a useful workaround until the above solution comes around. I’ll bring it up when we discuss the plugin system the next time. Thanks for that :slight_smile: