eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (cat=Spring Boot)
announcement - icon

Refactor Java code safely — and automatically — with OpenRewrite.

Refactoring big codebases by hand is slow, risky, and easy to put off. That’s where OpenRewrite comes in. The open-source framework for large-scale, automated code transformations helps teams modernize safely and consistently.

Each month, the creators and maintainers of OpenRewrite at Moderne run live, hands-on training sessions — one for newcomers and one for experienced users. You’ll see how recipes work, how to apply them across projects, and how to modernize code with confidence.

Join the next session, bring your questions, and learn how to automate the kind of work that usually eats your sprint time.

Course – LJB – NPI EA (cat = Core Java)
announcement - icon

Code your way through and build up a solid, practical foundation of Java:

>> Learn Java Basics

Partner – LambdaTest – NPI EA (cat= Testing)
announcement - icon

Distributed systems often come with complex challenges such as service-to-service communication, state management, asynchronous messaging, security, and more.

Dapr (Distributed Application Runtime) provides a set of APIs and building blocks to address these challenges, abstracting away infrastructure so we can focus on business logic.

In this tutorial, we'll focus on Dapr's pub/sub API for message brokering. Using its Spring Boot integration, we'll simplify the creation of a loosely coupled, portable, and easily testable pub/sub messaging system:

>> Flexible Pub/Sub Messaging With Spring Boot and Dapr

1. Overview

In this short tutorial, we’ll look at the possibility of destroying objects in Java.

2. Destructor in Java

Every time we create an object, Java automatically allocates the memory on the heap. Similarly, whenever an object is no longer needed, the memory will automatically be deallocated.

In languages like C, when we finish using an object in memory, we have to deallocate it manually. Unfortunately, Java doesn’t support manual memory deallocation. Moreover, one of the features of the Java programming language is taking care of object destruction by itself – using a technique called garbage collection.

3. Garbage Collection

Garbage collection removes unused objects from memory on the heap. It helps prevent memory leaks. Simply put, when there are no more references to the specific object and the object is no longer accessible, the garbage collector marks this object as unreachable and reclaims its space.

Failure to handle garbage collection properly can cause performance problems, and eventually, it causes an application to run out of memory.

An object can be garbage collected when it reaches a state of no longer being accessible in the program. An object is no longer reachable when one of two situations occurs:

  • The object doesn’t have any references pointing to it
  • All references to the object have gone out of scope

Java includes the System.gc() method to help support garbage collection. By calling this method, we can suggest to the JVM to run the garbage collector. However, we cannot guarantee the JVM will actually call it. The JVM is free to ignore the request.

4. Finalizer

The Object class provides the finalize() method. Before the garbage collector removes an object from memory, it’ll call the finalize() method. The method can run zero or one time. However, it cannot run twice for the same object.

The finalize() method defined inside the Object class doesn’t perform any special action.

The main goal of the finalizer is to release resources used by the object before its removal from the memory. For instance, we can override the method to close the database connections or other resources.

Let’s create a class that contains the BufferedReader instance variable:

class Resource {

    final BufferedReader reader;

    public Resource(String filename) throws FileNotFoundException {
        reader = new BufferedReader(new FileReader(filename));
    }

    public long getLineNumber() {
        return reader.lines().count();
    }
}
In our example, we didn’t close our resources. We can close them inside the finalize() method:
@Override
protected void finalize() {
    try {
        reader.close();
    } catch (IOException e) {
        // ...
    }
}

When JVM calls the finalize() method, the BufferedReader resource will be released. The exceptions thrown by the finalize() method will stop the object finalization.

However, since Java 9, the finalize() method has become deprecated. Using finalize() method can be confusing and hard to use properly.

If we want to release resources held by an object, we should consider implementing the AutoCloseable interface instead. Classes like Cleaner and PhantomReference provide a more flexible way to manage resources once an object becomes unreachable.

4.1. Implementing AutoCloseable

The AutoCloseable interface provides the close() method, which will be executed automatically when exiting a try-with-resources block. Inside this method, we can close resources used by an object.

Let’s modify our example class to implement the AutoCloseable interface:

class Resource implements AutoCloseable {

    final BufferedReader reader;

    public Resource(String filename) throws FileNotFoundException {
        reader = new BufferedReader(new FileReader(filename));
    }

    public long getLineNumber() {
        return reader.lines().count();
    }

    @Override
    public void close() throws Exception {
        reader.close();
    }
}

We can use the close() method to close our resources instead of using the finalize() method.

4.2. Cleaner Class

We can use the Cleaner class if we want to perform specific actions when an object becomes phantom reachable. In other words, when an object becomes finalized and its memory is ready to be deallocated.

Now, let’s see how to use the Cleaner class. Firstly, let’s define Cleaner:

Cleaner cleaner = Cleaner.create();

Next, we’ll create a class that contains a cleaner reference:

class Order implements AutoCloseable {

    private final Cleaner cleaner;

    public Order(Cleaner cleaner) {
        this.cleaner = cleaner;
    }
}

Secondly, we’ll define a static inner class that implements Runnable inside the Order class:

static class CleaningAction implements Runnable {

    private final int id;

    public CleaningAction(int id) {
        this.id = id;
    }

    @Override
    public void run() {
        System.out.printf("Object with id %s is garbage collected. %n", id);
    }
}

Instances of our inner class will represent cleaning actions. We should register each cleaning action in order for them to run after an object becomes phantom reachable.

We should consider not using a lambda for the cleaning action. By using a lambda, we could easily capture the object reference, preventing an object from becoming phantom reachable. Using a static nested class, as above, will avoid keeping the object reference.

Let’s add the Cleanable instance variable inside the Order class:

private Cleaner.Cleanable cleanable;

The Cleanable instance represents the cleaning object that contains the cleaning action.

Next, let’s create a method that will register the cleaning action:

public void register(Product product, int id) {
    this.cleanable = cleaner.register(product, new CleaningAction(id));
}

Finally, let’s implement the close() method:

public void close() {
    cleanable.clean();
}

The clean() method unregisters the cleanable and invokes registered cleaning actions. This method will be called at most once regardless of the number of calls to clean.

When we use our CleaningExample instance inside a try-with-resources block, the close() method calls the cleaning action:

final Cleaner cleaner = Cleaner.create();
try (Order order = new Order(cleaner)) {
    for (int i = 0; i < 10; i++) {
        order.register(new Product(i), i);
    }
} catch (Exception e) {
    System.err.println("Error: " + e);
}

In other cases, the cleaner will call the clean() method when an instance becomes phantom reachable.

Additionally, the behavior of cleaners during the System.exit() is implementation-specific. Java provides no guarantees whether cleaning actions will be invoked or not.

5. Conclusion

In this short tutorial, we looked at the possibility of object destruction in Java. To sum up, Java doesn’t support manual object destruction. However, we can use finalize() or Cleaner to free up the resources held by an object.
The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Partner – Moderne – NPI EA (tag=Refactoring)
announcement - icon

Modern Java teams move fast — but codebases don’t always keep up. Frameworks change, dependencies drift, and tech debt builds until it starts to drag on delivery. OpenRewrite was built to fix that: an open-source refactoring engine that automates repetitive code changes while keeping developer intent intact.

The monthly training series, led by the creators and maintainers of OpenRewrite at Moderne, walks through real-world migrations and modernization patterns. Whether you’re new to recipes or ready to write your own, you’ll learn practical ways to refactor safely and at scale.

If you’ve ever wished refactoring felt as natural — and as fast — as writing code, this is a good place to start.

eBook Jackson – NPI EA – 3 (cat = Jackson)