Spring Boot 4 finally codifies null safety, turning developer discipline into a mandatory build-time constraint. It’s a pragmatic evolution that effectively narrows the safety gap between Java and Kotlin through standardized static analysis.
Deep Dive
Prerequisite Knowledge
- No data available.
Where to go next
- No data available.
Deep Dive
Null-safe applications with Spring Boot 4 by Sébastien Deleuze @ Spring I/O 2026Added:
[music] >> Hello everybody. I'm Sebastian Deleuze.
I have been a Spring Framework committer for 12 years now. I have recently joined the Spring AI team, so I'm currently splitting my time between Spring Framework and Spring AI projects.
And I'm going to talk today about a topic that has occupied most of my previous year.
Uh working with the wider Spring team on introducing new safety in the whole Spring portfolio. And we are going to see how you can benefit of that in your Spring Boot 4 applications.
So, I mean, you already know NullPointerException that come basically Friday afternoon on production and then you need to redeploy stuff and yeah, we what we want to do is not to basically NullPointerException still exists, but we want to handle that before shipping our application on production. And we are going to see that it's much more involved and profound that just removing NullPointerException.
NullPointerException, so this is going to be the topic for for today. So, are we fixing the billion-dollar mistake, which is uh basically the qualifier that is used by the new inventor on on C side. Uh yes, we are and we are going to fix it with Spring Boot 4 and JSpecify.
So, JSpecify it's a it's a community effort that has been performed by various companies and organization like Google, JetBrains, Broadcom, via Spring and many others.
And basically, we have tried to come together in order to standardize annotations to express new safety, but also the scope could be a bit bigger later. The goal is to provide like some annotation that are not tied to specific tool to express that.
Uh to provide capabilities that allow to get net next level static analysis in your IDE, in your build tools.
Uh and this is what we are going to use today.
Um JSpecify it's not just for annotations, it's also uh full documentation, comprehensive documentation that basically explain all the nuances of nullability and believe me, there is a lot of nuances, especially when we are talking about generic types nullability for example. Moritz, I guess you remember.
Uh this is very long task on Spring Boot 4.
Um it's also specifications.
Uh this one is a bit more involved, so unless you are a compiler engineer, I don't really advise you to read that one, but this is one that is useful for tooling vendors. So, basically VS Code developers, uh people that develop the VS Code IDE or IntelliJ IDEA or NullAway or other kind of tools, they are using that as the source of truth to implement the same behavior. That way uh whatever tool or IDE you are using, you are expected to have the same behavior.
You may wonder, Sebastian, in 2017, you said that you were introducing new safety annotation in Spring Framework 5, so what's new?
Um that's true. We have been introducing that pretty early. It was inspired by Kotlin, which was providing that on Kotlin side and we have we have made a first step to introduce new safety on Java side. But uh those Spring Framework annotations are now deprecated in favor of JSpecify annotation. So, if you have a Spring Boot 4 Spring Framework 7 project, you will see that those new safety annotation that are in the org.springframework.lang package, they are now deprecated since 7.0 and you are advised to use JSpecify instead.
If you are using those annotations, the best way to migrate is not to use your agent to do stuff with code code or whatever, it's just to use OpenRewrite or tons of application advisor to migrate automatically because the rules of conversion are pretty simple. You are just migrating from Spring Framework Nullable to the JSpecify one with some nuances, so just applying those recipes is likely the most obvious way to do that and that's pretty simple.
Okay, so what changed?
What are the news? So, we are coming from Spring Boot 3 with Spring new safety annotation with mainly two two projects annotated, Spring Framework, Spring Data.
Um we were not using an automated tool to check everything was consistent, so to be totally transparent, it was Juergen and me checking warnings in the IntelliJ IDEA time to time to fix stuff. It was not super deterministic, but at that time it was like a first step and it was already good enough.
Um we also got a lot of feedback from the Kotlin community because basically when you get new safety wrong, new safety wrong, Kotlin developers can't use your API because they can't provide for example new parameters. So, we got a lot of feedback on that and the Kotlin community has been contributing a lot to the quality of the new safety annotation that we have now for the Java developers as well.
Um there has been some translation from the older Spring Framework annotation to Kotlin, but it required an explicit flag. Now, as of Kotlin 2.1, the translation from JSpecify to Kotlin new safety is automatic, nothing is needed.
Automatically handled by the Kotlin compiler. We have now proper specification, canonical dependency because I think there is at least five different JSR 305 dependencies that are flying around Maven Central, so here we have a single well-identified uh JSpecify dependency.
Usable by outside of Spring and it was not usable outside of Spring except if you are using directly JSR 305 and there was no handling of generic type nullability.
What is new is that basically the Spring team and I thanks all my colleagues for this very long task.
The whole Spring portfolio is now providing full new safe APIs.
Uh I'm going to list all the projects.
It's going to be long, but let's do it.
So, in addition to Framework and Data, who just migrated from Spring Framework to JSpecify annotation, we have now Boot, Security, AI, Batch, Kafka, Integration, GraphQL, Web Services, AMQP, Share, HATEOAS, Modulith Cloud and even Micrometer and Reactor are providing new safe annotation with JSpecify. It has been long to introduce that, but now that it's introduced, we are able to move faster and in a more safer in a most most safe way for the future evolution.
Uh and we get all the benefits. All those projects are just not adding annotation and basically praying for them to be okay. Every project has introduced new away checks. So, as soon as we have inconsistencies, Spring project build is broken and we need to fix it.
Uh we have out of the box Kotlin supports, proper specification and generic type nullability, so it's really the scope and the quality of those new safety annotation that has that have dramatically improved.
So, in practice, if you are using Spring Boot 4 and you go to the Java doc, you will see on almost every packages a new marked annotation on each package.
We have decided to new mark every package. That means that in this package uh the default is non-new, so if there is no other annotation, default is non-new and then you only specify explicitly at new label because we have I mean, I'm not sure about the stats, but something like 5% of the type usage are new label and the rest are non-new.
So, we to limit the noise, basically we focus on marking specifically the the unusual case.
So, in this package, when you see this kind of uh method definition, we have basically no JSpecify annotation. That means that the related parameters and return values are non-new. You you don't need to check new return values. You can't provide new parameters. You know that for sure and it's checked and validated and everything. And when we have something that is new label, either in term of return value, so you need to check the return type or parameter where you can potentially pass new as a parameter, this is explicitly mentioned by this at new label annotation, which is a JSpecify annotation and this is true for all the Spring portfolio.
So, what are the benefits for Java developers? And by benefits, I means you don't have to do anything except just consuming using Spring Boot 4, okay?
After that, we will see more involved steps. So, if you are using an IDE that supports JSpecify new label annotation, you have supports out of the box in IntelliJ IDEA, you have supports via plugins in VS Code. You will get this kind of warnings where if you are trying to do something that is not new safe like here, get web application type can be potentially return new label values and you need to check that before calling a method on it. You will get this kind of warnings with auto fix and so you get that information even before running your Maven or Gradle build.
Same if you try to pass new parameter to something that is not annotated with at new label, the IDE will say you, "Hey, it's look like you are doing something not really authorized." And you get the information right off time.
But it's it's much more than just avoiding NullPointerException.
Um when we have introduced new label in all Spring projects, we did that recently in Spring AI.
Um it has a profound impact. New label is a zero zero cost abstraction allowing to express the potential absence of value.
It was kind of implicit before and now the fact that is explicit, it's allow us to who code with more confidence. Kotlin developer know what I mean.
But, that's also true for Java side. And for example, on Spring AI, the fact that we have added explicit nullability and that we have made it everything explicit about this is mandatory, this is optional uh has led to a bigger factoring of the option uh management for Spring AI models. And you will see that in Spring AI 2.0. So, it's much more than uh basically just avoiding null pointer exception.
Let's talk about optionals. So, you may uh why don't use uh optional? I mean, it's provided by the JDK. It's designed to express the potential absence of value. And uh optional uh sadly is not usable for a lot of use cases. So, it's not a general purpose solution for what you want to try to do. Because we don't have yet project Valhalla.
Uh so, there is runtime overheads. But, the most important thing, do you think that uh Spring, JDK, and other popular project are going to modify all the API signatures to replace T by optional of T? No, it will never happen. We can't break all those APIs that are here forever or at least for 20 years. It's impossible. So, uh we can't use it. And also, it's not intended for use as parameter or fields. It's not a personal opinion. This is stated by optional Javadoc. For various reasons, you can uh have a deeper look. And it just increase the complexity of code because you are putting wrappers everywhere, etc. So, um yeah, I'm not a good friend with optional. I think when you are expressing explicitly nullability, so the absence of value or not explicitly, a lot of use cases can be solved without optional.
Um benefits for Kotlin developers. So, if you are Kotlin developers or if you are a Java library developer that you are targeting uh by nature basically Kotlin uh developers, this is the Spring API that is visible from Kotlin in Spring Boot 3. As a Kotlin developer, I see a lot of exclamation mark at the type system.
Exclamation mark means platform type, mean un- unspecified null safety. So, basically Kotlin manage natively null safety for its own API, but for the API that are coming from Java, Kotlin is not sure that it will be nullable or not. So, it will be lenient.
But, at the same time, you are at risk to get null pointer exception. And so, as a Kotlin developer, when I see that, it feel like Java compa- compatibility mode. It does not feel very idiomatic.
And when I'm using the same API from Spring Boot 4, it's it's like Spring Boot 4 was developed natively in Kotlin. I get everything specified explicitly, including on generic types. Nothing specified means basically it's non-nullable. This is the default. And when something is nullable, uh we have this question mark mechanism. So, basically Kotlin compiler is translating automatically at nullable annotation to question mark thing, and the rest is non-null, and it look like Kotlin idiomatic code. So, that's a big change for uh Kotlin developers, I think.
When there is nullability mismatch, of course, like with Kotlin code, it will trigger some error in the IDE. You get also uh basically compiler errors if you are not basically complying with the nullability, and everything is safe, and you are not at risk anymore to have null pointer exception on production if you are using Kotlin and uh Spring Boot 4.
So, uh now if you want we have described until now what you can do just by consuming Spring Boot 4. You have not done specifically except that you have upgraded from Spring Boot 3 to Spring Boot 4. But, what we did for the Spring project introducing null safety, introducing null away, etc., you can do it for your own project if you want.
It's totally optional. I'm not saying you need to do that on every project.
There is a lot of added value doing that depend on the context, but I'm going to explain how you can make your project null safe because you can't really be sure that you are not at risk to get null pointer exception on production.
We are covering the library uh uh code on Spring side, but on your side, your application is at risk to produce null pointer exception.
So, very basic step. So, the first step, step zero is upgrading to Spring Boot 4, okay? Mandatory. Then, um read J Specify documentation. That sounds like a very basic advice, but in the age of JNI and everything is going so fast, please take the time to read the documentation. The user guide is really designed for application developers and understanding the semantics, the nuances, especially regarding to generic types, array elements, and various thing.
It's worth your time. So, take your time, read that carefully, it will be useful.
Second step is to have the right mental model.
Um maybe you may think it's the just nullable non-nullable, but it's not the case.
Java code is as unspecified nullability.
And basically, this is similar to Kotlin platform type.
If you have some code that is not annotated with uh J Specify, you don't know what is the nullability.
And you will potentially mix that with some code that is null safe, for example, the Spring one.
So, regular Java unspecified nullability, everything is implicit. You have to read the Javadoc or read the implementation. Uh I'm not sure what you need to do.
Java plus J Specify, you are switching in a mode where the nullability is explicit, and a type usage is ever nullable, can include null, or non-null, never include null. Okay?
Then, you need to add the J Specify dependency. So, there is a canonical dependency, which is this org.j specify group ID, uh j specify artifact ID, and 1.0.0. Super simple.
Um you need to define the scope of where you are going to introduce null safety because if you have hundreds of thousands classes project, and you want to introduce null safety one shot, uh it's going to be difficult. So, I really advise to start uh small. Focus maybe on one single package initially, or maybe one module if that's bigger.
And basically, only check that the nullness declaration are consistent within this very same package, and then you are going to extend the scope gradually because otherwise it's it's going to be difficult.
So, when you have identified a nice package uh to start with, you just uh add a package info or edit if there is already one. And basically, you are going to add this null marked annotation, which says within this package, everything is non-null by default, and every nullable use case will be uh mentioned via at nullable.
Okay? This is not uh supporting sub package. So, if I have uh org.example.foo sub package, I need to create another package info and annotate it like it's regular Java way of handling things, but it's not transitive.
So, annotating one package null marked is pretty easy. Now, it's going to be a bit more challenging because you need to add carefully nullable where that's relevant.
So, here for example, I have added nullable on the return type because here this method can potentially return null.
Simple example, but when you have like a huge number of classes, you need to yeah, infer it based on the Javadoc, the implementation, and you you have to start somewhere, and then you will be able to use some tooling that will report errors, and then take it from there.
Before going to see some ways of uh basically doing that in a more automated fashion, uh few tip and tricks.
So, J Specify annotation are usually not enough to avoid too many false positive.
We need to express additional semantics.
This is why Spring Framework has introduced this contract annotation, which is similar to JetBrains or JSR 305 1. And here, we want to express additional semantics that J Specify can't yet express. By the way, we are working on J Specify side to standardize this kind of contract, but it's not yet ready.
Uh so, here for example, I want to express that when the boolean expression uh is false, this uh method will throw an exception, and basically the code flow will not continue. And this is useful for um static analysis of the code because here on the usage side, after calling assert.state, foo is different of null.
Uh I can be sure that basically foo will be different of null because if not, an exception will be thrown, and the foo.something line will be never reached. So, this is why um without this contract annotation, I would have some false positive of null away saying, "Oh, foo can be null. It's dangerous." But here, with this additional contract information, null away, the analysis of the code will basically be able to say, "Okay, I know that when basically I'm reaching foo.something, foo is not null. So, very complementary.
Um to give you an idea, this is the most frequent contracts that Spring Framework code base is using. Of course, in your project that will be different, but it's interesting to see the patterns. You see the patterns where basically uh when a parameter is null, something is returned false, or yeah, this is again used by null away to uh basically refine the code path analysis. You have some use case where basically we are throwing exception depending on the parameter values.
We have also what we call polynomial.
So, polynomial is basically the nullability of the return value depends on the nullability of the input parameter. And this is what specialist call polynomial.
Um and yeah, all the kind of use case, but this is the popular use case we have in Spring Framework, and maybe that that can provide you inspiration for the kind of use case you you may have to manage for your code base. Uh I think we are using that a lot for the utility classes assertions and stuff like that that Spring is doing.
So, yeah, maybe useful.
Uh second second hints, you can express flexible nullability at class level. So, I won't go into the detail of the nullability of generic type parameter at class level. It's pretty complex, but here uh basically I want to express the fact that T that is defined at the class level can be sometimes nullable, can be sometimes non-nullable. And the differentiation will be done when I will declare a transaction callback. So, if I declare transaction callback at nullable object, that means that the return value will be nullable. If I declare something like transaction callback object in a null marked code, that means that this is an implicit at non-null. So, the return value will be non-null. And so, the way to express that on declaration site is basically T extend at nullable object. You can read J Specify documentation to understand why we have to use this kind of syntax, but yeah, this is the best way we have found to to express that. And if the declaration was transaction callback at nullable of T, that would means that T is always nullable. Okay, so here we want to be flexible. And this is only possible here because there is a direct um T at class level has the same nullability than T at the return value of the method. Sometimes it's not the case, so this kind of flexible nullability at class level is not always possible, but sometimes it is.
Um Arrays and var args, so uh we are going to learn a bit of more syntax. So, basically J Specify nullable annotation is basically only targeting type use.
And those type use annotation have specific syntax to be able to differentiate if the annotation annotates the element type or the array itself.
And so, with J Specify when you want to say that the individual elements of the array are nullable, but not the array itself, you are going to use this at nullable object square brackets syntax.
When you want to express that basically elements are not nullable, but the array itself could be nullable, you are using this object at nullable square brackets.
You can basically think that yeah, you are going to annotate basically the element where you want to express the nullability. And if you want to express that both elements and array can be nullable, you would put at nullable object at nullable square brackets and you are you are fine.
Um Could be a bit weird initially, but there is more weird. There is that. So, this is not J Specify fault. This is a Java specification for again annotation that are only targeting type use.
And so, the Java specification, I think it's supported as Java 8, so pretty old, but hardly used.
Um if you want to annotate basically an inner type or a fully qualified type, you need to put the annotation after the last dot. So, if you put at nullable cache. value value wrapper, you will have a compiler error and same for the fully qualified Java validation validator. So, a bit weird, not that common, but this is the Java specification. So, J Specify is just following that. So, just just be aware.
Okay, now we have just annotated our code base, but we have checked nothing.
So, basically there could be plenty of errors. We could annotate the wrong thing. It's it's it's not super uh uh yeah, it's it's it's not very good. So, we are going to introduce build check with NullAway. NullAway is going to allow us to perform build time checks to check the consistency and the correctness of the nullability annotations.
So, you need to use a recent JDK. So, the updated guidelines are if you are using JDK 17, you need to use JDK 17.0.19 plus, which will be released next week.
So, almost good timing. Before you had an option except using a more recent JDK. So, it's a good thing that this support has been backported to Java 17.
So, you need to use this recent version and you need to use a Java C argument that is specified here.
Same for JDK 21. This one is already available. So, 21.0.8 or more recent with the very same Java C argument.
And JDK 25, no argument is needed. It's supporting everything by default. And what you can do, and this is what we have decided to do in the Spring portfolio, you can totally use a more recent JDK to compile your application and specify {dash}{dash} release 17 if you want to have a 17 baseline. And it's very safe because we are doing that for Spring Framework and Spring Boot and Spring Data and all of our projects. So, my recommendation would be to basically decouple basically the version of the JDK that is used and you use a more recent LTS 25 and use {dash}{dash} release something, which is basically your baseline.
So, let's see the detail of the configuration. For Gradle, we are going to um so, NullAway is an extension for Error Prone. Error Prone is a basically static analysis tool maintained by Google.
And so, we are going to declare this Error Prone Gradle plugin.
We specify that we are using a recent Java 17 25 version. And in addition to the J Specify dependency, we are adding with the Error Prone configuration Error Prone core and NullAway dependencies, which are annotation processors.
And we are going to configure NullAway in order to first disable the all the other checks from Error Prone because Error Prone is doing much more other things that NullAway. And so, here on my side I prefer to focus only on NullAway checks to not have additional noise and concern. Feel free to enable that after, but initially I would advise to focus on just NullAway.
By default, NullAway is basically generating warnings. I prefer to configure errors a bit like Kotlin compiler behavior.
We are using J Specify, then we enable enable the J Specify mode. It may become the default a bit later, but right now it's a flag that we enable explicitly.
And the last option is pretty important.
We say that we want to only perform checks on null marked scope.
And this one is super important to introduce gradually NullAway checks because if you are just annotating one package with null marks, NullAway will only check this unique package. And then you can expand gradually the scope. So, this option is very cool. And option release 17 if you want to specify the baseline.
Maven configuration is going to be a bit more verbose.
So, we configure the same 25 Java version, same J Specify dependency, and we are going to do a bit of advanced Maven compiler plugin configuration.
Mark, I see your eyes.
>> [laughter] >> I see you are crying thinking about Spring Data Maven configuration, but yeah.
Let's see. So, uh you need to configure the fork is enabled and we are going to configure annotation processor path and compiler args.
Annotation processor path very similar to Gradle, the two same annotation processors. We are fine. Now, brace yourself.
Yeah. So, compiler args. So, we have to add explicitly a few exports that are required for NullAway to have access to special JDK compiler capabilities. By the way, Gradle is doing the same. It's just that it is hidden, but here it's not hidden because there is no specific plugin.
That means that if somebody in the room want to develop a NullAway plugin for Maven, be my guest and please remove that madness from our configuration. But right now uh we have to specify it explicitly.
Just copy and paste, put that in a in a profile and forget about it. But and otherwise, you are going to specify the various arguments to disable checks, turn warnings to errors, enable J Specify mode, and only enable null mark.
Those args in this line with disable checks, they need to be on the same line. You can't use Yeah, don't ask me why.
Maven craziness. So, yeah, you you need to copy that, don't touch it, and it will be fine.
Thanks.
Okay, if you want to have a deeper look, I have created this J Specify NullAway demo repository where you can check as there is a Maven branch. Main is with Gradle and you can test it with a sample project. It it will be easier to to start.
Okay, now the most fun part of the of the talk. So, it took a lot of time to the Spring team to add nullability annotations.
Remember, it was last year, not in 2026.
And also, I mean, at some point we were the first one to do this kind of thing at that scope. I mean, Google has also introduced nullability annotation on big project, but I think we are the bigger.
So, basically as poor humans had to spend times, a lot of time, uh to annotate the code, see NullAway errors, fix things, stuff, and doing some kind of work like that.
Um the good news is that we have recently learned that coding agent can make code base null safe automatically. Of course, as a human, you are responsible for your code. you need to review and own what you produce even with crazy tools like that, but still it's possible, but you need to teach them how. And I'm going to share some secret recipes with you today.
Um and we have been able to successfully and especially Joe from the security team has been able to apply that using cursor and some Entropic models. So, I think he used used sonnets, but Opus should be even better.
Um with other models like I tried with Gemini does not work. So, really it really depends on the models, the version, how many people are using cloud code while you are running that. So, it's not deterministic, right? But should be doable.
So, let's see how we do that. We need to do a lot of preparation. If you just ask add G specify annotation to my project, nope, won't work. So, we are going to do a bit of preparation by creating some skills. You can mostly potentially use the plan mode of your agent to do that, but I prefer to use skills because they are reusable multiple times and you can refine them. So, we are going to prompt creation of skills that should add automatically G specify support.
So, the first one I advise to do is something like So, this is my prompt, okay?
Uh create an agent skill named G specify user guide from the URL of the G specify user documentation that will define rules useful to introduce G specify annotations to a Java project not yet annotated. So, it should create the related uh related skill.
Second one, uh do the same thing basically, but with the Spring Framework new safety documentation that I have carefully crafted and that product provide additional rules. Some of them are specific to the Spring project, but it's it's pretty complementary and since we want to be mindful of our context, focus on the rules not yet identified in G specify user guide. So, that should be a superset. Okay?
And the big one, and this is the one that is basically going to suck my brain >> [laughter] >> and basically reuse that knowledge for your project. Because basically I spent hundreds of hours adding new liability annotation on Spring Framework. Moritz did the same for Spring Boot. Mark did the same for Spring Data. And so, basically you can reuse all this effort by learning some rules. And so, basically my prompt is yeah, create an agent skills based on the detailed analysis of the G specified new liability and add contract annotation in URL of the GitHub repository Spring.
Focus on the Spring Core module because if you are doing that on all module, basically that would be too big. So, I really advise you to go module after module, and Spring Core is the most important one.
Identify implementation pattern and best practices. The goal is to identify the various ways to infer those annotations, especially at new level ones based on the implementation of Java doc.
Focus on rules not yet identified in previous skills. So, it's it's really this one that is going to be the most useful because you are going to learn about all the nuances, the subtleties that are even not specified. And you can basically refine using other modules.
So, basically do the same, refine those rules analyzing Spring Web module. I know Joe has been applying that on Spring Security. So, basically even a new project, if you have annotated one module, you can say, "Okay, learn my own rules that may be not the same that Spring ones." And then you are adding a complementary skills.
Um and then last one, create an agent skills named new way configure by analyzing the project the repository I was showing just before to understand how to configure new way in Gradle, Gradle Kotlin, or Maven builds. So, here you are finished to create your rules to learn, to do your plan mode, and you are ready to do the effective work on your project. So, you open your project, you open an agent, cloud code, or whatever.
You start by configure new way in my project using new way configure skills.
Should be good.
And then the most important part of the work, add G specify and contract annotation to package something or could be a whole module to make it new safe using the agent skills prefix with G specify. So, all the one we have been creating previously. Run the build, analyze new way error messages, fix related errors, and repeat until there is no error. And basically uh yeah, add potential new rules discovered to an agent skill name G specify agentic loop analysis. So, basically while the agentic loop is going to run new way, see errors, fix them, okay, I have two less errors, I need to fix five other ones, etc. The agent will be able to discover new rules automatically and convert gradually to basically discover those new rules and have zero error. And again, um Joe Granja has been applying that successfully to add new liability automatically with him as a human checking that everything is relevant, of course, in some Spring Spring Security modules using the work that has been done on other modules and Spring Framework, etc. So, I think that's pretty cool because it was the main drawback of this new safety effort that it required initially quite a lot of work to annotate a code base because the rules are pretty nuance and it was a bit challenging. And now with an agentic loop, new way, and some careful skills that you can craft like that, you can automate that and just burn a few tokens and yeah.
Um we can do also detection of newness at run time. So, be aware that I have introduced a newness enum class in the org.springframework.core which basically models the free state I was mentioning at the beginning and specified for unannotated code, new label and non new.
And basically you have a few methods like give me the newness for this method return type or this parameter or this field. And that's basically kind of reflective API that will allow you to discover that at run time and it's automatically taking account G specify, uh Kotlin APIs and reflection and also at new label annotations.
And in practice we are using that for example for the request param support.
Basically when no no new liability is expressed by default the request param is mandatory. So, if you are not specifying it, an exception is thrown. But if you are annotating with at new label, basically it will be new and it will let you handle that. And we are using this uh newness class internally to do it, but you can also use newness on your own code. If you have some features where to generate some forms or whatever, you need to discover at run time the new liability of your annotated API with G specify, you can do that with that.
Okay, and uh last part is the evolution of the Java platform. So, uh G specify is cool, but it's still a bunch of annotation with specification that are created pragmatically by some enterprise.
What about getting Java platform supporting new liability like Kotlin does? Um the good news is that there is ongoing effort for that.
The first related effort is lazy constants. Lazy constants are a bit like final fields, but basically uh they provide a more flexible behavior for the initialization. Like you can initialize lazy constants after the constructor. Uh just you can initialize it one time and the content will not be new.
Uh and so, basically you can get the same benefits, performance optimization than final fields, but with a much more flexible approach. And for new liability that's very important to be able to express this this thing is going to be initialized a bit later, but then just one time it will be non new. And so, this is going to be uh uh supported by the >> [snorts] >> by the JDK.
But the most exciting feature is of course Project Valhalla. So, Project Valhalla we are talking about it for 15 years, very long time.
Not sure how many years, but very long time.
The the the most popular feature is value classes to introduce object that lack identity and you can do related optimization. And Kotlin has that for example. But in recent version of Project Valhalla roadmap, you can see that the second most important feature mentioned is new checking at both compile time and run time to manage the flow of new references through programs. That's pretty exciting. This is basically partially similar of what we are going to do on with G specify. But of course, if you are supporting that at JDK level, you can implement such support directly in Java C. You can do optimized check at run time. It will be much more much more powerful. And while G specify does not provide efficiency run time benefits, this efforts can do it because if a field is non new, you need one less bit to basically store it. So, you you can get memory alignment, everything is optimized, and this is why they are introducing it as part of Valhalla. In order to get full benefits of value classes in term of performance, you need to be sure that the related field is non new to get everything aligned and optimized.
And it's getting concrete. Like you can see in this Project Valhalla PR that basically they are modifying the JDK APIs. Uh they are adding this kind of exclamation mark to say this parameter is non new.
And so, uh since that expressed at Java platform level, you can remove the objects that require non new. You don't have to execute this this code. It will be more efficient. It will be checked both at compile time and at run time, but at run time it will be like super optimized intrinsics that will be like super efficient and this is also less noise in your API.
My hope is that they provide a way like at null mark from J specified to define the defaults because again 5% of your use case are nullable most of the time and so if we need to annotate everything with exclamation mark there will be a lot of exclamation mark in your code, right? So it's it's it's a matter of trade-off.
If they introduce a default basically you need to be context aware to know if you are in a package, a module or something that is basically in non-null by default mode.
Here Kotlin it's easier because they chose the right default but many years after. So let's see but it's it's exciting and you can basically provide direct matching between J specified annotation null mark code or non-null to this kind of thing. So basically this will take many years to come as in your Java version. It will require to bump the baseline to I'm not sure Java 20 33.
So quite aggressive baseline. So I think it's a safe bet to invest into J specify, clarify the semantics of your if you of your code and then when that will be ready I'm pretty sure there will be some kind of annotation processor that will translate J specified annotations to this kind of bytecode level J thing and and then everything is fine. And also you can see that for example the nullability of generic types is not not supported etc. So we expect that J specify will be much more complete than this support but will provide additional runtime benefits and dedicated syntax.
So thank you for your attention. I can answer to a few questions and after the talk you can come to get this I think I get I look older on this picture on maybe that's myself but not sure. But you can come and I have a few cards if you want to get them. Thank you.
Is there any question or yeah?
If we're using error prone for extra functionality I understand why we use that but if IDEs are checking nullability annotations do we still need error prone or or this was just an example of how to set up your project if we need extra features?
Yeah, so if I understand right your question you are already using error prone but your IDE is going to provide feedbacks on nullabilities. So do you need to use NullAway or check like that in addition?
>> is if you're not using error prone Oh, if you're not using error prone Yeah, if you are not using error prone I mean NullAway extension of error prone. I don't really care about over checks from error prone. You can use them or not. I have no opinion on that. But I have seen the difference of quality between I'm checking warnings into my IDE time to times and then be sure that everybody using Kotlin was broken and there was a lot of inconsistencies. So really if you are just building an application you can potentially annotate a few nullable use case here and there. If you are publishing a library or even within your company you you should really check with with NullAway the level of quality. It's not not the same at all. So yeah, it's I'm not really pushing everybody to basically it's quite a lot still some work. Maybe AI will make it easier but introducing null tool safety and checking everything in your project is quite some work. So you can just consume it but if you will begin to annotate I would really advise to do the full NullAway stuff and like I said maybe a trade-off is you are using NullAway with error prone but just on specific packages. You you it will by default with the configuration I shared only check packages annotated with null mark. So maybe begin by a more specific scope but yeah check with NullAway and error prone. That's Yeah, that's the same.
Yeah.
I have questions regarding some false positives and what do you think is there a possible suppression to the specific cases?
Yeah, so about the false positives that are detected by NullAway how can we handle that because there is suppress warning NullAway which is a bit generic.
So there is a specific variant which is for lazy initialization which is suppress warning NullAway.init which is able to specify that. Maybe more use case will be identified but we are within the J specified group we have two additional refinements we are working on. Potentially refining a defining a standardized suppress warning nullness or something like that and we are discussing potential way to express some variants for the reason why we have to do this kind of suppress warnings.
And also standardizing contracts like I was mentioning. So maybe via this kind of ongoing standardization effort we could identify some specific way to identify more specific reason for basically uh Yeah, to to basically not know why why we have to define to to to specify suppress warnings. In the meantime NullAway itself is evolving like currently there is a big effort to introduce very consistent nullability for all JDK APIs and maybe more advanced contract and various other bug fixes that are basically reducing the need for suppress warning NullAway. Like I remember when we we we first introduced introduced that in Spring Framework we had a lot of suppress warning NullAway because sometimes NullAway is not clever enough to analyze the code flow of your code and I think we have removed half of them and basically the NullAway author and the J specified working group they continue to refine some use case to reduce that that need. So I think we just need to get a bit more evolution on on that and get NullAway more clever and Yeah, okay.
I have one more What is your recommendation regarding J specify dependency?
Just because this is a library you have to add it to your build. Yeah. So what is the best way to do that?
Add it explicitly or using dependency from the framework?
Yeah, so how should you manage this J specify dependency? So I don't really have a strong opinion of should it be defined explicitly in your project or come through the transitive dependency on Spring but the important point is that I think it should be a transitive dependency of for example your library.
So in Spring Framework for example this is not a compile or optional dependency.
This is like a regular dependency that will be a transitive dependency. So if you are using Spring Boot, Spring Framework, whatever you will have basically J specify already as your dependencies because it's not optional. It's not compile only. It's like regular implementation or API I don't remember but dependency that will be used transitively by your project. So you don't need to add it explicitly but if you are not using Spring you should add J specify as a dependency and I recommend to make it like a transitive dependency. One of the reason is basically if you are just using an optional dependency or compile only when people are going to watch your source code there will be red annotations everywhere because J specify is not in the in the in the class path. When you are doing some runtime check with nullness thing or via reflection I think it's the best practice. I mean you can you can deal with that with bytecode manipulation etc. to detect it but I think it's just a good practice to consider J specify annotations as part of your API. I mean it's going to qualify the nullability of the types so it makes sense to use it as a transitive dependency that you don't have to hide.
Technically technically you can but I I would advise to to make that explicit.
Okay. Thank you and feel free to come to discuss after the talk. Cheers.
Related Videos
Agentforce NOW AMA: Build with React and Salesforce Multi-Framework
SalesforceDevs
490 views•2026-05-28
How agent o11y differs from traditional o11y — Phil Hetzel, Braintrust
aiDotEngineer
450 views•2026-05-28
WEB TECHNOLOGIES UNIT-2 | Degree 4th sem BCOM Computers web technologies unit-2 full explanation💯✅
LearnwithSahera
1K views•2026-05-29
More tests are always better? How to use AI to identify tests that bring little value
Alliance4Qualification
335 views•2026-05-29
Search Algorithms Explained in 60 Seconds! 🤖💨
samarthtuliofficial
218 views•2026-06-01
People of Game of Thrones using JavaScript DOM
AltCampus
296 views•2026-05-30
Introduction to Problem Solving Part - 1 | Lecture 1 | Intermediate DSA
ascensionix
107 views•2026-05-29
🚀 BCS613C Compiler Design | Module 1 to 5 Schema Evaluation 🔥 | VTU 6th Sem 💯 #VTU #bcs613c #exam
Pranavaa-y4y
104 views•2026-06-02











