I am currently executing my JavaScript-scripts with this java code:
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(new FileReader("awesome_script.js"));
I need to call Java functions from JavaScript, so I defined this at the top of my awesome_script.js
file:
var first = Java.type('io.github.awesomeprogram.FirstClass');
var second = Java.type('io.github.awesomeprogram.SecondClass');
var extra = Java.type('io.github.awesomeprogram.ExtraClass');
I can then call some methods from these classes, e.g.:
second.coolmethod("arg1",2);
My problem is now that I need to use many java classes inside of my scripts. I also have a lot of scripts and I think it is very inefficient to define every single one of this classes in every script.
So I am looking for a solution to create the objects created inside of JavaScript with Java.type()
inside of Java and then pass them to the script I want to execute.
How can I do this?
Thanks in advance!
After quite a bit of research I found a way to put global variables in the ScriptEngine before executing: The Java Scripting API (Oracle Docs)
This enabled me to put any object I want into a global variable. However, I still needed a way to get the Object that Java.type()
creates inside of Java. So I wrote a test script which returns one of this objects and I found out it is an object of the type jdk.internal.dynalink.beans.StaticClass
. This class has an constructor which takes a ordinary Class
as an argument. Sadly, this constructor is not usable in my code because it is not visible. To bypass this I used reflection and made this method:
public StaticClass toNashornClass(Class<?> c) throws ClassNotFoundException, NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException, IllegalArgumentException, InvocationTargetException{
Class<?> cl = Class.forName("jdk.internal.dynalink.beans.StaticClass");
Constructor<?> constructor = cl.getDeclaredConstructor(Class.class);
constructor.setAccessible(true);
StaticClass o = (StaticClass) constructor.newInstance(c);
return o;
}
If I pass the Class
of the object I want as a global variable I just need to call toNashornClass(Example.class);
and put the resulting object into a global var with engine.put("example",object);
It works fine. I can use the example
var completely like a var created by Java.type()
.