48869

Classpath issue when binding an instance in a Scala Interpreter

Question:

I already posted this question in scala lang forum but unfortunately I did not get any answer. Second chance ?

I try to embed an interpreter an evaluate a scala snippet into this interpreter. I would like to bind an instance of a custom class within the interpreter. To sum up that would look like:

import scala.tools.nsc._ import scala.tools.nsc.interpreter._ class C { def sayHello(s:String) = "hello "+s } object Main extends App { val c= new C val s = new Settings s.usejavacp.value=true val i = new IMain(s) i.bind("myC",c) i.bind("world","the world") val script = "println(myC.sayHello(world))" i.eval(script)

}

When I run this snippet inside Eclipse (Kepler) - OpenJDK6/7 works for both - BSD OS Scala-2.11.0-M4 - scala-compiler.jar in the path it works fine If I try to run the same code inside the repl or directly with a scalac file.scala then scala -cp . Main I get the following error

error: not found value myC javax.script.ScriptException: compile-time error at scala.tools.nsc.interpreter.IMain.compile(IMain.scala:575) at scala.tools.nsc.interpreter.IMain.eval(IMain.scala:997) at javax.script.AbstractScriptEngine.eval(AbstractScriptEngine.java:264)

I was able to make it work under another OS (Win7) but by adding s.bootclasspath="path/to/my/classes"

I suspect some classpath issue

Later I was able to make it run by replacing the scala command line call by a java call this way: java -cp $CLASSPATH Main with CLASSPATH containing scala libraries it works

I looked at scala command and it is like it appends scala libraries in the java path in a different way.

Does anyone has any advice ?

Thanks

Added based on following comments:

Scalac does not output any error In fact if I run:

java -cp .:$SCALA_PATH/lib/scala-library.jar:$SCALA_PATH/lib/scala-compiler.jar:$SCALA_PATH/lib/scala-reflect.jar Main

or as suggested scala -nobootcp it works (Thanks for the valuable advice) Otherwise if I let scala use the bootcp the started line is the following one and it fails

java -Xbootclasspath/a:/usr/home/pcohen/Dev/Scala/scala-2.11.0-M4/lib/akka-actors.jar[...] -classpath "" [...]

When the scala jars are appended to the bootclasspath, it is like my binding is failing. I am not able to clearly understand why this bootclasspath difference affects my classes.

Answer1:

I don't know if this qualifies as advice, but are you aware:

scala> class C { def sayHello(s: String) = s"hello, $s" } defined class C scala> $intp.bind("world","the world") world: String = the world res0: scala.tools.nsc.interpreter.IR.Result = Success scala> val c = new C c: C = C@19878659 scala> $intp interpret "c sayHello world" res2: String = hello, the world res1: scala.tools.nsc.interpreter.IR.Result = Success

With separate compilation, your example works with scala -nobootcp my.Main.

You can see more with -Dscala.repl.debug=true. You'll see the Error return from the bind (everyone checks result values, right? println(i.bind("myC",c))) caused by:

java.lang.ClassCastException: intpbind.C cannot be cast to intpbind.C

and the wrapper code that is attempting it.

More words:

You said, "it is like my binding is failing," but as I showed above, it's exactly that the binding fails.

The reason is that when you say "bind", you really mean, "Autogenerate a bit of code just as if I'd written, scala> val myC = c." Oh, and compile it, and then make myC a symbol that can get imported by the rest of the REPL session.

When you compile that code with the REPL on the boot class path, the boot class path must be able to see your class C. (It must also be the same class loaded by your application class loader, the one that loads your main class; that is usually true by virtue of delegation.)

So, this works:

scalac -d /tmp/out mytest.scala scala -J-Xbootclasspath/a:/tmp/out mytest.Test

You could nuance that by putting only some of your classes on the boot class path, or, which is more likely, you'll do as I suggested and take scala off the boot class path.

I haven't researched this, but you could google for people with similar problems using the REPL embedded in managed environments where it really matters what class loader you reside in.

Bonus utility:

package scala { package object foo { def show(cl: ClassLoader): String = scala.reflect.runtime.ReflectionUtils.show(cl) } }

to use a scala-private utility for just dumping your class loader of interest:

import scala.foo._ Console println show(getClass.getClassLoader)

Recommend

  • Not a valid Win32 application… Python, PyInstaller, Windows7
  • Why does VB.NET Jet 4.0 app crash if Office not installed?
  • TypeError in Rhino: migration from Java 6 to Java 7
  • Numeric to Alphabetic Lettering Function in R [duplicate]
  • Powershell Regex to replace XML tag values
  • jQuery UI Autocomplete with scrollbar z-index help
  • Regex to remove word from XSLT
  • Getting contents of square brackets, avoiding nested brackets
  • Add-In Commands Ribbon shows in Excel Online but not in Excel for Windows
  • How can I refer to multiple databases using the same looping vector in R?
  • c# parsing xml with and apostrophe throws exception
  • JSP compilation error on Generics
  • Partial String Replacement using PowerShell
  • Scala's collect inefficient in Spark?
  • How to replace one set of color 'shades' with another set
  • Any function in numpy/pandas/python to search and replace
  • Do commands run from current directory in a shell script?
  • Can someone please explain how this implementation of bucket sort works?
  • Add Windows Feature from C#
  • Prolog Ambiguous Output
  • Mocha throws unexpected token error for ES6 object spread operator
  • Android Studio Can't Find tools.jar
  • Android Studio 1.3 RC3. Google Play services out of date. Requires 7571000 but found 6774470
  • How do I include a SWC in an AS2 Flash project?
  • How to add a focus style to an editable ComboBox in WPF
  • How do I superscript characters in a UIButton?
  • Functions in global context
  • Is my CUDA kernel really runs on device or is being mistekenly executed by host in emulation?
  • Does CUDA 5 support STL or THRUST inside the device code?
  • R: gsub and capture
  • jqPlot EnhancedLegendRenderer plugin does not toggle series for Pie charts
  • How to format a variable of double type
  • Comma separated Values
  • coudnt use logback because of log4j
  • Can Visual Studio XAML designer handle font family names with spaces as a resource?
  • How can I remove ASP.NET Designer.cs files?
  • Are Kotlin's Float, Int etc optimised to built-in types in the JVM? [duplicate]
  • JaxB to read class hierarchy
  • Running Map reduces the dimensions of the matrices
  • How to load view controller without button in storyboard?