Showing posts with label jfr. Show all posts
Showing posts with label jfr. Show all posts

Sunday, September 21, 2025

JDK-25: The Next Big Thing

Not exactly sure why but JDK-25 is a long awaited release. Probably because it is the next LTS (or whatever it means these days), or probably because it establishes a new baseline where there is no place for SecurityManager anymore. In any case, let us talk about everything that JDK-25 bundles in, starting with the stable features first.

  • JEP-506: Scoped Values: introduces scoped values, which enable a method to share immutable data both with its callees within a thread, and with child threads. Scoped values are easier to reason about than thread-local variables. They also have lower space and time costs, especially when used together with virtual threads and structured concurrency.

    Since the API is final now, let us take a look at it closely.

       private static final ScopedValue<Object> CONTEXT = ScopedValue.newInstance();
    
       executor.submit(() -> ScopedValue.where(CONTEXT, new Object()).run(() -> {
           final Object context = CONTEXT.get();
           // Use 'context'
        }));
      

    In simple terms, you can think of scoped values as an immutable ThreadLocals, however their true power kicks in with structured concurrency, which sadly is still in preview in JDK-25.

  • JEP-511: Module Import Declarations: enhances the Java programming language with the ability to succinctly import all of the packages exported by a module. This simplifies the reuse of modular libraries, but does not require the importing code to be in a module itself.

    This is pretty useful and simple enhancement that helps with imports explosion, for example:

      import module jdk.jfr;
     
  • JEP-512: Compact Source Files and Instance Main Methods: evolves the Java programming language so that beginners can write their first programs without needing to understand language features designed for large programs. Far from using a separate dialect of the language, beginners can write streamlined declarations for single-class programs and then seamlessly expand their programs to use more advanced features as their skills grow. Experienced developers can likewise enjoy writing small programs succinctly, without the need for constructs intended for programming in the large.

    It is now possible to omit some boilerplate when using the language:

      void main() {
          IO.println("Hello, World!");
      }
      
  • JEP-510: Key Derivation Function API: introduces an API for Key Derivation Functions (KDFs), which are cryptographic algorithms for deriving additional keys from a secret key and other data.

  • JEP-503: Remove the 32-bit x86 Port: removes the source code and build support for the 32-bit x86 port. This port was deprecated for removal in JDK 24.

  • JEP-514: Ahead-of-Time Command-Line Ergonomics: makes it easier to create ahead-of-time caches, which accelerate the startup of Java applications, by simplifying the commands required for common use cases.

    This is really nice improvement over two-step workflow in JDK 24 (please notice a new -XX:AOTCacheOutput command line flag), only one step is now required:

    $ java -XX:AOTCacheOutput=app.aot -cp app.jar com.example.App ...

    As a convenience, when operating in this way the JVM creates a temporary file for the AOT configuration and deletes the file when finished. The command line to run the application stays the same:

    $ java -XX:AOTCache=app.aot -cp app.jar com.example.App ...

    A new environment variable, JDK_AOT_VM_OPTIONS, can be used to pass command-line options that apply specifically to cache creation (AOTMode=create), without affecting the training run (AOTMode=record). The syntax is the same as for the existing JAVA_TOOL_OPTIONS environment variable. This enables the one-step workflow to apply even in use cases where it might seem that two steps are necessary due to differences in the command-line options.

  • JEP-513: Flexible Constructor Bodies: in the body of a constructor, allows statements to appear before an explicit constructor invocation, i.e., super(...) or this(...). Such statements cannot reference the object under construction, but they can initialize its fields and perform other safe computations. This change allows many constructors to be expressed more naturally. It also allows fields to be initialized before they become visible to other code in the class, such as methods called from a superclass constructor, thereby improving safety.

    In my opinion, this feature would greatly improve the readability of the class initialization, let us take a look at the example:

         class ByteArrayInputStreamInputStream extends ByteArrayInputStream {
            public ByteArrayInputStreamInputStream(int size) {
                if (size <= 0) {
                    throw new IllegalArgumentException("The size has to be greater than 0");
                }
                super(new byte[size]);
            }
        }
        

    In pre-JDK-25, super(...) had to be the first statement in the constructor body and we would have no choice but to implement a function to validate the size and return new byte array (or throw an IllegalArgumentException exception).

  • JEP-519: Compact Object Headers: changes compact object headers from an experimental feature (introduced in JDK 24) to a product feature. To enable this feature pass command line option:

    $ java -XX:+UseCompactObjectHeaders
  • JEP-521: Generational Shenandoah: changes the generational mode of the Shenandoah garbage collector from an experimental feature (introduced in JDK 24) to a product feature. The generational mode could be enabled through command line flags:

    $ java -XX:+UseShenandoahGC -XX:ShenandoahGCMode=generational
  • JEP-515: Ahead-of-Time Method Profiling: improves warmup time by making method-execution profiles from a previous run of an application instantly available, when the HotSpot Java Virtual Machine starts. This will enable the JIT compiler to generate native code immediately upon application startup, rather than having to wait for profiles to be collected.

  • JEP-518: JFR Cooperative Sampling: improves the stability of the JDK Flight Recorder (JFR) when it asynchronously samples Java thread stacks. Achieves this by walking call stacks only at safepoints, while minimizing safepoint bias.

    There is a new event introduced, jdk.SafepointLatency, which records the time it takes for a thread to reach a safepoint, for example:

        $ java -XX:StartFlightRecording:jdk.SafepointLatency#enabled=true,filename=recording.jfr
        $ jfr print --events jdk.SafepointLatency recording.jfr
        
  • JEP-520: JFR Method Timing & Tracing: extends the JDK Flight Recorder (JFR) with facilities for method timing and tracing via bytecode instrumentation.

    There are two new JFR events introduced, jdk.MethodTiming and jdk.MethodTrace, they both accept a filter to select the methods to time and trace, couple of the examples below:

        $ java '-XX:StartFlightRecording:jdk.MethodTrace#filter=java.util.HashMap::resize,filename=recording.jfr' ...
        $ jfr print --events jdk.MethodTrace --stack-depth 20 recording.jfr
        
        $ java '-XX:StartFlightRecording:filename=fd.jfr,method-trace=java.io.FileDescriptor::<init>java.io.FileDescriptor::close' ..
        $ jfr view --cell-height 5 MethodTrace fd.jfr
        
        $ java '-XX:StartFlightRecording:method-timing=::<clinit>,filename=clinit.jfr' ...
        $ jfr view method-timing clinit.jfr
       

    A filter can also name an annotation. This causes all methods bearing the annotation, and all methods in all classes bearing the annotation, to be timed or traced.

        $ jcmd <pid> JFR.start method-timing=@jakarta.ws.rs.GET
        

    It is also possible to use JMX and the JFRs RemoteRecordingStream class to configure timing and tracing over the network.

From all perspectives, the list of the finalized features that made it into JDK-25 is rock solid. But the release also bundles a number of a new experimental and preview APIs, in addition to carried over ones.

Besides JEPs, JDK-25 has plenty of enhancements across the board, including bugfixes and changes in the behavior that may affect the existing applications.

Moving on to the standard library, JDK-25 delivers rather moderate changes, but quite handy nonetheless. Let us take a look at those.

With respect to security, there are a few changes worth mentioning:

Last but not least, few regressions slipped into JDK-25 at the last moment, please be aware of those:

My personal retrospective on the JDK-25 release, among many other things, highlights a significant progress of the Project Leyden and substantial investments into JDK Flight Recorder (JFR) tooling and instrumentation. Let us see what comes next, the lineup for JDK-26 already looks exciting.

I πŸ‡ΊπŸ‡¦ stand πŸ‡ΊπŸ‡¦ with πŸ‡ΊπŸ‡¦ Ukraine.

Friday, October 11, 2024

JDK-23: the messenger?

It's been a little less than few weeks since JDK-23 was released and we have not covered it yet! To be fair, this is not a big deal, each new release gets more and more attention, but nonetheless! And while this one in particular may not be looking too exciting (well, mostly all the features are in preview), it is a messenger of what is coming next (and that is really thrilling).

Anyway, there are quite a few things that JDK-23 delivers.

Along with the new features, there are some disruptive changes as well, notably:

On the bright side, there are a number of enhancements, bug fixes, tooling and GC improvements that are worth mentioning:

