Handling OutOfMemoryError in Java is a tricky and often contentious topic. This error suggests that the Java Virtual Machine (JVM) has insufficient memory and is unable to allocate any more resources. Unlike regular exceptions, OutOfMemoryError is an Error (not an Exception), meaning it typically signifies a serious problem and is not meant to be caught and handled like normal exceptions.
However, there are scenarios where you might want to catch
an OutOfMemoryError, primarily for logging, cleanup, or controlled shutdown.
Here’s a detailed explanation of when and how you might handle this error, and
why you might choose to do so.
Why Catch an OutOfMemoryError?
- Logging
and Monitoring: To log the error and gather diagnostics information
for debugging.
- Graceful
Degradation: To allow the application to perform some critical cleanup
operations or free up resources before terminating.
- Controlled
Shutdown: To shut down the application gracefully, ensuring that no
critical data is lost.
- Preventing
Application Crash: In some cases, particularly in large enterprise
applications, it's better to degrade functionality rather than crash
outright.
How to Handle OutOfMemoryError
Custom Exception Class for Handling
Here’s an example of how you can catch and handle OutOfMemoryError
in a controlled manner.
- Custom
Exception Class:
java
public class TailoredOutOfMemoryException extends Error { public TailoredOutOfMemoryException(String
message) { super(message); } } |
- Handling MemoryExceedanceHandler in Application:
java
public class MemoryExceedanceHandler { public static void main(String[] args) { try { // Carry out a task that demands high memory usage. simulateTailoredOutOfMemory(); } catch (OutOfMemoryError e) { // Handle TailoredOutOfMemoryException handleOutOfMemoryError(e); } } private static void simulateTailoredOutOfMemory() { // Example code to simulate TailoredOutOfMemoryException List<byte[]> memoryList = new ArrayList<>(); while (true) { memoryList.add(new byte[1024 * 1024]);
// Allocate 1MB memory at a time } } private static void handleTailoredOutOfMemoryError(OutOfMemoryError e) { // Capture the error (for practical applications, consider employing a logging framework). System.err.println("TailoredOutOfMemoryException caught: " + e.getMessage()); e.printStackTrace(); // Undertake the cleanup operations or release resources appropriately. // This can include tasks such as clearing caches and disconnecting connections cleanUpResources(); // Optionally, you can encapsulate the error and throw it again as a specific custom error. throw new TailoredOutOfMemoryException("Custom
handling of Tailored OutOfMemoryError"); } private static void cleanTailoredUpResources() { // Here, the logic responsible for cleanup is defined. System.out.println("Here, the logic responsible for cleanup is defined...."); } } |
Considerations and Best Practices
- Avoid
Frequent Memory Allocation: Ensure your application is not allocating
memory excessively or leaking memory.
- Use
JVM Options: Use JVM options to tune memory usage (e.g., -Xms and -Xmx
to set initial and maximum heap sizes).
- Monitor
Memory Usage: Use tools like VisualVM, JConsole, or other profiling
tools to monitor and analyze memory usage.
- Fail
Fast: In many cases, it's better to let the JVM handle the OutOfMemoryError
and fail fast rather than trying to catch it.
- Graceful
Degradation: If you catch OutOfMemoryError, ensure your application
can degrade gracefully without leaving the system in an unstable state.
Conclusion
Catching OutOfMemoryError is generally not recommended for
routine operations, but in certain scenarios, it can be useful for logging,
cleanup, and graceful shutdown. Always prioritize avoiding the error in the
first place through proper memory management and monitoring. If you must catch
it, ensure you handle it in a way that does not leave your application in an
inconsistent state.
How to Generate an OutOfMemoryError?
Generating an OutOfMemoryError in a Java application can be
done by intentionally consuming a large amount of memory until the JVM can no
longer allocate the necessary memory. Here’s a straightforward example that
illustrates how to do this:
Example Code
The following example continuously allocates memory in a
loop until the JVM runs out of memory and throws an OutOfMemoryError.
java
import
java.util.ArrayList; import
java.util.List; public class MemoryLimitSimulator { public static void main(String[] args) { List<byte[]> memoryList = new ArrayList<>(); try { while (true) { // Allocate 1MB memory resouce memoryList.add(new byte[1024 *
1024]); } } catch (OutOfMemoryError e) { System.err.println("OutOfMemoryError for low memory: " + e.getMessage()); e.printStackTrace(); } } } |
Explanation
- Memory
Allocation: The code continuously allocates 1MB of memory in each
iteration of the loop by adding a new byte array to a list.
- OutOfMemoryError
Catch Block: When the JVM can no longer allocate the requested memory,
it throws an OutOfMemoryError, which is caught in the catch block. The
catch block then prints an error message and the stack trace.
Running the Example
- Compile
the Code: Save the code to a file named OutOfMemorySimulator.java and
compile it using:
bash
javac
OutOfMemorySimulator.java |
- Run
the Program: Run the program with limited heap space to trigger the OutOfMemoryError
more quickly. For example, you can set the maximum heap size to 20MB using
the -Xmx JVM option:
bash
java -Xmx20m MemoryLimitSimulator |
Output
When you run the program, it will eventually print something
like this:
yaml
OutOfMemoryError
caught: Java heap space java.lang.OutOfMemoryError:
Java heap space at MemoryLimitSimulator.main(MemoryLimitSimulator.java:10) |
Considerations
- Resource
Cleanup: In a real application, ensure that you perform necessary
resource cleanup in the catch block.
- Heap
Size: Adjust the heap size using the -Xmx JVM option to control when
the OutOfMemoryError is triggered. Smaller values will cause the error to
be thrown more quickly.
- Impact
on System: Running such a program can significantly impact your
system’s performance. Ensure you run this in a controlled environment
where it won’t affect other applications.
Conclusion
Intentionally generating an OutOfMemoryError can be useful
for testing how your application handles low-memory conditions. The provided
example demonstrates a simple way to consume memory until the JVM throws an OutOfMemoryError.
Always use caution and perform such tests in an isolated environment to avoid
disrupting other applications.
Some other examples:
package
com.kartik.error; /** * *
@author Kartik Chandra Mandal * How
to handle run time exception in Java file */ public class
RunTimeMemoryErrorException { private static final int MEGA_BYTE_MEMORY =
(1024*1024); public static void runOutOfMemoryError()
throws Exception{ MemoryMXBean memoryBean =
ManagementFactory.getMemoryMXBean(); try { long data[] = new
long[1000000000]; } catch (Exception e) { throw new
Exception("Out of low memory error e"); }catch (OutOfMemoryError
e) {
MemoryUsage heapUsage = memoryBean.getHeapMemoryUsage();
long maxMemory = heapUsage.getMax() / MEGA_BYTE_MEMORY ;
long usedMemory = heapUsage.getUsed() / MEGA_BYTE_MEMORY ;
System.out.println( "Memory Use :" + usedMemory +
"M/" + maxMemory + "M"); throw new
Exception("Out of low memory error by Kartik"); } } public static void main(String[] args) { try { runOutOfMemoryError(); } catch (Exception e) { System.out.println(e.getMessage()); e.printStackTrace(); } } } |
Output
When you run the program, it will eventually print something
like this:
plaintext
Memory Use
:1M/882M Out of low memory
error by Kartik java.lang.Exception:
Out of low memory error by Kartik at com.kartik.error.RunTimeMemoryErrorException.runOutOfMemoryError(RunTimeMemoryErrorException.java:21) at
com.kartik.error.RunTimeMemoryErrorException.main(RunTimeMemoryErrorException.java:28) |
For More DSA Related information, visit
Ø
Bench
mark of compiler using Ackerman function
Ø
To
check if the rows of a matrix are circularly identical in Java
Ø
Frequency
Weaving Logic & Spiral Printing of a Rectangle
Ø
Zig Zag
Matrix print multiple way
Ø
Gready
Algorithm’s or knapsack algorithms
Ø
understanding
recursive method for binary tree
Ø
Dynamic
Programming: Max Square Sub-matrix of 1s in a Matrix
Ø
Previous and
Next Date Palindrome
Ø
Karatsuba's
Algorithm for multiplying two large numbers
Ø
Multiplication
In different Way
Ø
Time
Analysis for Congested Routes Using Shortest Path Algorithms
Ø
Sorting
Of a list multiple attribute wise two technique
Ø
Seat
Arrangement in Sorting Order Like 1A-1E, 3C-3G etc
For More Java Related information, visit
Ø
Streams
Lambdas Collectors and Functional Interfaces in Java 8
Ø
Java
8 support static method or default method or both in the interface
Ø
Serialization
understanding
Ø
Garbage
Collection Under Standing
Ø
How
work Garbage Collection in Java
Ø
Under
Standing Of Mutable and Immutable Class
For Other information, visit
Ø
How
to get the neighbor of binary tree
Ø OWASP
(Open Web Application Security Project)
Ø Mastering
Debounce, Throttle, Rate Limit & Backoff in Java
Ø How
to draw sequence diagram and other diagrams using plantuml
Ø
Molecular
weight of chemistry in Java code
Ø
String
to xml or html Beautifier
Ø
Key
Components of Apache Kafka for Scalable Messaging
Ø
Build
a Video Stream Microservice with Kafka & REST API in Java
Ø
Kafka
general questions and answers
Ø
How
to convert XML to Object and Object to XML
Ø
To
securely obtain employee information utilizing TLS 1.3 or TLS 1.2
Ø
Convert
Floating-Point Values from SQL Server to Oracle in Java
Ø Design pattern
Ø Mastering Design Patterns Practical Implementation Tips
throwable class hierarchy |
1 Comments