How to pass compiler options when running a single-file source-code Java program?
Asked Answered
M

2

8

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?

Mollee answered 15/12, 2018 at 21:10 Comment(10)
javac is the compiler. java is not the compiler. Test.java is not a compiled class file. So your question is very unclear.Fierce
JEP 330 (linked above) allows to compile and run a Java file with a single invocation of the java command.Mollee
Link says: In source-file mode, compilation proceeds as follows: Any command-line options that are relevant to the compilation environment are taken into account. (sounds like a defect to me).Fierce
@Mollee Just to confirm, what is that flag supposed to do? Which version of Java are you using precisely?Cristiano
I'm using Java 12 (b23), and this flag suppresses notes emitted by the compiler. The question is a general one, though, it's not specific to that option.Mollee
The source launcher will use options specified to the java launcher that are applicable to compilation (--class-path, --module-path, etc.) but there isn't, AFAIK, a way to augment this with other compilation options.Mortification
I see, thanks for confirming, @AlanBateman. IMO it'd be worth having this, I'll go and log a feature rquest for it. Btw. my use case is exploration of the switch expression preview feature, and for that I'd like to suppress the note about using this preview feature as it convolutes the output of the java invocation.Mollee
This issue was considered during the design of JEP 330. In general, it is not practical to support all javac options when using source-file mode, which means we'd get into a design discussion of which subset of options it would be reasonable to support. While it is nice to see people wanting to use source file mode, the advice has to be, if you want the full power of javac options, use javac.Talanta
Can you shed some light on why "it is not practical to support all javac options when using source-file mode"? Couldn't you simply pass through all options given with a specific prefix, e.g. "-J" als already supported by other JDK tools? No need to discuss then which options to support. Not being able to disable the preview notes is a quite a turn off for one of the interesting use cases of source file mode, that is exploration of new (preview) language features.Mollee
@ElliottFrisch What that line means is that any java launcher options (like class path) that are also relevant to compilation are passed on to the compiler.Biparietal
E
2

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 the java 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 to javac, may not be passed (or recognized for that matter) by the java tool.

Ediva answered 17/12, 2018 at 18:0 Comment(1)
Great answer. It's a pity though; not being able to disable the preview notes makes usage of preview features (which is a prime use case for source file mode) quite a bit more convoluted than it should.Mollee
B
0

Short answer: you can't.

Wrong, you can.

Strange enough, the --source 11 option must appear twice: Before and after all other options:

#!/usr/bin/java --source 11 -ea -cp path/to/jars --source 11
// There appears to be a bug in JDK 11.0.2 single-file mode: The first option must
// be "--source 11" to enable single-file mode, but then the "-cp" DISABLES
// single-file mode (bug). The workaround is to repeat the "--source 11" option
// right after the "-cp" option.

Tested with

java version "11.0.2" 2019-01-15 LTS
GNU bash, Version 4.4.12(3)-release (x86_64-unknown-cygwin)
Bordie answered 9/12, 2020 at 14:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.