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

VB.net lag across different machines

vb.net timer lag

I wrote a small little key inventory program. Basically it uses an INI file to know what keys we have and which ones are signed out, to whom, by whom, etc. It is run on up to 4 computers all in th...

MOSS 2007 KeepAlive File

sharepoint moss

I have a standard MOSS 2007 Web Site (MOSS Terminology: Application and a SiteCollection)