1

I have a non-modular Java 15 application that depends on stand-alone Nashorn (as an example).

I have a maven project set up in Intellij with the Nashorn dependency:

<dependency>
    <groupId>org.openjdk.nashorn</groupId>
    <artifactId>nashorn-core</artifactId>
    <version>15.0</version>
</dependency>

And the following Main class to test with:

public class Main {    
    public static void main(String[] args) throws ScriptException {
        ScriptEngineManager factory = new ScriptEngineManager();
        ScriptEngine engine = factory.getEngineByName("nashorn");
        engine.eval("print('Hello, World!');");
    }    
}

Since my application is non-modular, I don't have a module-info.java file, and when running the main class (by clicking the green play button) Intellij puts my main class and all the dependencies on the class path:

"C:\Program Files\Java\jdk-15\bin\java.exe" "-javaagent:J:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2020.1.1\lib\idea_rt.jar=53813:J:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2020.1.1\bin" -Dfile.encoding=UTF-8 -classpath "H:\WS-new\non-modular nashorn\target\classes;C:\Users\Jorn\.m2\repository\org\openjdk\nashorn\nashorn-core\15.0\nashorn-core-15.0.jar;C:\Users\Jorn\.m2\repository\org\ow2\asm\asm\7.3.1\asm-7.3.1.jar;C:\Users\Jorn\.m2\repository\org\ow2\asm\asm-commons\7.3.1\asm-commons-7.3.1.jar;C:\Users\Jorn\.m2\repository\org\ow2\asm\asm-analysis\7.3.1\asm-analysis-7.3.1.jar;C:\Users\Jorn\.m2\repository\org\ow2\asm\asm-tree\7.3.1\asm-tree-7.3.1.jar;C:\Users\Jorn\.m2\repository\org\ow2\asm\asm-util\7.3.1\asm-util-7.3.1.jar" main.Main

However, since Nashorn can only be used as a JPMS module, the program ends up failing with an NPE:

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "javax.script.ScriptEngine.eval(String)" because "engine" is null
    at main.Main.main(Main.java:12)

It works if I run the program from the command line and put Nashorn and it's dependencies on the module path instead of the class path.

java -classpath <dir with Main class> --module-path <nashorn jars> --add-modules org.openjdk.nashorn main.Main

How can I tell IntelliJ to put Nashorn and it's dependencies on the module path, instead of the class path as well?

Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93
  • Using Maven generally places the dependencies on the modulepath itself using Java-9 and above, isn't that the case with Nashorn too? – Naman Dec 13 '20 at 02:53
  • Doesn't seem like it. I have (maven.compiler.)source and target set to 15 in the pom, but IntelliJ still puts things on the class path. From looking around on the internet this seemed to be up to having a module-info.java file in the IntelliJ module (which I explicitly don't want, since I want to know how to make it work for non-modular applications). – Jorn Vernee Dec 13 '20 at 13:05
  • FWIW, I'm still running this with the standard intellij "Application" runner. I'm just using Maven to get the dependency. – Jorn Vernee Dec 13 '20 at 13:27

1 Answers1

3

Unfortunately, there doesn't currently seem to be a way in Intellij to flag certain dependencies as being modular only, to have them put on the module path instead of the class path automatically.

But, you can make it work by manually adding the Nashorn jar and it's dependencies to the module path, as well as adding the org.openjdk.nashorn module, as additional VM options in the run configuration:

enter image description here

Here I've just copied the part of the class path from Intellij's run command that contained Nashorn and it's dependencies.

You might need to enable the "VM options" field in the form first by clicking on the "Modify options" link:

enter image description here

This makes the program run as expected, printing 'Hello, World!'. It looks like Intellij will still put these jars on the class path as well, but since the module path takes precedence over the class path this works any ways.

Jorn Vernee
  • 31,735
  • 4
  • 76
  • 93