DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Java and Low Latency
  • Analyzing “java.lang.OutOfMemoryError: Failed to create a thread” Error
  • SRE Best Practices for Java Applications
  • How Java Servlets Work: The Backbone of Java Web Apps

Trending

  • Java’s Next Act: Native Speed for a Cloud-Native World
  • Google Cloud Document AI Basics
  • Unlocking AI Coding Assistants Part 4: Generate Spring Boot Application
  • Breaking Bottlenecks: Applying the Theory of Constraints to Software Development
  1. DZone
  2. Coding
  3. Java
  4. Fixing OutOfMemoryErrors in Java Applications

Fixing OutOfMemoryErrors in Java Applications

In this guide, learn how to fix OutOfMemory errors in your Java programs with practical strategies from an experienced programmer.

By 
Pratik Dwivedi user avatar
Pratik Dwivedi
·
Apr. 04, 25 · Tutorial
Likes (4)
Comment
Save
Tweet
Share
7.5K Views

Join the DZone community and get the full member experience.

Join For Free

In one of my earlier posts, we discussed how to best find memory leaks and the reasons behind them. It's best to use a focused and modern tool like HeapHero to detect OutOfMemory errors and many other performance bottlenecks, as it can pinpoint the real culprits and suggest ways to optimize the usage of computing resources.   

Objects of byte[], String, int[]


Above, you can see that there are a few thousand objects of byte[], String, int[], etc.  

Let's discuss some ways of fixing OutOfMemoryErrors in Java. You can see which fixes are applicable in your scenario/code and apply them to save memory and run your programs better. Some of the ways discussed below may seem trivial to you, but remember that a few small corrections may add up to a big gain.

1. Use ByteBuffer from java.nio 

Instead of allocating large byte arrays that may be underutilized, it allows direct memory allocation (ByteBuffer.allocateDirect(size)) to reduce GC pressure and avoid unnecessary heap allocations.

If you are dealing with dynamically growing byte arrays, avoid starting with an unnecessarily large array.  

Java
 
ByteBuffer buffer = ByteBuffer.allocateDirect(1024); // Allocates 1KB in off-heap memory


For example, instead of:

Java
 
ByteArrayOutputStream baos = new ByteArrayOutputStream(10000);// Too large  


Let Java handle the resizing when needed because JVMs and JREs are continuously improved to consume minimal resources and manage their resource cycle well.

Java
 
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // Starts small and grows as needed

Or provide a small initial size if you know the minimum required length beforehand.  
Java
 
ByteArrayOutputStream baos = new ByteArrayOutputStream(2048); // Starts small and grows as needed


2. Use Streams to Process Data in Chunks

Instead of reading an entire file into memory using a huge byte array,

For example, don’t use:

Java
 
byte[] data = Files.readAllBytes(Path.of("myLargeFile.txt")); // Loads entire file into memory


Instead, try this:

Java
 
try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream("myLargeFile.txt"));
ByteArrayOutputStream baos = new ByteArrayOutputStream()) {

byte[] buffer = new byte[2048]; // Read in smaller chunks
int bytesRead;
while ((bytesRead = bis.read(buffer)) != -1) {
baos.write(buffer, 0, bytesRead);
}
byte[] data = baos.toByteArray();
}


3. Using the New MemorySegment Interface in Java 21

You can access off-heap or on-heap memory with the Foreign Function and Memory (FFM) API efficiently. It introduces the concept of an Arena. You use an Arena to allocate a memory segment and control the lifecycle of native memory segments.

SegmentAllocator from Project Panama (Java 21) allows better control over memory allocation.

Instead of large heap-based arrays, allocate memory using MemorySegment, which reduces garbage collection overhead.

When you use the try-with-resources, the Arena will be closed as soon as the try block ends, all memory segments associated with its scope are invalidated, and the memory regions backing them are deallocated.

For example:

Java
 
import java.lang.foreign.*;

String s = "My LARGE ......... LARGE string";
try (Arena arena = Arena.ofConfined()) {

// Allocate off-heap memory
MemorySegment nativeText = arena.allocateUtf8String(s);

// Access off-heap memory
for (int i = 0; i < s.length(); i++ ) {
System.out.print((char)nativeText.get(ValueLayout.JAVA_BYTE, i));
}
} // Off-heap memory is deallocated


4. Use Singleton Objects Wherever Possible

Some utility classes need not be instantiated per request; there can just be a single static instance for the whole application/session.

For example, Unmarshallers and Marshallers. Unmarshallers are a part of JAXB specification. They are used to convert XML data into Java objects to its XML representations. Similarly, Marshallers are used to convert Java objects into XML representations. These help in processing XML data in Java programs by mapping XML elements and attributes to Java fields and properties, using Java annotations.

If you look closely into the JAXBContext class, you will see that it has static methods
createUnmarshaller() / createMarshaller() methods, which is a clear indication that these could be better handled as a single static instance for the whole application/session.

5. Use Singleton Scope In Your Spring-Based Applications

This way, the container creates a single instance of that bean for the whole application to share, wherever possible, keeping your business logic intact.

If coding a web application, remember that the @application scope creates the bean instance for the lifecycle of a ServletContext, the @request scope creates a bean instance for a single HTTP request, while the session scope creates a bean instance for a particular HTTP session.

Java
 
@Bean
@Scope("singleton")
public SomeService someService() {
return new SomeService();
}


6. Use Faster and Memory-Efficient Alternatives to Popular Collections

Use Collections.singletonMap and Collections.singletonList (for Small Collections)

For example, if you only need a single key-value pair or item, avoid using a full HashMap or ArrayList, which have overhead.

Use ArrayDeque Instead of LinkedList 

LinkedList has high memory overhead due to storing node pointers (next/prev references). Instead, use ArrayDeque, which is faster and memory-efficient.

Java
 
import java.util.ArrayDeque;

ArrayDeque<Integer> deque = new ArrayDeque<Integer>();
deque.add(22);
deque.removeFirst();


Use Map.of() and List.of() (Immutable Collections)

If you don't need to modify a collection, use immutable collections, which are compact and optimized.  

Java
 
Map<String, Integer> map = Map.of("A", 1, "B", 2);
List<String> list = List.of("X", "Y", "Z");

Use WeakHashMap for Caching

If you store temporary data in a HashMap, it may never get garbage collected, so use WeakHashMap, which automatically removes entries when keys are no longer referenced.

7. Close Objects as Soon as Their Utility Finishes   

Unclosed network sockets, I/O streams, database connections, and database/network objects keep using memory and CPU resources, adding to the running cost of the application.

We have discussed some time-tested ways of dealing with OutOfMemory errors in Java.

Your comments are welcome.

applications Java (programming language) Memory (storage engine)

Opinions expressed by DZone contributors are their own.

Related

  • Java and Low Latency
  • Analyzing “java.lang.OutOfMemoryError: Failed to create a thread” Error
  • SRE Best Practices for Java Applications
  • How Java Servlets Work: The Backbone of Java Web Apps

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

ABOUT US

  • About DZone
  • Support and feedback
  • Community research
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 100
  • Nashville, TN 37211
  • [email protected]

Let's be friends: