JEP 330
Peter Levart
peter.levart at gmail.com
Tue Jun 5 08:11:57 UTC 2018
Hi,
On 06/03/2018 09:45 PM, Jonathan Gibbons wrote:
>> As an idealist, I might want Class.getResourceAsStream to return
>> the contents of a side file to the script file. But it's more likely to
>> return null, given the strategy of compiling the script into a temporary
>> artifact in an undisclosed location.
> Class.getResourceAsStream will find items on the classpath used by the VM.
...this will find the "content" of items on the classpath. If one wants
to find the "location" (i.e. URL) Class.getResource() will return it.
But in the context of java launcher executing a "source" file, searching
for location of the executing class would return some URL pointing to
"memory" where the source was compiled to, wouldn't it? Not something
that could be used to locate "side" files - files in the same directory
as source/script file.
I know that the main purpose of this JEP is to provide a stepping stone
for beginners in the Java world. But the experienced will always find it
also as a means to write executable scripts in Java. For the later it is
important that the feature allows writing scripts that are as portable
as possible. I see one obstacle to achieve that. The location of java
launcher executable is not standardized across platforms (even UNIX
platforms). So hard-coding absolute path in the shebang script is bound
to create non portable script. Locating the java launcher using PATH
would be much more portable. Java, if installed properly, is usually
added to PATH. The standard way to locate script interpreters using PATH
is by indirection through /bin/env utility:
#!/bin/env java
public class Cmd {
public static void main(String ...args) {
...
}
}
While this works and passes script arguments to java executable as
intended, it does not work when combined with additional options passed
to script interpreter (like "--source 11") in the script itself:
#!/bin/env java --source 11
public class Cmd {
public static void main(String ...args) {
...
}
}
At least on Linux, env tries to locate executable called "java --source
11" on the PATH and bails out with:
/bin/env: ‘java --source 11’: No such file or directory
So the best bet here is a hybrid script that starts as a bash script
which "computes" the environment and paths and then executes java
launcher with all required arguments. One way to do that is using "here"
documents. Stuart Marks provided an example:
#!/bin/bash
exec java --source 11 /dev/fd/3 "$@" 3<<EOF
public class Hello {
public static void main(String[] args) {
String name = System.console().readLine("Please enter your
name: ");
System.console().printf("Hello, %s!%n", name);
}
}
EOF
This script uses an OS feature where special file /dev/fd/N when opened,
provides a file handle dup-ed from the file handle N. I don't know how
portable this is across UNIX-es. Linux and Mac at least do have it and
use same paths. What about other UNIX-like OS-es where OpenJDK is built?
If for some OS the feature is not available, then java launcher could
help here by interpreting a special syntax of file specified as
"/dev/fd/N" and executing the necessary dup itself on such OS.
What do you think?
Regards, Peter
More information about the compiler-dev
mailing list