The changes on the standard library API side are quite moderate:

On the final note, it is good time to go over some security related updates that were introduced into JDK-23 (for more details, please check JDK 23 Security Enhancements):

If anything, JDK-23 is a solid release, ready for prime time. From the changes perfective, it looks low risk as well, so if you skipped JDK-22 for some reasons, JDK-23 may be the one.

I πŸ‡ΊπŸ‡¦ stand πŸ‡ΊπŸ‡¦ with πŸ‡ΊπŸ‡¦ Ukraine.

Saturday, March 23, 2024

JDK-22: The JNI's grave?

Another six months passed and it is about time for a new JDK release: without further ado, please meet JDK-22. The theme of this release is obviously Foreign Function & Memory API that becomes generally available after numerous preview cycles. So what else is there?

  • JEP-454: Foreign Function & Memory API: introduces an API by which Java programs can interoperate with code and data outside of the Java runtime. By efficiently invoking foreign functions (i.e., code outside the JVM), and by safely accessing foreign memory (i.e., memory not managed by the JVM), the API enables Java programs to call native libraries and process native data without the brittleness and danger of JNI.

    By all means, Foreign Function & Memory API (or FFM shortly), was eagerly awaited. For a long time JNI was the only mechanism to access native code on JVM and it has gained pretty infamous reputation of being brittle and outdated. FFM has emerged as a (substantially) better alternative and, after many rounds of previews, the API is finalized in JDK-22.

  • JEP-423: Region Pinning for G1: reduces latency by implementing region pinning in G1, so that garbage collection need not be disabled during Java Native Interface (JNI) critical regions.

  • JEP-456: Unnamed Variables & Patterns: enhances the Java programming language with unnamed variables and unnamed patterns, which can be used when variable declarations or nested patterns are required but never used. Both are denoted by the underscore character, _.

    To be fair, the positive impact of this small language change on the readability of Java programs is paramount. Familiar to Scala developers for years, it is here for Java developers now.

            if (content instanceof String s && s.startsWith("{")) {
                parseJson(s);
            } else if (content instanceof String s && s.startsWith("<")) {
                parseXml(s);
            } else if (content instanceof String _) {
                throw new IllegalArgumentException("The content type is not detected");
            };
      

    It becomes even more evident with records:

    
         sealed interface Response permits NoContentResponse, ContentResponse {}
        record NoContentResponse(int status) implements Response {}
        record ContentResponse(int status, byte[] content) implements Response {}
    
        public int status(final Response response) {
            return switch(response) {
                case NoContentResponse(var status) -> status;
                case ContentResponse(var status, _) -> status;
            };
        }
          

    And lamba functions:

        BiFunction<String, Number, String> f = (_, n) -> n.toString();
        
  • JEP-458: Launch Multi-File Source-Code Programs: enhances the java application launcher to be able to run a program supplied as multiple files of Java source code. This will make the transition from small programs to larger ones more gradual, enabling developers to choose whether and when to go to the trouble of configuring a build tool.

    This is a logical continuation of the JEP 330: Launch Single-File Source-Code Programs, delivered in JDK-11. With this change, Java could seriously challenge the status quo of the established scripting languages.

Couple of new and refined preview language features and APIs are also made into release, just briefly mentioning them here (and we would get back to them once finalized).

Every new JDK release comes with a long list of bugfixes, and in case of JDK-22, there are quite a few worth mentioning:

Moving off from bugs and regressions, let us take a look at the interesting new features that JDK-22 delivers across the board:

Last but not least, let us talk about the API changes (standard library) that went into this release.

From the security perspective, there are couple of notable changes to highlight (but please, do not hesitate to check out JDK 22 Security Enhancements for more details):

To finish up, it will be useful to mention a few regressions that ended up in JDK-22 release, the fixes are already scheduled for the upcoming major or patch releases:

Some may say that JDK-22 is a boring release, but I personally disagree: FFM APIs and formalizing _ usage are all but not boring features.

I πŸ‡ΊπŸ‡¦ stand πŸ‡ΊπŸ‡¦ with πŸ‡ΊπŸ‡¦ Ukraine.

Thursday, October 5, 2023

JDK-21: green threads are officially back!

The JDK-21 is there, bringing virtual threads (back) into JVM as a generally available feature (if you are old enough like myself, you might have remembered that in Java 2 releases prior to 1.3 the JVM used its own threads library, known as green threads, to implement threads in the Java platform). This is big, but what else is coming?

  • JEP-431: Sequenced Collections: introduces new interfaces to represent collections with a defined encounter order. Each such collection has a well-defined first element, second element, and so forth, up to the last element. It also provides uniform APIs for accessing its first and last elements, and for processing its elements in reverse order.

    The following new interfaces have been introduced (and retrofitted into the existing collections type hierarchy), potentially a breaking change for some library implementors:

  • JEP-439: Generational ZGC: improves application performance by extending the Z Garbage Collector (ZGC) to maintain separate generations for young and old objects. This will allow ZGC to collect young objects — which tend to die young — more frequently.

    By default, the -XX:+UseZGC command-line option selects non-generational ZGC, but to select the Generational ZGC, additional command line option -XX:+ZGenerational is required:

    $ java -XX:+UseZGC -XX:+ZGenerational ...
    

  • JEP-440: Record Patterns: enhances the Java programming language with record patterns to deconstruct record values. Record patterns and type patterns can be nested to enable a powerful, declarative, and composable form of data navigation and processing. This is certainly a huge step towards having a powerful, feature-rich pattern matching capabilities in the language:

        interface Host {}
        record TcpHost(String name, int port) implements Host {}
        record HttpHost(String scheme, String name, int port) implements Host {}
        

    The are several places the records could be deconstructed, instanceof check being one of those:

        final Host host = new HttpHost("https", "localhost", 8080);
        if (host instanceof HttpHost(var scheme, var name, var port)) {
            ... 
        } else if (host instanceof TcpHost(var name, var port)) {
            ...
        }
        
  • JEP-441: Pattern Matching for switch: enhances the Java programming language with pattern matching for switch expressions and statements. Extending pattern matching to switch allows an expression to be tested against a number of patterns, each with a specific action, so that complex data-oriented queries can be expressed concisely and safely.

    Considering the example with the records deconstruction from above, we could use record patterns in switch expressions too:

            var hostname = switch(host) {
                case HttpHost(var scheme, var name, var port) -> name;
                case TcpHost(var name, var port) -> name;
                default -> throw new IllegalArgumentException("Unknown host");
            };
        

    But the switch patterns are much more powerful, with guards to pattern case labels, null labels, etc.

            final Object obj = ... ; 
            var o = switch (obj) {
                case null ->  ... ;
                case String s -> ... ;
                case String[] a when a.length == 0 -> ... ;
                case String[] a -> ... ;
                default ->  ... ;
            }
        
  • JEP-444: Virtual Threads: introduces virtual threads to the Java Platform. Virtual threads are lightweight threads that dramatically reduce the effort of writing, maintaining, and observing high-throughput concurrent applications. The virtual threads and executors could be used along the traditional ones, following the same familiar API:

        try (var executor = Executors.newVirtualThreadPerTaskExecutor()) {
            executor.submit(() -> {
                    ...
            });
        }  
        

    Some of the quirks of the virtual threads we have discussed previously here and here, but there is one more: you could use them in parallel streams, but should you? The answer is a bit complicated, so referring you to Virtual Threads and Parallel Streams article if you are looking for clarity.

    The JDK tooling (like jcmd and jfr) has been updated to include the information about virtual threads where applicable.

    The jcmd thread dump lists virtual threads that are blocked in network I/O operations and virtual threads that are created by the ExecutorService interface. It does not include object addresses, locks, JNI statistics, heap statistics, and other information that appears in traditional thread dumps (as per Viewing Virtual Threads in jcmd Thread Dumps).
    Java Flight Recorder (JFR) can emit these events related to virtual threads (as per Java Flight Recorder Events for Virtual Threads):
    • jdk.VirtualThreadStart and jdk.VirtualThreadEnd (disabled by default)
    • jdk.VirtualThreadPinned (enabled by default with a threshold of 20 ms)
    • jdk.VirtualThreadSubmitFailed (enabled by default)

    It is worth noting that Oracle has published a comprehesive guide on virtual threads as par of JDK-21 documentation update.

  • JEP-449: Deprecate the Windows 32-bit x86 Port for Removal: deprecates the Windows 32-bit x86 port, with the intent to remove it in a future release.

  • JEP-451: Prepare to Disallow the Dynamic Loading of Agents: issues warnings when agents are loaded dynamically into a running JVM. These warnings aim to prepare users for a future release which disallows the dynamic loading of agents by default in order to improve integrity by default. Serviceability tools that load agents at startup will not cause warnings to be issued in any release.

    Running with -XX:+EnableDynamicAgentLoading on the command line serves as an explicit "opt-in" that allows agent code to be loaded into a running VM and thus suppresses the warning. Running with -XX:-EnableDynamicAgentLoading disallows agent code from being loaded into a running VM and can be used to test possible future behavior.

    In addition, the system property jdk.instrument.traceUsage can be used to trace uses of the java.lang.instrument API. Running with -Djdk.instrument.traceUsage or -Djdk.instrument.traceUsage=true causes usages of the API to print a trace message and stack trace. This can be used to identify agents that are dynamically loaded instead of being started on the command line with -javaagent.

  • JEP-452: Key Encapsulation Mechanism API: introduces an API for key encapsulation mechanisms (KEMs), an encryption technique for securing symmetric keys using public key cryptography. The new APIs are centered around javax.crypto.KEM and javax.crypto.KEMSpi abstractions.

  • JEP-430: String Templates (Preview): enhances the Java programming language with string templates. String templates complement Java's existing string literals and text blocks by coupling literal text with embedded expressions and template processors to produce specialized results. This is a preview language feature and API.

  • JEP-453: Structured Concurrency (Preview): simplifies concurrent programming by introducing an API for structured concurrency. Structured concurrency treats groups of related tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability. This is a preview language feature and API.

  • JEP-443: Unnamed Patterns and Variables (Preview): enhances the Java language with unnamed patterns, which match a record component without stating the component's name or type, and unnamed variables, which can be initialized but not used. Both are denoted by an underscore character, _. This is a preview language feature.

  • JEP-445: Unnamed Classes and Instance Main Methods (Preview): evolves the Java language so that students can write their first programs without needing to understand language features designed for large programs. Far from using a separate dialect of Java, students can write streamlined declarations for single-class programs and then seamlessly expand their programs to use more advanced features as their skills grow. This is a preview language feature.

  • JEP-446: Scoped Values (Preview): introduces scoped values, values that may be safely and efficiently shared to methods without using method parameters. They are preferred to thread-local variables, especially when using large numbers of virtual threads. This is a preview language API.

    In effect, a scoped value is an implicit method parameter. It is "as if" every method in a sequence of calls has an additional, invisible, parameter. None of the methods declare this parameter and only the methods that have access to the scoped value object can access its value (the data). Scoped values make it possible to pass data securely from a caller to a faraway callee through a sequence of intermediate methods that do not declare a parameter for the data and have no access to the data.

  • JEP-442: Foreign Function & Memory API (3rd Preview): introduces an API by which Java programs can interoperate with code and data outside of the Java runtime. By efficiently invoking foreign functions (i.e., code outside the JVM), and by safely accessing foreign memory (i.e., memory not managed by the JVM), the API enables Java programs to call native libraries and process native data without the brittleness and danger of JNI. This is a preview language API.

  • JEP-448: Vector API (6th Incubator): introduces an API to express vector computations that reliably compile at runtime to optimal vector instructions on supported CPU architectures, thus achieving performance superior to equivalent scalar computations.

Those JEPs are the themes of JDK-21 but what other features are coming? There are quite a few to unpack to be fair.

The JDK-21 changeset looks already impressive but ... we are not done yet, let us walk through the standard library changes.

From the security perspective, JDK-21 is pretty packed with enhancements. Some of them we have highlighted above but a few more deserve special mentions (if you need a comprehensive look, please check out JDK 21 Security Enhancements article):

From all perspectives, JDK-21 looks like the release worth migrating to (it is supposed to be LTS), despite the fact there are unforeseen delays announced by some vendors.

I πŸ‡ΊπŸ‡¦ stand πŸ‡ΊπŸ‡¦ with πŸ‡ΊπŸ‡¦ Ukraine.