Java 8 is shipping with a slew of awesome new features that you learned about in parts one and two of this Java 8 series. In part three we wrote about the improvements being made to HashMap and the date and time API, and now, in the fourth (and final) installment, we’ll round out the series by showing some of the other various improvements being shipped with Java 8.
The java.util.concurrent.atomic package has been expanded to include four new classes that allow for concurrent, scalable, and updatable variables. LongAccumulator and LongAdder (and the complementary DoubleAccumulator and DoubleAdder) can be used almost anywhere you need to sum a value across multiple threads, and is generally preferable to the AtomicLong class since it’s considerably faster. These new classes essentially store each update without affecting the original variable. This makes them thread-safe by avoiding contention rather than locking variables on write. Instead, the variable is only locked and updated whenever it’s read, meaning the performance enhancements provided by these new classes are negligible when reads are frequent. An interesting and thorough overview of the algorithm and performance enhancements can be found here.
Additionally, due to the way the accumulation is performed en masse, floating point errors can affect numerical stability. These new accumulators offer a boost in performance, but may only be applicable in some instances.
SNI comes to Java! Not sure what SNI is? Here’s a quick overview. Virtual hosting came with HTTP/1.1, and allowed a single server to host different websites with different hostnames that mapped to the same IP address. While this provided the benefits of sharing resources (and lower costs) it became problematic once websites began to utilize SSL and TLS encryption. The problem is that the handshaking process used by TLS requires servers to release their certificates based on the IP address the client is trying to access and not the hostname (the hostname came later). SNI (server name indication) is an extension to the TLS protocol that allows the client to specify the hostname before the handshaking starts so that the server knows which certificate to serve. The new SNIHostName, SNIMatcher, and SNIServerName classes that support this functionality are located in the javax.net.ssl package.
PermGen Error Elimination
Prior to Java 8, the Java HotSpot VM had a memory space, known as PermGen that was used to store class metadata. The capacity of this virtual memory space was fixed, which often lead to java.lang.OutOfMemoryError:PermGen errors. With Java 8, the HotSpot VM will no longer have PermGen space, and will instead allocate native memory, called Metaspace, to store class metadata, similar to the way the IBM and JRockit JVMs operate.
Capacity, Allocation, and Garbage Collection
By default, the initial size of the Metaspace will be set to 12 MB and 16 MB on the 32-bit client and server VMs, respectively, with larger sizes for the 64-bit VMs, and the maximum size is limited only by the amount of virtual memory available. These initial and maximum sizes can be capped manually, however, using the new MetaspaceSize and MaxMetaspaceSize flags, which are analogous to the old PermSize and MaxPermSize flags (note that the PermSize and MaxPermSize flags will be ignored at startup, and a warning will be issued). At runtime, the actual allocation of the Metaspace will be dynamically re-sized to meet the application’s needs. Once its use reaches MetaspaceSize, garbage collection will be triggered and the Metaspace will be expanded. This will continue to occur until either MaxMetaspaceSize is reached (if set) or if it runs out of native memory. At this point, a java.lang.OutOfMemoryError:Metaspace error will be thrown.
Not all of the data that was previously stored in PermGen will be moved to Metaspace. Most class metadata will be moved to Metaspace, but some miscellaneous data will be moved to the heap. Interned strings, for example, used to be stored in PermGen, but were moved to the heap in Java 7. As a result, it will be difficult for developers to intuit how a change to Java 8 will affect performance, and will necessitate a lot of testing and capacity planning to determine memory requirements. Some fine-tuning of the -Xms and -Xmx flags may be required, and developers will also need to determine whether they need to control the Metaspace allocation behavior with the MetaspaceSize and MaxMetaspaceSize flags.
Should You Upgrade to Java 8?
Java 8 is packed with great new features and much-needed improvements, making it one of the most highly anticipated Java updates. But should you update? There are some concerns. Two of the biggest concerns are likely to be the default methods, which could be easily overused, and the elimination of the Permanent Generation space, which will affect application performance and may necessitate a considerable amount of testing and planning. However, the performance increases with streams, HashMap, and concurrency classes, along with the potential uses of Nashorn and other miscellaneous library improvements seem to make upgrading to java 8 worth the effort.
This post is part four of a series covering Java 8:
– Java 8 Part 1 – Lamdas, Streams, and Functional Interfaces
– Java 8 Part 3 – HashMap and java.time
– Java 8 Part 4 – Concurrency, TLS SNI, and PermGen