We're updating the issue view to help you get more done. 

Do not assume that all classloaders in hierarchy implement URLClasspath

Description

Currently, java.classpath assumes that all classloaders in the hierarchy implement URLClasspath. This is not always true, nor is it always possible to achieve this.

Cursive recently switched to running Leiningen inside an isolated classloader tree using ShimDandy. When someone tries to work with a project with cider-nrepl in their profiles, they receive the following error:

1 2 3 4 5 6 7 java.lang.IllegalArgumentException: No implementation of method: :urls of protocol: #'mranderson045.javaclasspath.v0v2v2.clojure.java.classpath/URLClasspath found for class: com.intellij.util.lang.UrlClassLoader, compiling:(track_state.clj:57:8) No implementation of method: :urls of protocol: #'mranderson045.javaclasspath.v0v2v2.clojure.java.classpath/URLClasspath found for class: com.intellij.util.lang.UrlClassLoader

cider-nrepl uses java.classpath to introspect the classpath, and java.classpath walks the classloader hierarchy until it reaches the root classloader which is a com.intellij.util.lang.UrlClassLoader, which does not extend java.net.URLClassLoader. It is essential that this classloader not extend URLClassLoader because lein uses pomegranate to add jars to the classpath, and pomegranate will add those jars to the classpath using dynapath in the highest modifiable classloader it can find. It's important that that not be the root classloader since that would mean that lein plugins would be incorrectly loaded onto the classpath for different projects. Additionally, I cannot extend the URLClasspath protocol to the IntelliJ classloader because it's not available inside the shim.

I believe the solution is that java.classpath should check that the classloaders satisfy URLClasspath before calling urls on them.

Environment

None

Status

Assignee

Stuart Sierra

Reporter

Colin Fleming

Labels

None

Approval

None

Patch

None

Priority

Major