Comment by twic
1 day ago
$ echo 'class Hello { public static void main(String[] args) { System.out.println("Hello, world"); } }' >Hello.java
$ javac Hello.java
$ java --version
openjdk 21.0.7 2025-04-15 LTS
OpenJDK Runtime Environment Zulu21.42+21-CRaC-CA (build 21.0.7+6-LTS)
OpenJDK 64-Bit Server VM Zulu21.42+21-CRaC-CA (build 21.0.7+6-LTS, mixed mode, sharing)
$ time java -cp . Hello
Hello, world
real 0m0.026s
user 0m0.010s
sys 0m0.018s
For some reason this machine is still on 21. Anyway, the overhead of the JVM itself is pretty low.
For small tools it's fine:
$ echo 'class Dig { public static void main(String[] args) throws Exception { var addr = java.net.InetAddress.getByName(args[0]); System.out.println(addr); } }' >Dig.java
$ javac Dig.java
$ time java -cp . Dig news.ycombinator.com
news.ycombinator.com/209.216.230.207
real 0m0.047s
user 0m0.026s
sys 0m0.021s
$ time host news.ycombinator.com
news.ycombinator.com has address 209.216.230.207
news.ycombinator.com has IPv6 address 2606:7100:1:67::26
real 0m0.052s
user 0m0.005s
sys 0m0.004s
Java startup gets slow when you use some massive framework like Spring. If you need a program to start fast, don't use one!
You can also choose to run directly from source with a small penalty at startup and verbosity has decreased for simple use cases. It's still not great for scripting but the situation has been steadily improving over the last couple of years.
You can also use a shebang and mark the file as executable on Linux:
Spring is slow because it scans the classpath, uses reflection and generates proxy classes all at startup. You can avoid some of that using the Spring AOT feature in newer versions.
Or you can just use a different framework like Micronaut which does none of that and uses an annotation processor at compile time instead. (Similar to Spring AOT, with fewer limitations)