Issue
I'd like to use JEP 330 to run a single-file source-code program with Java (>= 11).
Doing so, I'd like to pass options understood by the compiler (javac) but not the runtime (java), e.g. -XDsuppressNotes
. This causes e.g. the following invocation to fail:
java --enable-preview --source=12 -XDsuppressNotes Test.java
Unrecognized option: -XDsuppressNotes
Error: Could not create the Java Virtual Machine.
Error: A fatal exception has occurred. Program will exit.
How can I specify such compiler-specific option in this case?
Solution
How can I specify such compiler-specific option in this case?
Short answer: you can't.
The goal of this JEP is not to replace javac
! It is merely to make it more convenient, especially in the context of beginning programming to achieve the goal of "run this program".
JEP-330 has a set of limitations in comparison to standard javac -> java chain. Quotes from the JEP itself:
As of JDK 10, the java launcher operates in three modes: launching a class file, launching the main class of a JAR file, or launching the main class of a module. Here we add a new, fourth mode: launching a class declared in a source file.
...
In source-file mode, the effect is as if the source file is compiled into memory, and the first class found in the source file is executed. For example, if a file called HelloWorld.java contains a class called hello.World, then the command
java HelloWorld.java
is informally equivalent to
javac -d <memory> HelloWorld.java
java -cp <memory> hello.World
Any arguments placed after the name of the source file in the original command line are passed to the compiled class when it is executed. For example, if a file called Factorial.java contains a class called Factorial to calculate the factorials of its arguments, then the command
java Factorial.java 3 4 5
is informally equivalent to
javac -d <memory> Factorial.java
java -cp <memory> Factorial 3 4 5
In source-file mode, any additional command-line options are processed as follows:
The launcher scans the options specified before the source file for any that are relevant in order to compile the source file. This includes: --class-path, --module-path, --add-exports, --add-modules, --limit-modules, --patch-module, --upgrade-module-path, and any variant forms of those options. It also includes the new --enable-preview option, described in JEP 12.
No provision is made to pass any additional options to the compiler, such as -processor or -Werror.
...
In other words, there are certain limitations the one should keep in mind while running single-file source-code Java programs:
No outside classes, Single-File Programs only - you may not invoke any other classes in files other than the file you are executing.
No class files available - the invocation of the
java
tool in this manner does not produce any*.class
files you can see in your working directory.If existing class file exists in classpath, you’re forced to use it - For a file, say
SampleClass.java
, should an existing class file, say,SampleClass.class
exist, you may not invoke thejava
tool to run your source file in source-file mode.File name, not class name - the
java
tool considers the name of the file and NOT the name of the class in executing source files.First class in the file, not matching file-class names - the class loader no longer determines the class to be executed by matching file name and class name. The first class in the file is the one that will be run,
No limits on public files in a source file - While
javac
cares about the amount of public classes in a source file,java
couldn’t care less.You may not pass certain compiler specific arguments - the arguments like
-Werror
or-nowarn
that you can pass tojavac
, may not be passed (or recognized for that matter) by thejava
tool.
Answered By - Mikhail Kholodkov
Answer Checked By - Gilberto Lyons (JavaFixing Admin)