A comprehensive guide to all Java 17 (LTS) concepts with practical examples for interview preparation.
- Sealed Classes (Finalized)
- Pattern Matching for switch (Preview)
- Enhanced Pseudo-Random Number Generators
- Foreign Function & Memory API (Incubator)
- Vector API (Second Incubator)
- Context-Specific Deserialization Filters
- New macOS Rendering Pipeline
- macOS/AArch64 Port
- Remove RMI Activation
- Deprecate Applet API
- Deprecation for Removal of Finalization
- Strongly Encapsulate JDK Internals
- Performance Improvements
- Common Interview Questions
Sealed classes are now a standard feature.
// Sealed class - restricts inheritance
public sealed class Shape
permits Circle, Rectangle, Triangle {
public abstract double area();
}
// Permitted subclasses
public final class Circle extends Shape {
private final double radius;
public Circle(double radius) {
this.radius = radius;
}
@Override
public double area() {
return Math.PI * radius * radius;
}
}
public final class Rectangle extends Shape {
private final double width, height;
public Rectangle(double width, double height) {
this.width = width;
this.height = height;
}
@Override
public double area() {
return width * height;
}
}
public final class Triangle extends Shape {
private final double base, height;
public Triangle(double base, double height) {
this.base = base;
this.height = height;
}
@Override
public double area() {
return 0.5 * base * height;
}
}
// Cannot extend Shape with unpermitted classes
// public class Polygon extends Shape {} // Compile errorpublic sealed interface Expression
permits Constant, Variable, Add, Multiply {
double evaluate();
}
public record Constant(double value) implements Expression {
@Override
public double evaluate() {
return value;
}
}
public record Variable(String name) implements Expression {
@Override
public double evaluate() {
return lookup(name);
}
}
public record Add(Expression left, Expression right) implements Expression {
@Override
public double evaluate() {
return left.evaluate() + right.evaluate();
}
}
public record Multiply(Expression left, Expression right) implements Expression {
@Override
public double evaluate() {
return left.evaluate() * right.evaluate();
}
}Note: Sealed classes are now a standard feature (no preview flag needed). See SealedClassesDemo.java for complete example.
Pattern matching with switch expressions.
Object obj = "Hello";
// Pattern matching with switch (preview)
String result = switch (obj) {
case String s -> "String: " + s;
case Integer i -> "Integer: " + i;
case null -> "Null";
default -> "Unknown";
};Shape shape = new Circle(5.0);
double area = switch (shape) {
case Circle c -> Math.PI * c.radius() * c.radius();
case Rectangle r -> r.width() * r.height();
case Triangle t -> 0.5 * t.base() * t.height();
// No default needed - exhaustive (all cases covered)
};Object obj = "Hello World";
String result = switch (obj) {
case String s when s.length() > 10 -> "Long string: " + s;
case String s -> "Short string: " + s;
case Integer i when i > 100 -> "Large number: " + i;
case Integer i -> "Small number: " + i;
default -> "Unknown";
};New interfaces and implementations for random number generation.
Java 17 introduces enhanced pseudo-random number generators with a new API that provides better performance, reliability, and flexibility.
import java.util.random.RandomGenerator;
import java.util.random.RandomGeneratorFactory;
// Get default random generator
RandomGenerator rng = RandomGeneratorFactory.getDefault().create();
int randomNumber = rng.nextInt(100);
System.out.println("Random number: " + randomNumber);
// Get specific algorithm
RandomGenerator lcg = RandomGeneratorFactory.of("L32X64MixRandom").create();
long randomLong = lcg.nextLong();
// Get all available algorithms
RandomGeneratorFactory.all()
.map(f -> f.name() + " - " + f.group())
.sorted()
.forEach(System.out::println);- L32X64MixRandom: Fast, good quality
- L64X128MixRandom: Very fast, excellent quality
- Xoshiro256PlusPlus: Fast, good quality
- Xoroshiro128PlusPlus: Fast, good quality
- SplittableRandom: Splittable for parallel streams
- Multiple algorithms: Choose based on performance needs
- Better performance: Optimized implementations
- Stream support: Works with parallel streams
- Splittable: For parallel processing
- Monte Carlo simulations
- Game development
- Cryptography (with secure random)
- Statistical sampling
- Testing and simulation
- Better performance than legacy Random
- Multiple algorithm choices
- Better quality random numbers
- Splittable for parallel processing
Note: See RandomGeneratorDemo.java for complete examples.
API for calling native code and accessing off-heap memory.
import jdk.incubator.foreign.*;
import java.lang.invoke.MethodHandle;
// Link with native libraries
Linker linker = Linker.nativeLinker();
SymbolLookup stdlib = linker.defaultLookup();
MethodHandle strlen = linker.downcallHandle(
stdlib.find("strlen").orElseThrow(),
FunctionDescriptor.of(ValueLayout.JAVA_LONG, ValueLayout.ADDRESS)
);
try (MemorySegment str = Arena.ofAuto().allocateUtf8String("Hello")) {
long len = (long) strlen.invoke(str);
System.out.println("Length: " + len);
}import jdk.incubator.foreign.*;
// Allocate off-heap memory
try (Arena arena = Arena.ofConfined()) {
MemorySegment segment = arena.allocate(100);
// Write to memory
segment.set(ValueLayout.JAVA_INT, 0, 42);
// Read from memory
int value = segment.get(ValueLayout.JAVA_INT, 0);
System.out.println("Value: " + value);
}Note: Requires --add-modules jdk.incubator.foreign and --enable-preview flags. See ForeignFunctionMemoryDemo.java for complete examples.
Refinements to Vector API.
import jdk.incubator.vector.*;
// SIMD operations
var species = IntVector.SPECIES_256;
int[] a = new int[256];
int[] b = new int[256];
int[] c = new int[256];
// Vectorized addition
for (int i = 0; i < a.length; i += species.length()) {
var av = IntVector.fromArray(species, a, i);
var bv = IntVector.fromArray(species, b, i);
var cv = av.add(bv);
cv.intoArray(c, i);
}Enhanced security for object deserialization.
Context-specific deserialization filters allow you to control which classes can be deserialized, providing protection against deserialization attacks.
import java.io.ObjectInputFilter;
// Create a filter
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
"java.base.*;!*");
ObjectInputStream ois = new ObjectInputStream(inputStream);
ois.setObjectInputFilter(filter);// Allow all
"*"
// Reject all
"!*"
// Allow specific package
"java.base.*"
// Allow package, reject others
"java.base.*;!*"
// Multiple packages
"java.base.*;java.util.*;!*"
// Array size limit
"maxarray=1000"
// Depth limit
"maxdepth=10"
// Combined
"java.base.*;maxarray=1000;maxdepth=10;!*"// Set global filter for all ObjectInputStream instances
ObjectInputFilter.Config.setSerialFilter(
ObjectInputFilter.Config.createFilter("java.base.*;!*"));ObjectInputFilter customFilter = info -> {
String className = info.serialClass() != null
? info.serialClass().getName()
: null;
if (className != null && className.startsWith("java.")) {
return ObjectInputFilter.Status.ALLOWED;
}
return ObjectInputFilter.Status.REJECTED;
};- Security: Prevents deserialization attacks
- Control: Fine-grained control over deserialization
- Flexibility: Multiple filter patterns
- Performance: Limits array size and depth
- Secure deserialization
- Preventing deserialization attacks
- Controlling object graph complexity
- Limiting resource usage
Note: See DeserializationFiltersDemo.java for complete examples.
Java 17 introduces a new rendering pipeline based on Apple's Metal API.
The new macOS rendering pipeline replaces the older OpenGL-based pipeline with Apple's Metal API, providing better performance and compatibility.
- Metal-based: Uses Apple's Metal API instead of OpenGL
- Better performance: Improved rendering performance on macOS
- Modern API: Aligned with Apple's direction
- Future-proof: Better compatibility with modern macOS versions
- Improved performance on macOS
- Enhanced compatibility with modern macOS versions
- Future-proof rendering pipeline
- Better integration with macOS graphics stack
- Automatic for Java applications on macOS
- No code changes required
- Better performance out of the box
Note: This is an internal JVM improvement and doesn't require code changes.
Java 17 supports macOS running on Apple Silicon (M1) chips.
The macOS/AArch64 port provides native support for Apple Silicon (M1, M2, etc.) processors, enabling Java applications to run natively on Apple Silicon Macs.
- Native support: Runs natively on Apple Silicon
- Better performance: Leverages full power of M1/M2 architecture
- Optimized: Optimized for ARM64 architecture
- Full compatibility: All Java features work on Apple Silicon
- Native support for Apple Silicon
- Better performance than Rosetta emulation
- Full utilization of M1/M2 architecture
- Streamlined development experience
# Java 17 automatically detects and uses native ARM64 build
java -version
# Should show: ... aarch64 ... (on Apple Silicon)
# No special flags needed
java MyApplicationNote: This is a platform port and doesn't require code changes.
RMI Activation removed (deprecated since Java 14).
Applet API deprecated for removal (obsolete).
Finalization mechanism is deprecated for future removal.
Java 17 deprecates the finalize() method and finalization mechanism, signaling its future removal. This encourages developers to use better resource management alternatives.
Finalization was a mechanism to clean up resources before an object is garbage-collected:
// Deprecated in Java 17
public class Resource {
@Deprecated(since = "17", forRemoval = true)
protected void finalize() throws Throwable {
// Cleanup code
super.finalize();
}
}- Unpredictable timing: Finalization runs at unpredictable times
- Performance overhead: Adds overhead to garbage collection
- Resource leaks: Can cause resource leaks if not handled properly
- Better alternatives: Modern alternatives are available
// Use try-with-resources for automatic cleanup
try (FileInputStream fis = new FileInputStream("file.txt")) {
// Use resource
} // Automatically closedimport java.lang.ref.Cleaner;
public class Resource {
private static final Cleaner cleaner = Cleaner.create();
private final Cleaner.Cleanable cleanable;
public Resource() {
this.cleanable = cleaner.register(this, () -> {
// Cleanup code
});
}
}import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
// Use PhantomReference for cleanup- Identify finalize() usage: Find all classes using
finalize() - Replace with try-with-resources: For closeable resources
- Use Cleaner API: For non-closeable resources
- Test thoroughly: Ensure cleanup works correctly
- Better resource management
- Predictable cleanup timing
- Improved garbage collection performance
- Modern, recommended practices
Note: Finalization will be removed in a future Java version. Migrate now to avoid issues.
Strong encapsulation of internal APIs.
- Access to internal APIs restricted
- Use
--add-opensif needed - Better security and maintainability
Java 17 includes numerous performance optimizations.
Java 17 brings significant performance improvements across various areas, including garbage collection, JVM startup time, and application throughput.
- G1 GC: Further refinements and optimizations
- ZGC: Improved concurrent processing
- Shenandoah: Better pause time management
- Parallel GC: Enhanced for better throughput
- Faster class loading
- Improved initialization
- Better module system performance
- Reduced startup overhead
- Better compiler optimizations
- Improved inlining
- Enhanced escape analysis
- Better code generation
# Use G1 GC (default in many cases)
java -XX:+UseG1GC MyApp
# Use ZGC for low latency
java -XX:+UseZGC MyApp
# Use Shenandoah for consistent pause times
java -XX:+UseShenandoahGC MyApp- Faster application startup
- Lower latency for high-performance applications
- Higher throughput
- Better resource utilization
- Microservices (faster startup)
- High-performance applications
- Low-latency systems
- Large-scale applications
Note: These are internal JVM improvements and don't require code changes.
A: LTS (Long-Term Support) means:
- Extended support period (Oracle: until September 2029)
- Important for enterprise applications
- Stability and security updates
- Critical for production systems
A: Sealed classes allow exhaustive pattern matching:
- Compiler knows all possible subtypes
- Switch expressions can cover all cases
- No default case needed (when all types handled)
- Compile-time safety
A: Pattern matching extends switch to:
- Work with types (instanceof pattern)
- Work with sealed classes (exhaustive matching)
- Use guards (when clauses)
- Bind variables automatically
Last Updated: 2024
Version: 1.0