Java 15

Release Information

  • Release Date: September 15, 2020
  • Support Type: Non-LTS (6-month support)
  • End of Support: March 2021 (superseded by Java 16)
  • JEPs: 14 enhancements

Language Features

Text Blocks (JEP 378) - Standard

Multi-line string literals became a standard feature after three preview rounds.

Example:

String json = """
    {
        "name": "Java 15",
        "type": "Programming Language",
        "features": ["Text Blocks", "Sealed Classes"]
    }
    """;

New in final release: Text block transformations with String::formatted and String::stripIndent

Sealed Classes (JEP 360) - Preview

Restrict which classes can extend or implement a type.

Example:

public sealed class Shape
    permits Circle, Rectangle, Triangle {
}

final class Circle extends Shape {
    double radius;
}

final class Rectangle extends Shape {
    double width, height;
}

final class Triangle extends Shape {
    double base, height;
}

Use cases:

  • Domain modeling (closed set of possible types)
  • Pattern matching exhaustiveness
  • Library API design

Permitted subclasses must be:

  • final (no further subclasses)
  • sealed (restrict its own subclasses)
  • non-sealed (open for extension)

Pattern Matching for instanceof (JEP 375) - Second Preview

Improvements from first preview:

  • Pattern variable scope refinement
  • Compatibility with && operator

Example:

if (obj instanceof String s && s.length() > 5) {
    System.out.println(s.toUpperCase());
}

Records (JEP 384) - Second Preview

Improvements from first preview:

  • Records can now be local (declared inside methods)
  • Support for annotations on record components

Local record example:

public List<Point> filterPoints(List<Coordinate> coords) {
    record Point(int x, int y) {} // Local record

    return coords.stream()
        .map(c -> new Point(c.x(), c.y()))
        .toList();
}

Garbage Collection Features

ZGC (JEP 377) - Production Ready

Z Garbage Collector no longer experimental (was experimental since Java 11).

Characteristics:

  • Pause times <10ms regardless of heap size
  • Handles heaps from 8MB to 16TB
  • Concurrent (minimal stop-the-world pauses)

How to enable:

java -XX:+UseZGC -Xmx16g MyApp
# No longer requires -XX:+UnlockExperimentalVMOptions

When to use ZGC:

  • Applications requiring low latency (trading platforms, gaming servers)
  • Large heap sizes (multi-GB to TB range)
  • Predictable pause times more important than throughput

Shenandoah GC (JEP 379) - Production Ready

Shenandoah became production-ready (was experimental since Java 12).

Characteristics:

  • Ultra-low pause times (independent of heap size)
  • Concurrent evacuation and compaction
  • Lower memory overhead than ZGC

How to enable:

java -XX:+UseShenandoahGC -Xmx8g MyApp

ZGC vs Shenandoah:

FeatureZGCShenandoah
Max heap16TB128GB (practical limit)
Pause times<10ms<10ms
CPU overheadLowerHigher
Memory overheadHigherLower
Best forMassive heapsMedium heaps, predictable pauses

Security Features

Edwards-Curve Digital Signature Algorithm (JEP 339)

Implements EdDSA cryptographic signatures (RFC 8032).

Example:

import java.security.*;

// Generate Ed25519 key pair
KeyPairGenerator kpg = KeyPairGenerator.getInstance("Ed25519");
KeyPair kp = kpg.generateKeyPair();

// Sign message
Signature sig = Signature.getInstance("Ed25519");
sig.initSign(kp.getPrivate());
sig.update("Hello, World!".getBytes());
byte[] signature = sig.sign();

// Verify signature
sig.initVerify(kp.getPublic());
sig.update("Hello, World!".getBytes());
boolean valid = sig.verify(signature);

Benefits:

  • Faster than RSA and ECDSA
  • Smaller keys and signatures
  • Resistant to timing attacks

Use cases: TLS 1.3, SSH, blockchain, certificate signing

JVM Features

Hidden Classes (JEP 371)

Framework-generated classes invisible to reflection and class loaders.

Purpose: Improve framework efficiency (Spring, Hibernate, bytecode generation libraries)

Characteristics:

  • Cannot be discovered by Class.forName() or reflection
  • Automatically garbage collected when unreachable
  • Cannot be extended or used as superclass

Use case: Dynamic proxy classes, lambda expressions implementation

Example (framework internal use):

import java.lang.invoke.MethodHandles;

MethodHandles.Lookup lookup = MethodHandles.lookup();
Class<?> hiddenClass = lookup.defineHiddenClass(
    classBytes,
    true, // Initialize
    MethodHandles.Lookup.ClassOption.NESTMATE
).lookupClass();

Removals and Deprecations

Remove Nashorn JavaScript Engine (JEP 372)

Nashorn JavaScript engine removed (deprecated in Java 11).

Reason: ECMAScript rapid evolution, maintenance burden

Alternative: GraalVM JavaScript engine

Migration:

# Before (Java 8-14)
jjs script.js

# After (GraalVM)
# Use GraalVM's js or integrate via GraalVM SDK

Disable and Deprecate Biased Locking (JEP 374)

Biased locking disabled by default (will be removed in future release).

What is biased locking: Optimization for uncontended locks

Why disabled: Complex implementation, minimal benefit on modern hardware

Performance impact: Negligible on most workloads

Remove Solaris and SPARC Ports (JEP 381)

Support for Solaris and SPARC platforms removed.

Reason: Minimal usage, high maintenance cost

Affected: Only users running Java on Solaris/SPARC hardware

Deprecate RMI Activation for Removal (JEP 385)

RMI Activation marked for future removal.

Reason: Obsolete technology, rare usage

Alternative: Modern alternatives (REST, gRPC, messaging)

Other Notable Features

Reimpl

ement the Legacy DatagramSocket API (JEP 373)

Improved maintainability and performance of UDP sockets.

User-visible changes: None (internal implementation only)

Benefits: Easier to maintain with Project Loom (virtual threads)

Foreign-Memory Access API (JEP 383) - Second Incubator

Continued incubation with improvements:

  • Better safety checks
  • Improved API usability
  • Performance optimizations

Example:

import jdk.incubator.foreign.*;

try (MemorySegment segment = MemorySegment.allocateNative(100)) {
    MemoryAccess.setByteAtOffset(segment, 0, (byte) 127);
    byte value = MemoryAccess.getByteAtOffset(segment, 0);
}

Migration Considerations

Upgrading from Java 11 LTS:

  1. Nashorn removed: Migrate JavaScript integration to GraalVM
  2. Biased locking disabled: Review if using -XX:+UseBiasedLocking (usually no action needed)
  3. Solaris/SPARC: Migrate to Linux/x86 if on legacy platforms
  4. Preview features: Enable with --enable-preview for Sealed Classes, Pattern Matching, Records
  5. GC options: Consider ZGC or Shenandoah for low-latency requirements

Compatibility: Binary compatible with Java 11 (no breaking changes in standard APIs)

Related Topics

References

Sources:

Official OpenJDK JEPs:

Last updated