New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
IMain interpret does not reset context classloader #8521
Comments
Imported From: https://issues.scala-lang.org/browse/SI-8521?orig=1 |
@gourlaysama said: $ cat test.scala
import scala.tools.nsc.interpreter.IMain
object Test extends App {
val cl = Thread.currentThread().getContextClassLoader
println(cl)
val imain = new IMain()
imain.interpret("println(42)")
val cl2 = Thread.currentThread().getContextClassLoader
println(cl2)
println(cl == cl2)
}
$ scala Test
scala.reflect.internal.util.ScalaClassLoader$URLClassLoader@1f32e575
42
scala.reflect.internal.util.ScalaClassLoader$URLClassLoader@1f32e575
true |
Martin Grotzke (martin.grotzke) said (edited on May 15, 2015 10:12:49 PM UTC): This happened in tests (scalatest), where in consequence other tests that try to create an ActorSystem fail because in akka some components are created via reflection relying on the thread context CL: sbt.ForkMain$ForkError: interface akka.actor.Scheduler is not assignable from class akka.actor.LightArrayRevolverScheduler
at akka.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:69)
at akka.actor.ReflectiveDynamicAccess$$anonfun$getClassFor$1.apply(DynamicAccess.scala:66)
at scala.util.Try$.apply(Try.scala:191)
at akka.actor.ReflectiveDynamicAccess.getClassFor(DynamicAccess.scala:66)
at akka.actor.ReflectiveDynamicAccess.createInstanceFor(DynamicAccess.scala:84)
at akka.actor.ActorSystemImpl.createScheduler(ActorSystem.scala:676)
at akka.actor.ActorSystemImpl.<init>(ActorSystem.scala:576)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:142)
at akka.actor.ActorSystem$.apply(ActorSystem.scala:109)
at foo.bar.SomeSpec.<init>(SomeSpec.scala:32)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:422)
at java.lang.Class.newInstance(Class.java:442)
at org.scalatest.tools.Framework$ScalaTestTask.execute(Framework.scala:641)
at sbt.ForkMain$Run$2.call(ForkMain.java:294)
at sbt.ForkMain$Run$2.call(ForkMain.java:284)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
at java.lang.Thread.run(Thread.java:745) I can reproduce this with this App run from sbt with package foo
import javax.script.ScriptEngineManager
object Main extends App {
val ngine = new ScriptEngineManager().getEngineByName("scala")
val iMain = ngine.asInstanceOf[scala.tools.nsc.interpreter.IMain]
class Foo
iMain.settings.embeddedDefaults[Foo]
println(Thread.currentThread().getContextClassLoader)
iMain.compile("val x = 1")
println(Thread.currentThread().getContextClassLoader)
} scala version is 2.11.6 |
@som-snytt said: |
https://users.scala-lang.org/t/java-scriptengine-cannot-cast-to-scripted/1166 recaps the reproduction from two years ago. |
Another mode of suffering https://gitter.im/scala/scala?at=59b75be4177fb9fe7eacd7f1 https://gist.github.com/cnestor/2c1658d67cf2997a5cc586c7fb0b7fb0 where log4j loads script engines. And then everything breaks. |
I was just bitten by this again in 2.13.0-M5. Thought the issue was solved. I don't really understand this merge. Is it only for Scala 2.12? In the meantime I will reinstall my patch in my IMain subclass like so // work-around for SI-8521 (Scala 2.11.0)
override def interpret(line: String, synthetic: Boolean): Results.Result = {
val th = Thread.currentThread()
val cl = th.getContextClassLoader
try {
super.interpret(line, synthetic)
} finally {
th.setContextClassLoader(cl)
}
} I think the issue should be re-opened and tagged 2.13.x? |
@Sciss yes, it was never forward-ported over the scary REPL refactor. I'll refresh my memory and make a PR. One really does take forward-merging for granted. |
scala/scala#7544 for 2.13 (scala/scala#5657 for 2.12) |
Calling
interpret
sets the current thread's context classloader, but fails to reset it to its previous state when returning from that method.The following workaround illustrates the problem:
Jason Zaugg suggests that the following might be the regression: scala/scala@3a30af1#diff-36a995091016ecd5cdb97e267764e05aL538
The text was updated successfully, but these errors were encountered: