In this blog post, I take a look at the smaller API changes in Java 27: additions to existing classes that can make everyday code a little simpler. As in the previous posts, I leave out preview and incubator features.
Among the bigger changes, Java 27 makes G1 the default garbage collector in all environments and enables compact object headers by default. It also adds post-quantum hybrid key exchange for TLS 1.3 and in-process data redaction for Java Flight Recorder.
Java 27 (September 2026) ¶
String.encodedLength ¶
How many bytes does a string need when encoded as UTF-8? Until now, the straightforward answer was text.getBytes(StandardCharsets.UTF_8).length. Java 27 adds String.encodedLength(Charset), so you can ask for the size directly.
import java.nio.charset.StandardCharsets;
String text = "café";
System.out.println(text.length()); // 4 UTF-16 code units
System.out.println(text.encodedLength(StandardCharsets.UTF_8)); // 5 bytes
System.out.println(text.encodedLength(StandardCharsets.UTF_16BE)); // 8 bytes
This is useful when checking a byte limit for a message or sizing a buffer. The result is the same as getBytes(charset).length, and the API documents equivalent or better performance. There is no need to request a byte array just to find out its length.
The method also follows the replacement behavior of getBytes: malformed input and characters that the charset cannot represent count as replacement bytes. It does not validate that the string can be encoded without losing information.
BigDecimal nth roots ¶
The previous post covered nth roots for BigInteger. Java 27 adds the decimal counterpart, BigDecimal.rootn(int, MathContext). It computes an nth root with the precision and rounding mode supplied by the MathContext.
import java.math.BigDecimal;
import java.math.MathContext;
MathContext mc = MathContext.DECIMAL64;
System.out.println(new BigDecimal("125").rootn(3, mc)); // 5
System.out.println(new BigDecimal("2").rootn(3, mc)); // 1.259921049894873
System.out.println(new BigDecimal("-125").rootn(3, mc)); // -5
System.out.println(new BigDecimal("8").rootn(-3, mc)); // 0.5
A negative root degree calculates the reciprocal of the corresponding positive root. An odd root of a negative value is supported too. Calling rootn(2, mc) is equivalent to the existing sqrt(mc).
This saves you from converting to double for a fractional power and losing decimal precision along the way. There are still invalid inputs: an even root of a negative number, a negative root of zero, and degrees of zero or Integer.MIN_VALUE throw ArithmeticException. Requesting an exact result with unlimited precision also throws if the root has no finite decimal representation.
Inverse hyperbolic functions ¶
Math and StrictMath have supported sinh, cosh, and tanh for a long time. Java 27 adds their inverses:
Math.asinh(double)andStrictMath.asinh(double): inverse hyperbolic sine.Math.acosh(double)andStrictMath.acosh(double): inverse hyperbolic cosine.Math.atanh(double)andStrictMath.atanh(double): inverse hyperbolic tangent.
These are mostly useful in numerical code. One reason to use the library methods is that a direct translation of a mathematical formula can behave badly with floating-point numbers:
double x = 1e200;
// A direct formula for asinh overflows when calculating x * x.
System.out.println(Math.log(x + Math.sqrt(x * x + 1))); // Infinity
System.out.println(Math.asinh(x)); // approximately 461.2101657793691
System.out.println(Math.acosh(1.0)); // 0.0
System.out.println(Math.acosh(0.5)); // NaN
System.out.println(Math.atanh(1.0)); // Infinity
System.out.println(Math.atanh(2.0)); // NaN
acosh accepts values from 1 upwards; atanh produces finite results between -1 and 1, with infinities at the endpoints. Use the StrictMath variants when you need the specified, reproducible results across platforms.
KeyStore creation time as an Instant ¶
Another small addition is KeyStore.getCreationInstant(String). The existing getCreationDate returns a java.util.Date; the new method returns a java.time.Instant, which fits directly into modern date and time code.
With an already loaded KeyStore named keyStore:
import java.time.Instant;
import java.time.ZoneOffset;
Instant created = keyStore.getCreationInstant("server");
if (created != null) {
System.out.println(created.atZone(ZoneOffset.UTC));
}
The result is null when the alias does not exist, and an uninitialized keystore causes a KeyStoreException. This is the creation time of the keystore entry, not a certificate's validity period. Keystore provider implementations get a corresponding KeyStoreSpi.engineGetCreationInstant(String) method.
For the complete list, check the new API list and select only 27. The JDK 27 project page lists the larger release features.
You can find the earlier parts of this series here: