Scala Script Engine creating another instance of a singleton

So, I'm creating a scripting system using JSR 223 for Scala, but I came across this problem I can't find any cause for.

There is a singleton-like class, which has methods to add event listeners (from the scripts) and dispatch events (from the core). Everything worked fine, but for some reason the added listeners had disappeared when I got to dispatch an event.

After reproducing the problem, I found out that the script engine creates another instance of the singleton:

Here is my Singleton class:

package test;

import java.util.Arrays;

public final class Singleton {

    private static final Singleton instance = new Singleton();

    private Singleton() {
        Arrays.stream(Thread.currentThread().getStackTrace()).forEach(System.out::println);
        System.out.println();
    }

    public static Singleton instance() {
        return instance;
    }
}

And here is my Main class:

package test;

import javax.script.ScriptEngine;
import javax.script.ScriptEngineManager;
import javax.script.ScriptException;

public final class Main {

    public static void main(String[] args) throws ScriptException {

        ScriptEngine engine = new ScriptEngineManager().getEngineByName("scala");

        // this is a trick I found to access the classpath,
        // might be the problem
        @SuppressWarnings("rawtypes")
        scala.collection.immutable.List nil = scala.collection.immutable.Nil$.MODULE$;
        @SuppressWarnings("unchecked")
        scala.collection.immutable.$colon$colon<String> vals = scala.collection.immutable.$colon$colon$.MODULE$.apply("true", nil);
        ((scala.tools.nsc.interpreter.IMain) engine).settings().usejavacp().tryToSet(vals);

        engine.eval("test.Singleton.instance");
        Singleton.instance();
    }
}

And here is the output:

java.lang.Thread.getStackTrace(Unknown Source)
test.Singleton.<init>(Singleton.java:10)
test.Singleton.<clinit>(Singleton.java:7)
$line3.$read$$iw$$iw$.<init>(<console>:8)
$line3.$read$$iw$$iw$.<clinit>(<console>)
$line3.$eval$.$result$lzycompute(<console>:5)
$line3.$eval$.$result(<console>:5)
$line3.$eval.$result(<console>)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
java.lang.reflect.Method.invoke(Unknown Source)
scala.tools.nsc.interpreter.IMain$ReadEvalPrint.call(IMain.scala:773)
scala.tools.nsc.interpreter.IMain$ReadEvalPrint.callEither(IMain.scala:777)
scala.tools.nsc.interpreter.IMain$ReadEvalPrint.evalEither(IMain.scala:792)
scala.tools.nsc.interpreter.IMain$WrappedRequest.eval(IMain.scala:613)
scala.tools.nsc.interpreter.IMain.eval(IMain.scala:1047)
javax.script.AbstractScriptEngine.eval(Unknown Source)
test.Main.main(Main.java:19)

java.lang.Thread.getStackTrace(Unknown Source)
test.Singleton.<init>(Singleton.java:10)
test.Singleton.<clinit>(Singleton.java:7)
test.Main.main(Main.java:20)

The stack trace shows that the script engine ends up creating a new instance of Singleton, but I got no idea why.

Thank you.

Answers


Found out the fix after browsing the source code:

((scala.tools.nsc.interpreter.IMain) engine).settings().embeddedDefaults(Main.class.getClassLoader());

This changes the ClassLoader for the ScriptEngine to the same one.


Need Your Help

How can I go back to the initial view controller in Swift?

swift uinavigationcontroller pushviewcontroller

So I have a login view, after successful login it goes to the first view of a navigation controller, then the user can go deeper to a settings view and then to a logout view. This logout should tak...