how can I re-instantiate a class instanced by javascript (Nashorn Engine)

Tags: , , ,



so, i instantiate a new class in javascript, and then add it to a list … Later I go through the list and instantiate all the classes again, to work with them.

the Javascript:

var BPmanager = Java.type('paperVS.tabs.blueprint.BlueprintManager');
var abstractFunction= Java.extend(Java.type('paperVS.logic.function.Function'));

var getYPos = new abstractFunction("getYPos") {

   //Some Functions
}

BPmanager.allFunctions.add(getYPos);

and later in Java:

for (Function fun : allFunctions) { 
     try {
        Class<?> c = Class.forName(fun.getClass().getName());
        Object object = c.newInstance();
        instances.add((Function)object);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

Exeption:

java.lang.ClassNotFoundException: jdk.nashorn.javaadapters.paperVS_logic_function_Function
    at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
    at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
    at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
    at paperVS.tabs.blueprint.BlueprintManager.getFromList(BlueprintManager.java:176)

This code works for all classes except the Javascript classes. The Javascript works fine (loading and executing the single instance), but not instancing of the Class. The normal ClassLoader does the same

Answer

Java ClassLoaders use a delegation model, where the system instantiates a “primordial” (or “system”) class loader, and then class loaders can be created that look in specialized places for classes, and if not found, look in the ancestor (or delegate) class loader.

Nashorn has its own internal class loaders to deal with script classes; see Java 8 ScriptEngine across ClassLoaders. So you are creating classes in those class loaders, and then trying to use them in an ancestor class loader (you can see that in the stack trace) by name.

So that’s one problem to solve.

Another is that these types created by Java.extend are Nashorn-managed objects, bound to a particular Nashorn script context, and will be inconvenient to use from other Java code (see comments below, where the OP notes that the classes can’t be used easily, even if they’re accessible).

If you want to use the JavaScript-created objects in Java code, you’ll want to create Java objects and then pass them back to Java. You seem to be doing this, so perhaps you’re just using them incorrectly. Making guesses based on your class names, etc., I am guessing that rather than:

Class<?> c = Class.forName(fun.getClass().getName());
Object object = c.newInstance();
instances.add((Function)object);

… you may just want something like:

instances.add((Function)fun);


Source: stackoverflow