Java 11 comes with a bunch changes and features (17 as listed here) one of which is JEP 330 which grants the ability of running a program from source without a separate compilation session; in other words you can now compile and run code in one go. JEP 330 describes the rules that must be followed to make use of this feature such as:
- A single source file ought to be provided as argument, additional files are ignored.
- The code must not have external dependencies other than
java.base
module. - The code is compiled under the unnamed module.
- Program arguments may be supplied.
- A compilation error stops the procedure and the program is not launched.
- The top level class does not have to match the file name.
Decided to take this feature for a spin and time the execution. The test code is a simple hello world program consisting of two classes as seen in the following snippet
HelloWorld.java
public class HelloWorld { public static void main(String[] args) { System.out.println("Hello Java 11"); System.out.println("Hello " + new World()); } } class World { public String toString() { return "World!"; } }
Next I created two launch scripts, one that relies on the new feature and the other that compiles and runs the code the old fashioned way
runFromSource.sh
#!/usr/bin/java --source 11 HelloWorld.java
compileAndRun.sh
/usr/bin/javac HelloWorld.java /usr/bin/java HelloWorld
Then proceeded to time them several times, the results were quite similar
$ time runFromSource.sh Hello Java 11 Hello World! real 0m0.691s user 0m1.489s sys 0m0.106s $ time compileAndRun.sh Hello Java 11 Hello World! real 0m0.778s user 0m1.206s sys 0m0.109s
As you can see the time difference is not substantial however running from source skips generating intermediate class files that may be left lingering on your system if you don't clean up afterwards. Just for kicks I wrote a similar Apache Groovy script with equivalent behavior
hello.groovy
class World { String toString() { 'World!' } } println 'Hello Groovy 11' println "Hello ${new World()}"
Its corresponding launch shell script
runGroovy.sh
$GROOVY_HOME/bin/groovy hello.groovy
Yields a similar time as the previous two options
time runGroovy.sh Hello Groovy 11 Hello World! real 0m0.908s user 0m1.554s sys 0m0.154s
Of course the elephant in the room is: what about additional dependencies? As it currently stands this feature is not really groundbreaking, but (and here comes a big) IF a future release of Java adds the ability to specify additional modules that provide the much needed extra behavior THEN we have a clear winner.
Or you can simply give Apache Groovy and its @Grab feature a try, it's been working like a charm for 10 years now.
Keep on Coding!