Home DEVELOPER Null problem: Better null checking in Java with JSpecify

Null problem: Better null checking in Java with JSpecify

0


Just a year ago I wrote about null checking in Java. It still makes sense to include parameters of methods and constructors with annotations regarding behavior null (eg @NonNull). However, support has gotten much better now, as version 1.0 was recently released JSpecify has appeared. I would like to use this for updates on the topic.

Advertisement





Hendrik Ebbers (@hendrikEbbers) is a Java Champion, member of the JCP Expert Group and has been recognized as a JavaOne Rockstar Speaker several times. With his own company Open Elements, Hendrik is currently helping to design the Hedera Hashgraph and make its services available to the public. Hendrik is a co-founder of JUG Dortmund and Cyberland and gives lectures and workshops on Java worldwide. His book “Mastering JavaFX 8 Controls” was published by Oracle Press in 2014. Hendrik actively works on open source projects such as JakartaEE or Eclipse Adoptium. Hendrik is a member of the AdoptOpenJDK TSC and the Eclipse Adoptium WG.

JetBrains tools with new UI, native TypeScript, and multiple AI assistants

JSpecify is a Open Source Projectin which previous providers of void-handling annotations have finally come together to define a usable standard. These include Google, JetBrains, Meta, Microsoft and Oracle. JSpecify is a full-fledged module in the Java module system, has no dependencies of its own and, with only four annotations, provides everything you need to handle a modern Java project. null to specify parameters. Example code using annotations might look like this:

static @Nullable String emptyToNull(@NonNull String x) {
    return x.isEmpty() ? null : x;
}

static @NonNull String nullToEmpty(@Nullable String x) {
    return x == null ? "" : x;
}

More code examples can be found here JSpecify User Guide,

However, simply adding the JSpecify annotation has little effect. The compiler continues to translate that code null with one @NonNull-Annotated parameters, and the translated code does not automatically throw exceptions at runtime.

Among other things, the benefits of annotations can be seen in the interaction with the development environment. IntelliJ can recognize annotations and display warnings or errors for code that violates annotations. If you want to be safe and not allow code with such problems at all, you can use additional tools. Open source tools developed by Uber Zero away You can check for these annotations at build time and generate errors if the annotation definition is not met. If you add the whole thing to your Gradle or Maven build, an error will be automatically generated when compiling:

error: (NullAway) passing @Nullable parameter 'null' where @NonNull is required
   myMethod(null);
          ^

With this toolchain you can make your code more robust NullPointerExceptionAvoid runtime.

Now you don’t have to worry about it NullPointerExceptions Creating? Unfortunately it’s not that easy. These solutions can only check your own code. If you have dependencies that do not use such annotations, you cannot know if you can use it as a parameter null can be passed and what behavior it triggers. So it is still important to set variables in different places null to check.

Anyone who develops libraries or code that is called by other projects cannot ensure that users follow the defined rules @NonNull There are actually no annotated parameters null Hand over. Therefore, it is important to always perform null checks when leaving context of your code – whether on your dependencies or on public APIs.

This is from OpenJDK java.util.Objects.requireNonNull(obj, message) remains the method of choice. To always create meaningful exceptions, you must use the variant with the message parameter, otherwise the system… NullPointerException Without messages. The whole thing looks like this for the public API:

public void setName(@NonNull String name) {
   this.name = Objects.requireNonNull(name, “name must not be null”);
}

Anyone who works in a performance-critical environment should avoid using their own methods for checking. The JIT compiler handles it Objects.requireNonNull(...) Through annotation @ForceInline Specifically, it encapsulates all calls to the method directly into the calling method (inline) to optimize performance and stack size.

It took a long time for the Java community to get to where it is today and have a clean and useful library with zero handling annotations. What jsr305 Which was started in 2006 and unfortunately dropped again soon after, after many problems with different types of annotations and implementations, before it could evolve into a de facto standard like SLF4J (Simple Logging Facade for Java).

JSpecify is clearly taking the right approach here. It would be great if a tool like NullAway became established and, with its ease of use and best practices, enabled almost every project to do better. null to deal with. If you haven’t used annotations and tools like NullAway yet, you should give them a try. Now is the perfect time to start.

Comment: At the time of writing this post, OpenJDK is in parallel A new JEP Improved native support has been announced. Since the features discussed in the JEP will still take some time to find their way into the LTS version of OpenJDK, the resources and tools described here remain an obvious recommendation. However, the JEP provides enough aspects to take a closer look at it in a timely article.


(RME)

Mastering Microservices: Faster, More Flexible, More Scalable, and More Secure!

NO COMMENTS

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Exit mobile version