3. Incubator Modules
3
• Defined by JEP 11
• Non-final APIs and non-final tools
‒ Deliver to developers to solicit feedback
‒ Can result in changes or even removal
‒ First example: HTTP/2 API (Introduced in JDK 9, final in JDK 11)
4. Preview Features
4
• Defined by JEP 12
• New feature of the Java language, JVM or Java SE APIs
‒ Fully specified, fully implemented but not permanent
‒ Solicit developer real-world use and experience
‒ May lead to becoming a permanent feature in future release
• Must be explicitly enabled
‒ javac --release 14 --enable-preview ...
‒ java --enable-preview ...
• Preview APIs
‒ May be required for a preview language feature
‒ Part of the Java SE API (java or javax namespace)
7. Why Do We Need Modularity in Java?
7
• JDK 1.0
‒ 122 library classes for simplifying application development
• JDK 8.0
‒ Over 4,500 public classes in the rt.jar file
• JDK 9
‒ 27 Java SE modules, 48 JDK modules
• Two sides to modularity:
1. JDK core libraries
2. Application code
8. Module Fundamentals
8
• Module is a grouping of code
‒ For Java this is a collection of packages
• Modules can contain other things
‒ Native code
‒ Resources
‒ Configuration data
com.azul.zoop
com.azul.zoop.alpha.Name
com.azul.zoop.alpha.Position
com.azul.zoop.beta.Animal
com.azul.zoop.beta.Reptile
com.azul.zoop.theta.Zoo
com.azul.zoop.theta.Lake
20. Accessibility
• For a package to be visible
‒ The package must be exported by the containing module
‒ The containing module must be read by the using module
• Public types from those packages can then be used
com.azul.zoop
com.azul.zapp
reads
24. Application Execution
• -p is the abbreviation of --module-path
$ java –p mods –m com.azul.zapp/com.azul.zapp.Main
Azul application initialised!
module name main class
25. Packaging With Modular JAR Files
mods/module-info.class
mods/com/azul/zapp/Main.class
$ jar --create --file=mylib/zapp.jar
--main-class=com.azul.zapp.Main
-C mods .
module-info.class
com/azul/zapp/Main.class
zapp.jar
29. The Implications Of jlink
• "Write once, run anywhere"
Long term Java slogan, mainly held true
• jlink generated runtime may not include all Java SE modules
‒ But is still a conforming Java implementation
‒ To conform to the specification, the runtime:
Must include the java.base module
If other modules are included, all transitive module dependencies must also be
included
Defined as a closed implementation
32. Typical Application (JDK 9)
jar
jar
jar
module
java.base
module
java.desktop
module
java.datatransfer
module
java.xml
jar
jar
jar
jar jar
jar
jar
jar
jar
Unnamed
module
38. Automatic Modules
38
• Real modules
• Simply place unmodified jar file on module path
‒ Rather than classpath
• No changes to JAR file
• Module name derived from JAR file name
• Exports all its packages
‒ No selectivity
• Automatically requires all modules on the module path
42. Migration Guidance From Oracle
"Clean applications that just depend on java.se
should just work"
43. Migrating Applications to JPMS
43
• Initially, leave everything on the classpath
• Anything on the classpath is in the unnamed module
‒ All packages are exported
‒ The unnamed module depends on all modules
• Migrate to modules as required
‒ Try automatic modules
‒ Move existing jar files from classpath to modulepath
45. Reversing Encapsulation
• "The Big Kill Switch"
--illegal-access
• Four options:
‒ permit (current default)
‒ warn
‒ debug
‒ deny (JDK 16 default)
46. Reversing Encapsulation
• Big kill switch overrides encapsulation
‒ From the unnamed module (i.e. classpath)
‒ Allows unlimited refective access to named modules
Not from named modules
• Warning messages written to error stream
• Useful to understand use of --add-exports and --add-opens when
migrating to named modules
47. Reversing Encapsulation
47
• Allowing direct access to encapsulated APIs
‒ --add-exports
• Allowing reflective access to encapsulated APIs
‒ --add-opens
--add-exports java.management/com.sun.jmx.remote.internal=mytest
--add-exports java.management/sun.management=ALL-UNNAMED
--add-opens java.base/java.util=ALL-UNNAMED
50. Java Storage Basics
50
• Fields (instance and static)
‒ Part of an object, exist for the lifetime of an object
‒ Initialisation guaranteed by compiler
• Local variables
‒ Scoped to region of code (method, statement, block)
‒ Initialisation not guaranteed
‒ Cheap when allocated on the stack
‒ Name and use is often more important than the type
51. Local Variable Type Inference
• Why?
‒ JavaScript has it so it must be good
‒ Streams hide intermediate types
‒ Why not expand this elsewhere?
‒ var can make code more concise
Without sacrificing readability
List l = names.stream() // Stream<String>
.filter(s -> s.length() > 0) // Stream<String>
.map(s -> getRecord(s)) // Stream<Record>
.collect(toList()); // ArrayList<Record>
52. Simple Uses of Local Variables
ArrayList<String> nameList = new ArrayList<String>();
List<String> userList = new ArrayList<>();
Stream<String> stream = userList.stream();
for (String name : userList) {
...
}
for (int i = 0; i < 10; i++) {
...
}
53. Simple Uses of Local Variable Type Inference
var userList = new ArrayList<String>(); // Infers ArrayList<String>
var stream = userList.stream(); // Infers Stream<String>
for (var name : userList) { // Infers String
...
}
for (var i = 0; i < 10; i++) { // Infers int
...
}
54. Simple Uses of var
• Clearer try-with-resources
try (InputStream inputStream = socket.getInputStream();
InputStreamReader inputStreamReader =
new InputStreamReader(inputStream, UTF_8);
BufferedReader bufferedReader =
new BufferedReader(inputStreamReader)) {
// Use bufferedReader
}
55. Simple Uses of var
• Clearer try-with-resources
try (var inputStream = socket.getInputStream();
var inputStreamReader = new inputStreamReader(inputStream, UTF_8);
var bufferedReader = new BufferedReader(inputStreamReader)) {
// Use bufferedReader
}
56. More Typing With Less Typing
• Java is still statically typed
var name = "Simon"; // Infers String, so name is String
name = "Dylan"; // Still String
name = 42; // Not a String
error: incompatible types: int cannot be converted to String
57. Final and Non-Final
57
• var simply indicates the compiler infers the type
• Use of var does not make a variable final
• Still need final
• No shortcut for final var (like val)
‒ How often do you make local-variables final?
var name = "Simon";
name = "Dylan"; // name is not final
final var name = "Simon";
58. Action At A Distance
var l = new ArrayList<String>();
var s = l.stream();
// Lots of lines of complex code
var n = l.get(0); // Err, what is n?
59. Not Everything Can Be Inferred
int[] firstSixPrimes = {2, 3, 5, 7, 11, 13};
var firstSixPrimes = {2, 3, 5, 7, 11, 13};
error: cannot infer type for local variable firstSixPrimes
var firstSixPrimes = {2, 3, 5, 7, 11, 13};
^
(array initializer needs an explicit target-type)
var firstSixPrimes = new int[]{2, 3, 5, 7, 11, 13};
var firstTwoPrimes = new Integer[]{2, 3};
60. Types Required On Both Sides
var list = null;
error: cannot infer type for local variable list
var list = null;
^
(variable initializer is 'null')
61. Types Required On Both Sides
var list;
list = new ArrayList<String>();
error: cannot infer type for local variable list
var list;
^
(cannot use 'var' on variable without initializer)
62. No Multiple Variable Declaration
62
var a, b = 1;
error: 'var' is not allowed in a compound declaration
63. Literals with var (Good)
• Original
‒ boolean ready = true;
‒ char ch = 'x';
‒ long sum = 0L;
‒ String label = "Foo";
64. Literals with var (Good)
• With var
‒ var ready = true;
‒ var ch = 'x';
‒ var sum = 0L;
‒ var label = "Foo";
65. Literals with var (Dangerous)
• Original
‒ byte flags = 0;
‒ short mask = 0x7fff;
‒ long base = 10;
66. Literals with var (Dangerous)
• Original
‒ var flags = 0;
‒ var mask = 0x7fff;
‒ var base = 10;
All these cases will infer int
67. Beware of Multiple Type Inference
var itemQueue = new PriorityQueue<>();
Diamond operator,
primary type
inference
Secondary type
inference
itemQueue infered as PriorityQueue<Object>();
PriorityQueue<Integer> itemQueue = new PriorityQueue<>();
68. Programming To An Interface
• Common to use interface rather than concrete type
• Using var always infers concrete type
• Polymorphism still works
‒ArrayList<String> is still a List
‒You can use myList wherever a List is required
List<String> myList = new ArrayList<>();
var myList = new ArrayList<String>();
69. Lambdas and var
Predicate<String> blankLine = s -> s.isBlank();
var blankLine = s -> s.isBlank();
error: cannot infer type for local variable blankLine
var blankLine = s -> s.isBlank();
^
(lambda expression needs an explicit target-type)
70. Intersection Types
<T extends Closeable & Iterable<E>> T getData() {
// Return something that implements both
// Closeable and Iterable<E>
}
Valid Java syntax
71. Intersection Types
• The problem
<E> Optional<E> firstMatch(Predicate<? super E> condition) {
XXX elements = getData();
try (elements) {
return StreamSupport.stream(elements.spliterator(), false)
.filter(condition)
.findAny();
}
}
elements must implement Closeable
elements must implement Iterable<E>
XXX is Closeable & Iterable<E>, which won't compile
72. Intersection Types
• The solution: var
<E> Optional<E> firstMatch(Predicate<? super E> condition) {
var elements = getData();
try (elements) {`
return StreamSupport.stream(elements.spliterator(), false)
.filter(condition)
.findAny();
}
}
Compiler infers a valid type that is impossible to express with Java syntax
73. Inner Classes
73
• This code won't compile
Object fruit = new Object() {
String name = "apple";
String inFrench() {
return "pomme";
}
};
System.out.println("Fruit = " + fruit.name);
System.out.println("In French = " + fruit.inFrench());
74. Inner Classes
74
• Using var this will compile and run
‒ The key is non-denotable types
var fruit = new Object() {
String name = "apple";
String inFrench() {
return "pomme";
}
};
System.out.println("Fruit = " + fruit.name);
System.out.println("In French = " + fruit.inFrench());
75. var: Reserved Type (Not Keyword)
var var = new Var();
public class var {
public var(String x) {
...
}
}
public class Var {
public Var(String x) {
...
}
}
77. Puzzler 1
• Should we use var? Yes? No?
static boolean calc1(int mask) {
var temp = 0x12345678;
return (((temp << 6) | temp) & mask) > 0;
}
78. Puzzler 1
• 0x12345678 fits in an int
‒ Using var will infer an int, not a long
• Passing a mask < 0 will give different results
‒ Using long, mask < 0 returns true
‒ Using var (infer int), mask < 0 returns false
79. Puzzler 2
static List<String> create1(boolean foo, boolean bar) {
List<String> list = new ArrayList<>();
if (foo)
list.add("foo");
if (bar)
list.add("bar");
return list;
}
80. Puzzler 2
• Should we use var? Yes? No?
static List<String> create1(boolean foo, boolean bar) {
var list = new ArrayList<>();
if (foo)
list.add("foo");
if (bar)
list.add("bar");
return list;
}
81. Puzzler 2
• Remember, "Beware of multiple type inference"
‒ var list = new ArrayList<>();
‒ Diamond operator infers Object
error: incompatible types: ArrayList<Object> cannot be
converted to List<String>
return list;
82. Puzzler 3
• Good use of var? Yes? No?
static List<Integer> listRemoval() {
List<Integer> list =
new ArrayList<>(Arrays.asList(1, 3, 5, 7, 9));
var v = valueToRemove();
list.remove(v);
return list;
}
// Separate class, package or module (in a galaxy far, far away)
static Integer valueToRemove() {
return 3;
}
83. Puzzler 3
• New intern arrives and changes code...
• Unexpected change in behaviour
static int valueToRemove() {
return 3;
}
List.remove(int) // Remove element at given index
List.remove(Object) // Remove first instance of object
{1,3,7,9} // Using var with changed valueToRemove
{1,5,7,9} // Using var with unchanged valueToRemove
84. Guidelines For Use of var
84
1. Reading code is more important that writing it
2. Code should be clear from local reasoning
3. Code readability shouldn't depend on an IDE
4. Choose variable names that provide useful information
5. Minimise the scope of local variables
6. Consider var when the initialiser provides sufficient information
7. Use var to break up chained or nested expressions
8. Take care when using var with generics
9. Take care when using var with literals
90. Missing Modules
90
• Remember, "Clean applications that only use java.se..."
• The java.se.ee aggregator module removed in JDK 11
• Affected modules
‒ java.corba
‒ java.transaction
‒ java.activation
‒ java.xml.bind
‒ java.xml.ws
‒ java.xml.ws.annotation
91. Resolving Missing Modules
91
• All modules (except CORBA) have standalone versions
‒ Maven central
‒ Relevant JSR RI
• Deploy standalone version on the upgrade module path
‒ --upgrade-module-path <path>
• Deploy standalone version on the classpath
93. Switch Expressions (Preview)
93
• Switch construct was a statement
‒ No concept of generating a result that could be assigned
• Rather clunky syntax
‒ Every case statement needs to be separated
‒ Must remember break (default is to fall through)
‒ Scope of local variables is not intuitive
94. Old-Style Switch Statement
94
int numberOfLetters;
switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
numberOfLetters = 6;
break;
case TUESDAY:
numberOfLetters = 7;
break;
case THURSDAY:
case SATURDAY:
numberOfLetters = 8;
break;
case WEDNESDAY:
numberOfLetters = 9;
break;
default:
throw new IllegalStateException("Huh?: " + day); };
95. New-Style Switch Expression
int numberOfLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
default -> throw new IllegalStateException("Huh?: " + day);
};
96. New Old-Style Switch Expression
int numberOfLetters = switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
break 6;
case TUESDAY
break 7;
case THURSDAY
case SATURDAY
break 8;
case WEDNESDAY
break 9;
default:
throw new IllegalStateException("Huh?: " + day);
};
97. New Old-Style Switch Expression
outside:
for (day : dayList)
int numberOfLetters = switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
break 6;
case TUESDAY
break 7;
case THURSDAY
case SATURDAY
break 8;
case WEDNESDAY
break 9;
default:
continue outside;
};
Illegal jump through switch
expression
98. Streams
• New collector, teeing
‒ teeing(Collector, Collector, BiFunction)
• Collect a stream using two collectors
• Use a BiFunction to merge the two collections
98
Collector 1
Collector 2
BiFunction
Stream Result
101. Text Blocks (Preview)
String webPage = """
<html>
<body>
<p>My web page</p>
</body>
</html>""";
System.out.println(webPage);
$ java WebPage
<html>
<body>
<p>My web page</p>
</body>
</html>
$
incidental white space
102. Text Blocks (Preview)
String webPage = """
<html>
<body>
<p>My web page</p>
</body>
</html>
""";
System.out.println(webPage);
$ java WebPage
<html>
<body>
<p>My web page</p>
</body>
</html>
$
Additional blank line
incidental white space
Intentional indentation
103. Switch Expression
int numberOfLetters = switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
break 6;
case TUESDAY
break 7;
case THURSDAY
case SATURDAY
break 8;
case WEDNESDAY
break 9;
default:
throw new IllegalStateException("Huh?: " + day);
};
104. Switch Expression
int numberOfLetters = switch (day) {
case MONDAY:
case FRIDAY:
case SUNDAY:
yield 6;
case TUESDAY
yield 7;
case THURSDAY
case SATURDAY
yield 8;
case WEDNESDAY
yield 9;
default:
throw new IllegalStateException("Huh?: " + day);
};
106. Simple Java Data Class
106
class Point {
private final double x;
private final double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
public double x() {
return x;
}
public double y() {
return y;
}
}
107. Records (Preview)
107
record Point(double x, double y) { }
record Range(int low, int high) {
public Range { // Compact constructor
if (low > high)
throw new IllegalArgumentException("Bad values");
}
}
108. Record Additional Details
108
• Compact constructor can only throw unchecked exception
‒ Syntax does not allow for specifying a checked exception
• Object methods equals(), hashCode() and toString() can be
overridden
• The base class of all records is java.lang.Record
‒ This is an example of a preview feature Java SE API
‒ Records cannot sub-class (but may implement interfaces)
• Records do not follow the Java bean pattern
‒ x() not getX() in previous example
• Instance fields cannot be added to a record
‒ Static fields can
• Records can be generic
110. Pattern Matching instanceof (Preview)
110
if (obj instanceof String s)
System.out.println(s.length());
else
// Use of s not allowed here
if (obj instanceof String s && s.length() > 0)
System.out.println(s.length());
// Compiler error
if (obj instanceof String s || s.length() > 0)
System.out.println(s.length());
111. Pattern Matching instanceof (Preview)
111
if (!(o instanceof String s && s.length() > 3)
return;
System.out.println(s.length());
112. Pattern Matching instanceof
112
• Be careful of scope!
class BadPattern {
String s = "One";
void testMyObject(Object o) {
if (o instanceof String s) {
System.out.println(s); // Prints contents of o
s = s + " Two"; // Modifies pattern variable
}
System.out.println(s); // Prints "One"
}
}
113. Text Blocks
• Second preview
• Two new escape sequences
String continuous = """This line will not
contain a newline in the middle
and solves the extra blank line issue
""";
String endSpace = """This line will not s
lose the trailing spaces s""";
114. Helpful NullPointerException
114
• Who's never had an NullPointerException?
• Enabled with -XX:+ShowCodeDetailsInExceptionMessages
a.b.c.i = 99;
Exception in thread "main" java.lang.NullPointerException
at Prog.main(Prog.java:5)
Exception in thread "main" java.lang.NullPointerException:
Cannot read field "c" because "a.b" is null
at Prog.main(Prog.java:5)
116. Java Inheritance
116
• A class (or interface) in Java can be sub-classed by any class
‒ Unless it is marked as final
Shape
Triangle Square Pentagon
117. Sealed Classes (JEP 360)
117
• Preview feature
• Sealed classes allow control over which classes can sub-class a class
‒ Think of final as the ultimate sealed class
• Although called sealed classes, this also applies to interfaces
118. Sealed Classes (JEP 360)
118
• Uses contextual keywords
‒ New idea replacing restricted identifiers and keywords
‒ sealed, permits and non-sealed
• Classes must all be in the same package or module
public sealed class Shape permits Triangle, Square, Pentagon { ... }
Shape
Triangle Square Pentagon Circle
X
119. Sealed Classes (JEP 360)
119
• All sub-classes must have inheritance capabilities explicitly specified
// Restrict sub-classes to defined set
public sealed class Triangle permits Equilateral, Isosoles extends Shape { ... }
// Prevent any further sub-classing
public final class Square extends Shape { ... }
// Allow any classes to sub-class this one (open)
public non-sealed class Pentagon extends Shape { ... }
121. Hidden Classes (JEP 371)
121
• JVM rather than language-level feature
• Classes that cannot be used directly by the bytecodes of other classes
• Several situations where bytecodes generated at runtime
‒ Use of invokedynamic bytecode
‒ Lambdas are a good example
‒ Mostly bound to static class (not for use elsewhere)
‒ Often only used for short time
• Hidden classes can only be accessed via reflection
‒ Primarily intended for framework developers
122. Records (Second Preview)
122
• Record fields are now (really) final
‒ Cannot be changed via reflection (will throw IllegalAccessException)
• Native methods now explicitly prohibited
‒ Could introduce behaviour dependent on external state
123. Records (Second Preview)
123
• Local records
‒ Like a local class
‒ Implicitly static
List<Seller> findTopSellers(List<Seller> sellers, int month) {
// Local record
record Sales(Seller seller, double sales) {}
return sellers.stream()
.map(seller -> new Sales(seller, salesInMonth(seller, month)))
.sorted((s1, s2) -> Double.compare(s2.sales(), s1.sales()))
.map(Sales::seller)
.collect(toList());
}
124. Records (Second Preview)
124
• Records work with sealed classes (interfaces)
public sealed interface Car permits RedCar, BlueCar { ... }
public record RedCar(int w) implements Car { ... }
public record BlueCar(long w, int c) implements Car { ... }
126. Pattern Matching instanceof (JEP 394)
126
• Now final, i.e. part of the Java SE specification
• Two minor changes to previous iterations
‒ Pattern variables are no longer implicitly final
‒ Compile-time error to compare an expression of type S against a pattern of type T where S
is a sub-type of T
if (x instanceof Object o) …
It will always succeed and so is pointless
127. Records (JEP 395)
127
• Records now final, i.e., part of the Java SE specification
• Record fields are (really) final
‒ Cannot be changed via reflection (will throw IllegalAccessException)
• Native methods explicitly prohibited
‒ Could introduce behaviour dependent on external state
• Inner classes can now declare explicit/implicit static members
‒ Allows an inner class to declare a member that is a Record class
128. Add UNIX-Domain Socket Channels
128
• Add UNIX_AF socket channels
‒ Used for IPC on UNIX-based OSs and Windows
• Better security and performance than TCP/IP loopback connections
‒ Behaviour is identical
• No constructor, use factory methods
var unix = UnixDomainSocketAddress.of("/tmp/foo");
129. Streams mapMulti
129
• Similar to flatMap
‒ Each element on the input stream is mapped to zero or more elements on the output
stream
‒ Difference is that a mapping can be applied at the same time
‒ Uses a BiConsumer
• 1 to (0..1) example
Stream.of("Java", "Python", "JavaScript", "C#", "Ruby")
.mapMulti((str, consumer) -> {
if (str.length() > 4)
consumer.accept(str.length()); // lengths larger than 4
})
.forEach(i -> System.out.print(i + " "));
// 6 10
132. Vector API (JEP 338)
132
• Incubator module (not part of the Java SE specification)
• API to express vector computations
‒ Compile at runtime to optimal hardware instructions
‒ Deliver superior performance to equivalent scalar operations
• Ideally, this would not be necessary
‒ Compiler should identify where vector operations can be used
133. Vector API (JEP 338)
133
void scalarComputation(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i++)
c[i] = (a[i] * a[i] + b[i] * b[i]) * -1.0f;
}
static final VectorSpecies<Float> SPECIES = FloatVector.SPECIES_256;
void vectorComputation(float[] a, float[] b, float[] c) {
for (int i = 0; i < a.length; i += SPECIES.length()) {
var m = SPECIES.indexInRange(i, a.length);
var va = FloatVector.fromArray(SPECIES, a, i, m);
var vb = FloatVector.fromArray(SPECIES, b, i, m);
var vc = va.mul(va).
add(vb.mul(vb)).
neg();
vc.intoArray(c, i, m);
}
}
134. Foreign-Memory Access API (JEP 393)
134
• Introduced in JDK 14, now third incubator iteration
• API for safe and efficient access to memory outside of the Java heap
• MemorySegment
‒ Models a contiguous area of memory
• MemoryAddress
‒ Models an individual memory address (on or off heap)
• MemoryLayout
‒ Programmatic description of a MemorySegment
try (MemorySegment segment = MemorySegment.allocateNative(100)) {
for (int i = 0; i < 25; i++)
MemoryAccess.setIntAtOffset(segment, i * 4, i);
}
135. Foreign-Memory Access API (JEP 393)
135
• Example using MemoryLayout and VarHandle
‒ Simpler access of structured data
SequenceLayout intArrayLayout
= MemoryLayout.ofSequence(25,
MemoryLayout.ofValueBits(32,
ByteOrder.nativeOrder()));
VarHandle indexedElementHandle
= intArrayLayout.varHandle(int.class,
PathElement.sequenceElement());
try (MemorySegment segment = MemorySegment.allocateNative(intArrayLayout)) {
for (int i = 0; i < intArrayLayout.elementCount().getAsLong(); i++)
indexedElementHandle.set(segment, (long) i, i);
}
136. Foreign Linker API (JEP 389): Incubator
136
• Provides statically-typed, pure-Java access to native code
‒ Works in conjunction with the Foreign Memory Access API
‒ Initially targeted at C native code. C++ should follow
• More powerful when combined with Project Panama jextract command
public static void main(String[] args) throws Throwable {
var linker = CLinker.getInstance();
var lookup = LibraryLookup.ofDefault();
// get a native method handle for 'getpid' function
var getpid = linker.downcallHandle(lookup.lookup("getpid").get(),
MethodType.methodType(int.class),
FunctionDescriptor.of(CLinker.C_INT));
System.out.println((int)getpid.invokeExact());
}
137. Warnings for Value-Based Classes
137
• Part of Project Valhalla, which adds value-types to Java
‒ Introduces the concept of primitive classes
• Primitive wrapper classes (Integer, Float, etc.) designated value-based
‒ Constructors were deprecated in JDK 9
‒ Now marked as for removal
‒ Attempting to synchronize on an instance of a value-based class will issue a warning
139. Zulu Enterprise
139
• Enhanced build of OpenJDK source code
Fully TCK tested
JDK 6, 7, 8, 11 and 13
TLS1.3, Flight Recorder backports for Zulu 8
• Wide platform support:
Intel 64-bit Windows, Mac, Linux
Intel 32-bit Windows and Linux
• Real drop-in replacement for Oracle JDK
Many enterprise customers
No reports of any compatibility issues
140. Zulu Extended Support
140
• Backporting of bug fixes and security patches from supported OpenJDK
release
• Zulu 8 supported until December 2030
• LTS releases have 9 years active + 2 years passive support
• JDK 15 is a Medium Term Support release
‒ Bridge to next LTS release (JDK 17)
‒ Supported until 18 months after JDK 17 release
141. Conclusions
141
• The six-month release cycle is working well
• Not all releases will have lots of new features
• Use Zulu builds of OpenJDK if you want to deploy to production
• Java continues to evolve!