Question

I am seeing an odd problem when using an embedded Scala interpreter. It manifests itself as a corruption (?) of the hosting (non-interpreter) class loader. It roughly goes like this:

  • I have a class Foo in the hosting environment
  • I am matching against Foo in some place (case f: Foo => ...)
  • I am running the interpreter at some point (IMain -> interpret)
  • After that the pattern match for Foo fails; if I check the class it is Foo but it does not match with Foo

So I except that there are now two competing class loaders which produce two non-identical instances of class Foo. There is only one Foo in my entire class path, so there is no way that it could be shadowed. Also, it is sufficient to run something like 1 + 1 in the interpreter, so there is absolutely no way that the IMain itself tried to load class Foo.

I know this is very vague, but I am hoping for hints as to trace the bug.


Edit: After further investigation, this problem occurs only when building against Scala 2.11.0, but disappears when building against 2.10.4; I ensured that the builds were made from clean-state. This worries me, because it could indicate a new problem with the 2.11 interpreter?

The class involved (Foo in the example) is a Java class, so there is also no reason to believe it was compiled against the wrong Scala version.


Edit: After further investigation, this problem might relate to Java Swing rather than the Scala interpreter. Foo is actually a javax.swing.text.Document sub-class, and I can see some problems with JEditorPane (How can I safely solve this Java context classloader problem?) and Swing threading (http://bugs.java.com/view_bug.do?bug_id=8017776). I am using OpenJDK 6 and OpenJDK 7, I believe OpenJDK 6 is a fork off OpenJDK 7, so it might still be the problem showing up in the Bug database.

Was it helpful?

Solution

It appears that in Scala 2.11.0, the interpreter sets the thread's context class loader but does not restore it to its previous value.

The following is a workaround:

val th = Thread.currentThread()
val cl = th.getContextClassLoader
try {
  intp.interpret(text)
} finally {
  th.setContextClassLoader(cl)
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top