Kotlin Classpath and Java ClassLoaders with REPL


#1

I am trying to use Kotlin with Processsing and it works fine in IntelliJ; however, I am having some classloader trouble with the REPL.  I think the Kotlin classpath is not being passed along to the Java classloader properly.

./kotlinc -cp /Applications/Processing2.app/Contents/Java/core.jar:p5.jar
Welcome to Kotlin version 1.0.0-beta-1038 (JRE 1.7.0_67-b01)
Type :help for help, :quit for quit
>>> System.setProperty(“java.awt.headless”, “false”)
true
>>> import kp5.*
>>> val sketch = createSketch(500, 500)
java.lang.ExceptionInInitializerError
Caused by: java.lang.RuntimeException: You need to use “Import Library” to add processing.core.PGraphicsJava2D to your sketch.
at processing.core.PApplet.makeGraphics(PApplet.java:1952)
at processing.core.PApplet.init(PApplet.java:972)
at kp5.Kp5.startSketch(p5.kt:33)
at kp5.P5Kt.createSketch(p5.kt:85)
at kp5.P5Kt.createSketch$default(p5.kt:83)
at kp5.P5Kt.<clinit>(p5.kt:77)
at Line3.<init>(Unknown Source)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)

I modified some of the code in ReplFromTerminal and ReplInterpreter as a workaround to make Java use the Kotlin classloader but I am not sure if that is necessary.


#2

Is p5.jar located in the current directory or in /Applications/Processing2.app/Contents/Java/ ?

Can you show us what changes have you made to the Kotlin REPL? Thanks!


#3

Yes, p5.jar is in the current directory and it finds those classes just fine.

Here is my work around (which I’m not sure is completely correct):

ReplFromTerminal:

  •  &nbsp;&nbsp;List&lt;URL&gt; classpath = Lists.newArrayList();
    
  •  &nbsp;&nbsp;for (File file : JvmContentRootsKt.getJvmClasspathRoots(compilerConfiguration)) {
    

+           try {
+           classpath.add(file.toURI().toURL());
+           }
+           catch (MalformedURLException e) {
+           throw ExceptionUtilsKt.rethrow(e);
+           }

  •  &nbsp;&nbsp;}
    
  •  &nbsp;&nbsp;ClassLoader cl = Thread.currentThread().getContextClassLoader();
    
  •  &nbsp;&nbsp;ClassLoader c = new URLClassLoader(classpath.toArray(new URL[classpath.size()]), cl);
    
  •  &nbsp;&nbsp;Thread.currentThread().setContextClassLoader(c);
    

ReplInterpreter:

  •  &nbsp;&nbsp;this.classLoader = new ReplClassLoader(new URLClassLoader(classpath.toArray(new URL[classpath.size()]), null));
    
  •  &nbsp;&nbsp;ClassLoader cl = Thread.currentThread().getContextClassLoader();
    
  •  &nbsp;&nbsp;ClassLoader c = new URLClassLoader(classpath.toArray(new URL[classpath.size()]), cl);
    
  •  &nbsp;&nbsp;this.classLoader = new ReplClassLoader(c);
    
  •  &nbsp;&nbsp;Thread.currentThread().setContextClassLoader(c); //kjo</p>

#4

Could you please create an issue at youtrack.jetbrains.com? Also would be nice if you could explain there why the workaround with the context class loader helps REPL with the library you're using. Thank you!