🏷 Tooling
9 patterns
Topic: Tooling
All Java patterns related to Tooling — java.evolved
Language
Compact source files
Old
public class HelloWorld {
public static void main(String[] args) {
System.out.println(
"Hello, World!");
}
}
Modern
void main() {
IO.println("Hello, World!");
}
hover to see modern →
JDK 25+
learn more →
Tooling
AOT class preloading
Old
// Every startup:
// - Load 10,000+ classes
// - Verify bytecode
// - JIT compile hot paths
// Startup: 2-5 seconds
Modern
// Training run:
$ java -XX:AOTCacheOutput=app.aot \
-cp app.jar com.App
// Production:
$ java -XX:AOTCache=app.aot \
-cp app.jar com.App
hover to see modern →
JDK 25+
learn more →
Tooling
Built-in HTTP server
Old
// Install and configure a web server
// (Apache, Nginx, or embedded Jetty)
// Or write boilerplate with com.sun.net.httpserver
HttpServer server = HttpServer.create(
new InetSocketAddress(8080), 0);
server.createContext("/", exchange -> { ... });
server.start();
Modern
// Terminal: serve current directory
$ jwebserver
// Or use the API (JDK 18+)
var server = SimpleFileServer.createFileServer(
new InetSocketAddress(8080),
Path.of("."),
OutputLevel.VERBOSE);
server.start();
hover to see modern →
JDK 18+
learn more →
Tooling
Compact object headers
Old
// Default: 128-bit object header
// = 16 bytes overhead per object
// A boolean field object = 32 bytes!
// Mark word (64) + Klass pointer (64)
Modern
// -XX:+UseCompactObjectHeaders
// 64-bit object header
// = 8 bytes overhead per object
// 50% less header memory
// More objects fit in cache
hover to see modern →
JDK 25+
learn more →
Tooling
JFR for profiling
Old
// Install VisualVM / YourKit / JProfiler
// Attach to running process
// Configure sampling
// Export and analyze
// External tool required
Modern
// Start with profiling enabled
$ java -XX:StartFlightRecording=
filename=rec.jfr MyApp
// Or attach to running app:
$ jcmd <pid> JFR.start
hover to see modern →
JDK 9+
learn more →
Tooling
JShell for prototyping
Old
// 1. Create Test.java
// 2. javac Test.java
// 3. java Test
// Just to test one expression!
Modern
$ jshell
jshell> "hello".chars().count()
$1 ==> 5
jshell> List.of(1,2,3).reversed()
$2 ==> [3, 2, 1]
hover to see modern →
JDK 9+
learn more →
Tooling
JUnit 6 with JSpecify null safety
Old
import org.junit.jupiter.api.Test;
import static org.junit.jupiter.api.Assertions.*;
class UserServiceTest {
// JUnit 5: no null contracts on the API
// Can assertEquals() accept null? Check source...
// Does fail(String) allow null message? Unknown.
@Test
void findUser_found() {
// Is result nullable? API doesn't say
User result = service.findById("u1");
assertNotNull(result);
assertEquals("Alice", result.name());
}
@Test
void findUser_notFound() {
// Hope this returns null, not throws...
assertNull(service.findById("missing"));
}
}
Modern
import org.junit.jupiter.api.Test;
import org.jspecify.annotations.NullMarked;
import org.jspecify.annotations.Nullable;
import static org.junit.jupiter.api.Assertions.*;
@NullMarked // all refs non-null unless @Nullable
class UserServiceTest {
// JUnit 6 API is @NullMarked:
// assertNull(@Nullable Object actual)
// assertEquals(@Nullable Object, @Nullable Object)
// fail(@Nullable String message)
@Test
void findUser_found() {
// IDE warns: findById returns @Nullable User
@Nullable User result = service.findById("u1");
assertNotNull(result); // narrows type to non-null
assertEquals("Alice", result.name()); // safe
}
@Test
void findUser_notFound() {
@Nullable User result = service.findById("missing");
assertNull(result); // IDE confirms null expectation
}
}
hover to see modern →
JDK 17+
learn more →
Tooling
Multi-file source launcher
Old
$ javac *.java
$ java Main
// Must compile all files first
// Need a build tool for dependencies
Modern
$ java Main.java
// Automatically finds and compiles
// other source files referenced
// by Main.java
hover to see modern →
JDK 22+
learn more →
Tooling
Single-file execution
Old
$ javac HelloWorld.java
$ java HelloWorld
// Two steps every time
Modern
$ java HelloWorld.java
// Compiles and runs in one step
// Also works with shebangs:
#!/usr/bin/java --source 25
hover to see modern →
JDK 11+
learn more →