Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add and remove Jar files and classes from inside JavaScript (Rhino / Nashorn)

Basically I have Java a system which runs a number of "plugin" scripts using Javascript through either Rhino or Nashorn, depending on what JRE the user has installed.

I also have a system within the Java environment that allows the plugging in of extra .JAR files at runtime.

That's all fine and dandy. However I have now come across a situation where I want something slightly different: I want to load a .JAR file into the ClassPath from within the Rhino/Nashorn engine instance, so the classes are available to that instance (and that instance only), and then remove them when the engine finishes running.

I know I can easily call my existing Java routine to load the URL of the .JAR file from with JavaScript, however the classes are then permanently installed and I can't get rid of them.

The problem basically stems from the fact that a user could have multiple plugins with different versions of the same .JAR file (it's provided by a third party and used for multiple different plugins in different ways), and I need the plugins to be able to load the right one and then ditch it afterwards.

My existing URL loader is:

public static void addURL(URL u) {
    final Class[] parameters = new Class[]{URL.class};
    URLClassLoader sysloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
    Class sysclass = URLClassLoader.class;

    try {
        Method method = sysclass.getDeclaredMethod("addURL", parameters);
        method.setAccessible(true);
        method.invoke(sysloader, new Object[]{u});
    } catch (Exception ex) {
        ex.printStackTrace();
    }
}

Now I don't actually have much of a clue how that works - I'm not a power Java programmer (I do C/C++ mainly). I know that you can't "unload" a URL from the URLClassLoader, so I'm not asking that. What would be best, I guess, is if there was a way I could add the .JAR file to a "temporary" URLClassLoader which I then ditch at the end of execution. Or some way I can just load the classes directly into the script engine and not the main Java ClassPath.

If it's something I could just call from JavaScript directly that would be great, but I don't mind implementing some Java methods to do the job if needed, or even extending the scripting engine in some way.

like image 529
Majenko Avatar asked Feb 03 '17 11:02

Majenko


People also ask

Is Nashorn deprecated?

The Nashorn engine has been deprecated in JDK 11 as part of JEP 335 and and has been removed from JDK15 as part of JEP 372. GraalVM can step in as a replacement for JavaScript code previously executed on the Nashorn engine.

Which of the following JavaScript engine was replaced with Nashorn?

Technical Article. Until Java SE 7, JDKs shipped with a JavaScript scripting engine based on Mozilla Rhino. Java SE 8 will instead ship with a new engine called Oracle Nashorn, which is based on JSR 292 and invokedynamic .

Can we run JavaScript on JVM?

js runtime cannot be embedded into a JVM but has to be started as a separate process. By setting the classpath, you instruct node to start a JVM properly. Both Node. js and JVM then run in the same process and the interoperability works using the same Value classes as above.

What is ScriptEngine in Java?

ScriptEngine is the fundamental interface whose methods must be fully functional in every implementation of this specification. These methods provide basic scripting functionality. Applications written to this simple interface are expected to work with minimal modifications in every implementation.


1 Answers

To isolate the plugin specific classes, you may need to create a separate (custom) class loader instance and pass it to the java script engine. Any class loaded by the particular class loader will only be visible to the particular java script engine.

I found this answer which describe the class loader in context of ScriptEngine.

I hope this helps you to move forward in right direction.

like image 132
skadya Avatar answered Oct 04 '22 09:10

skadya