What changed in Java 11

Java 11LTS

The first LTS after 8, and the one many teams still run

The migration target for everyone leaving 8, and the release that removed Java EE modules — which is why that upgrade broke builds far more often than the language changes suggested.

Released 2018-09 · 4 features · 9 questions · 2 scenarios

Features

HTTP Client (standard)

standardJEP 321

A modern HTTP client in the JDK supporting HTTP/2, WebSocket, and both synchronous and asynchronous requests.

The problem it solved

HttpURLConnection dated from HTTP/1.0, had an awkward API, and had no HTTP/2 support, so almost every project added Apache HttpClient or OkHttp for something the platform should provide.

How you did it before

HttpURLConnection for trivial cases, or a third-party client and its transitive dependencies for anything real.

Compiled and run on this build
// Built once and shared — it owns a connection pool and an executor.
var client = java.net.http.HttpClient.newBuilder()
    .connectTimeout(Duration.ofSeconds(5))
    .build();

System.out.println("version    = " + client.version());
System.out.println("timeout    = " + client.connectTimeout().orElseThrow());
System.out.println("reusable, so create one per application, not per request");
Output
version    = HTTP_2
timeout    = PT5S
reusable, so create one per application, not per request

Journey: Incubator in 9 and 10, standard in 11.

Asked as

  • Why did the JDK need a new HTTP client?
  • How do you make concurrent HTTP calls with the JDK client?
  • Is the JDK HttpClient thread-safe and reusable?

Scenario question

  • A service creates a new HttpClient per request and is running out of file descriptors under load.

    What is wrong and how do you fix it?

    What a good answer weighs

    HttpClient is designed to be created once and shared — it holds a connection pool and an executor. Creating one per request creates a pool per request and leaks the resources. Make it a singleton and configure its timeouts and executor deliberately.

String convenience methods

standard

isBlank, lines, strip, stripLeading, stripTrailing and repeat, filling gaps that every project had a StringUtils class for.

The problem it solved

trim() only removed characters below U+0020, so it did not handle Unicode whitespace, and there was no built-in way to test for whitespace-only or to stream lines.

How you did it before

Apache Commons StringUtils, Guava, or a hand-rolled utility class in every codebase.

Compiled and run on this build
System.out.println("[" + "  hi  ".strip() + "]");
System.out.println("blank? " + "   ".isBlank());
System.out.println("ab".repeat(3));
"one\ntwo".lines().forEach(l -> System.out.println("line: " + l));
Output
[hi]
blank? true
ababab
line: one
line: two

Asked as

  • What is the difference between trim() and strip()?
  • Why did trim() need replacing rather than fixing?

Remove the Java EE and CORBA modules

removedJEP 320

JAXB, JAX-WS, JAF, Common Annotations and CORBA were removed from the JDK entirely.

The problem it solved

Enterprise APIs shipped inside the JDK duplicated what application servers provided and tied their release cycles to the platform's.

How you did it before

javax.xml.bind and friends were simply on the classpath, so code used them without declaring any dependency.

Asked as

  • Why does upgrading from Java 8 to 11 break builds that never used modules?
  • What do you do when javax.xml.bind is missing on 11?

Scenario question

  • A Java 8 service fails to compile on 11 with "package javax.xml.bind does not exist". Nothing in the code changed.

    What happened and what is the fix?

    What a good answer weighs

    JAXB was removed from the JDK in 11, so a class that was previously free now needs an explicit dependency — jakarta.xml.bind plus an implementation. The instructive part is that the code was always depending on something it never declared; the removal only made the dependency visible.

Launch single-file source-code programs

standardJEP 330

java Hello.java compiles in memory and runs, with no separate javac step and no .class file.

The problem it solved

Trying one idea required a compile step and an artefact on disk, which made Java unusable for the scripting-sized tasks other languages handled in one command.

How you did it before

javac Hello.java && java Hello, leaving a .class file to clean up.

Asked as

  • How do you run a Java file without compiling it first?
  • What are the limits of single-file source launch?

Other versions