Why is "java.lang.OutOfMemoryError: Java heap space" not caught? - java

I have a thread in a Java web application that causes a java.lang.OutOfMemoryError: Java heap space exception, but the try/catch block does not catch the error.
Sample code:
private void doSomeWork()
{
try
{
processData(); //Causes OutOfMemoryError
System.out.println("This line does not execute");
}
catch (Exception e)
{
System.out.println("Exception. This line does not execute.");
//Log error
}
finally
{
System.out.println("finally. This line does execute");
System.out.println("Thread name: " + Thread.currentThread().getName());
}
}
Output:
finally. This line does execute
Thread name: _Worker-8
Exception in thread "_Worker-8" java.lang.OutOfMemoryError: Java heap space
...
Background:
I recently took over this Java project and I'm trying to get up to speed with Java and this project. I'm a C# developer, so I'm not yet familiar with this project or Java.
I know I can fix the error using the -Xmx setting, but I'm interested in catching this error so I can log it. The error is not showing up in any of the logs files, and the output is being shown in the console in debug mode in Eclipse.

Because OutOfMemoryError is an Error, not an Exception. Since OutOfMemoryError isn't a subclass of Exception, the catch (Exception e) doesn't apply.
OutOfMemoryError does extend Throwable, however, so you should be able to catch it. Here's a SO discussion on when (if ever) you should catch Errors. Generally, since you can't do anything about it, the recommendation is to not bother catching Errors in production code. But given a special case where you're trying to debug what's going on, it might be helpful.

java.lang.OutOfMemoryError doesn't extends java.lang.Exception so it's not an Exception. OutOfMemoryError extends java.lang.Error. If you want to catch Error try this:
private void doSomeWork()
{
try
{
processData(); //Causes OutOfMemoryError
System.out.println("This line does not execute");
}
catch (Error e)
{
System.out.println("Exception. This line does not execute.");
//Log error
}
finally
{
System.out.println("finally. This line does execute");
System.out.println("Thread name: " + Thread.currentThread().getName());
}
}
Note: Exception and Error extends Throwable so you you can also use Throwable to catch both.
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Throwable.html

An "~Error" is not an "~Exception".
You have to catch "Error" or "Throwable"

OutOfMemoryError extends VirtualMachineError while Exception extends Throwable directly. So it is not being caught as per Java specs. IF you're looking to catch all exceptions, add catch (Throwable e) to the clause and you'll have it.

What I will usually do is add an 'UncaughtExceptionHandler' to a Thread so if anything leaks by you at least have a chance to log the issue and maybe do some cleanup.

Related

Sonarcloud alerts "not enough arguments" when logging exceptions using SLF4J

I manage an open source project in Java and have about 20 places in my code where I log exceptions using the following pattern (slf4j version 1.7.30)
private static final Logger logger = LoggerFactory.getLogger();
...
try {
interfaces = NetworkInterface.getNetworkInterfaces();
} catch (SocketException ex) {
logger.error("Socket exception when retrieving interfaces: {}", ex);
}
or similarly
try {
// stuff
} catch (IOException ioe) {
logger.error("Server error: {}", ioe);
}
Starting today, the SonarCloud automated code quality review has begun flagging these with rule java:S2275 (Printf-style format strings should not lead to unexpected behavior at runtime) with the specific message "Not enough arguments."
EDIT: Of note, this appears to consistently happen when an Exception is the final argument. The following pattern does not flag:
try {
// Server connection code
} catch (IOException e) {
logger.error("Server Connection error: {}", e.getMessage());
}
A review of this other StackOverflow question indicates that perhaps an extra argument for the exception is optional and would result in different behavior, so I'm not clear how that would apply here and why it would suddenly change.
Is there something I can/should do to better translate these exceptions to log messages (e.g., use getMessage() on all of them instead of relying on the automated toString() parsing), or is this a false positive?
(Sonar's list of my 20 issues linked here.)
This is pure conjecture, but each of the issues points to a log line that can be generalized as:
LOG.something(format, custom_arguments, exception)
where format has {} appearing count(custom_arguments) + 1 (the 1 reserved for exception).
As you've seen the linked answer, exceptions get treated specially by slf4j, so it's possible that due to some reason SonarCloud is doing the same thing. Unfortunately there's no documentation.
The "fix" would be to remove the final {} intended for the exception, so e.g.
LOG.error("boom: {}", e);
LOG.error("boom2 {}: {}", something, e);
becomes
// exceptions handled in a special way
LOG.error("boom", e);
LOG.error("boom2 {}", something, e);

What is a IOException, and how do I fix it?

What are IO Exceptions (java.io.IOException) and what causes them?
What methods/tools can be used to determine the cause so that you stop the exception from causing premature termination? What does this mean, and what can I do to fix this exception?
Java IOExceptions are Input/Output exceptions (I/O), and they occur whenever an input or output operation is failed or interpreted. For example, if you are trying to read in a file that does not exist, Java would throw an I/O exception.
When writing code that might throw an I/O exception, try writing the code in a try-catch block. You can read more about them here: https://docs.oracle.com/javase/tutorial/essential/exceptions/catch.html
Your catch block should look something like this:
try {
//do something
}catch(FileNotFoundException ex){
System.err.print("ERROR: File containing _______ information not found:\n");
ex.printStackTrace();
System.exit(1);
}
Here you go https://docs.oracle.com/javase/7/docs/api/java/io/IOException.html
IOException is thrown when an error occurred during an input-output operation. That can be reading/writing to a file, a stream (of any type), a network connection, connection with a queue, a database etc, pretty much anything that has to do with data transfer from your software to an external medium.
In order to fix it, you would want to see the stack trace of your exception or at least the message, to see exactly where the exception is thrown and why.
try {
methodThrowingIOException();
} catch (IOException e) {
System.out.println(e.getMessage()); //if you're using a logger, you can use that instead to print.
//e.printStackTrace(); //or print the full stack.
}
The error message that will be printed will likely show you what the issue is. If you add the error message here, I'll be able to give you more info on how to fix that specific IOException. Without that, no one can really give you a complete answer.
It is a very generic exception that a lot IO operation can cause. A best way is to read the Stack Trace. To continue the execution you can use the try-catch block to bypass the exception, but as you mention you should investigate into the cause.
To print the stack trace:
try {
// IO operation that could cause an exception
} catch (Exception ex) {
ex.printStackTrace();
}
IOException is usually a case in which the user inputs improper data into the program. This could be data types that the program can't handle or the name of a file that doesn't exist. When this happens, an exception (IOException) occurs telling the compiler that invalid input or invalid output has occurred.
Like others have said, you can use a try-catch statement to stop a premature termination.
try {
// Body of code
} catch (IOException e) {
e.printStackTrace();
}

Java JSoup Exception ignores try catch?

I've got a program that uses JSoup to connect to and parse data from a website. When the website fails to connect after the 10 second timeout I've given it, the JSoup method throws an UncheckedIOException. This may contain an IOException like "SSL Peer shut down unexpectedly" or "timed out" which are IOExceptions I've dealt with in the past. It's weird because it wrapped in a try catch:
Document document;
try {
document = Jsoup.connect("https://www.website.com").timeout(10000).maxBodySize(0).get();
} catch (Exception e) {
return false;
}
Elements elements = document.select("tr");
for (Element e : elements) {
System.out.println(e.text());
}
return true;
I've done all sorts of workarounds like wrapping the method in a try catch, making the method throw exception and handling it higher up, and the above where I've isolated the line causing the issue and wrapped only that in a try catch. I've tried catching Exception, IOException, UncheckedIOException, etc but it all eventually still causes the whole application to crash due to the error seeping through somehow.
I've never encountered something like this. How is it that a try catch can't deal with the error? Is it the way JSoup has set up their error system? This can't be right, can it? I'm using JSoup 1.11.2 if that helps, downloaded from https://jsoup.org/download.
The issue was that an Error was not being caught because I was trying to catch an Exception. JSoup throws an Object that extends Error, not Exception, so when I did
try {
} catch (Exception e) {}
I should have done
try {
} catch (Error e) {}

is it possible to catch a fatal xml exception in java?

When i do DOM XML Schema validation i get this error when there is a syntax error in my deliberately-incorrect test file.
[Fatal Error] :10:3: The element type "gizmos" must be terminated by the matching end-tag "</gizmos>".
However, I want to catch this so that it wouldn't give the red fatal error warning, instead a message that says something like "your xml is not valid." Is it possible?
Thanks,
I believe you can catch Throwable to handle your scenario
try{
....
....
....
}catch (Exception e) {
e.printStackTrace();
}catch (Throwable t) {
t.printStackTrace();
}
Errors can not be catched, only Exceptions can be catched.
According to Java Docs :
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.
A method is not required to declare in its throws clause any subclasses of Error that might be thrown during the execution of the method but not caught, since these errors are abnormal conditions that should never occur. That is, Error and its subclasses are regarded as unchecked exceptions for the purposes of compile-time checking of exceptions.
But still, you can catch Throwable to catch any error. That is not recommended though.
catch (Throwable e) {
//e.printStackTrace();
}
You can catch a Throwable (Error extends Throwable):
try {
//...
} catch(Throwable e) {
//...
}
Please note that it's often recommended not to do it. You can read more about it here: When to catch java.lang.Error?.
If you are using the JAXP validation API then you can nominate an ErrorHandler to receive notification of errors. With this you can change what messages are displayed and where they are displayed.

Java thread stops with no Exception

When I use 4 threads for my program there is usually no problems, but today I increased it to 8 and I noticed 1-3 threads stop working without throwing any exceptions. Is there anyway to find out why they are stopping? is there anyway to make the thread restart?
This is how the structure of my thread is
public void run()
{
Main.logger.info(threadName + ": New Thread started (inside run)");
while (true)
{
try
{
//all my code
//all my code
//all my code
}
catch(Exception e)
{
Main.logger.error("Exception: " + e);
try
{
Thread.sleep(10000);
}
catch (InterruptedException e1)
{
e1.printStackTrace();
}
}
finally
{
try
{
webClient.closeAllWindows();
Thread.sleep(3000);
Main.logger.info(threadName + ": Closed browser!");
}
catch (Exception e)
{
Main.logger.error("Exception: " + e);
}
}
}// end while
}
Regards!
Note that an Error is not an Exception; it's a Throwable.
So, if you catch Exception, Errors will still get through:
private void m() {
try {
m(); // recursively calling m() will throw a StackOverflowError
} catch (Exception e) {
// this block won't get executed,
// because StackOverflowError is not an Exception!
}
}
to catch "everything", change your code to this:
try {
...
} catch (Throwable e) {
// this block will execute when anything "bad" happens
}
Note that there might be little you can do if an Error occurs. Excerpt from javadoc for Error:
An Error is a subclass of Throwable that indicates serious problems that a reasonable application should not try to catch. Most such errors are abnormal conditions. The ThreadDeath error, though a "normal" condition, is also a subclass of Error because most applications should not try to catch it.
Is there anyway to find out why they are stopping?
That's a bit tricky.
A Java thread can terminate for two reasons:
it can return from its run() method,
it can terminate due to an exception being thrown and not caught on the thread's stack.
You can detect the latter case by using an "UncaughtExceptionHandler" for the thread, but the former case can't be positively detected unless you modify your thread's run() method to log the event ... or something like that.
I guess, the other way to figure out what is going on would be to attach a debugger to the JVM and get it to report the uncaught exception to you.
(I suspect that the reason you are not seeing any exceptions is that your threads' run methods are not catching / logging all exceptions, AND they don't have an uncaught exception handler.)
is there anyway to make the thread restart?
No. There is no way to restart a Thread that has terminated.
If you are running from the command line, you can have dump states of all threads to the console. On windows you do this by hitting Ctrl+Break, under linux, by sending the QUIT signal to the process with 'kill'.
Please refer to An Introduction to Java Stack Traces
Sending a signal to the Java Virtual Machine On UNIX platforms you can
send a signal to a program by using the kill command. This is the quit
signal, which is handled by the JVM. For example, on Solaris you can
use the command kill -QUIT process_id, where process_id is the process
number of your Java program.
Alternatively you can enter the key sequence \ in the window
where the Java program was started. Sending this signal instructs a
signal handler in the JVM, to recursively print out all the
information on the threads and monitors inside the JVM.
To generate a stack trace on Windows 95, or Windows NT platforms,
enter the key sequence in the window where the Java
program is running, or click the Close button on the window.
Thread priority on one of them could be too high, try setting them the same level through?
Deadlocking is possible if there is any control on each and other between them.

Categories

Resources