Java Exception Handling – J041

by Jan 5, 2016




DeegeU Java Course

The “Java Exception Handling” video is part of a larger free online class called “Free Java Course Online”. You can find more information about this class on “Free Java Course Online” syllabus.

Transcript – Java Exception Handling?

In any computer program, bad things can happen despite our awesome code. Bad things can be errors like trying to access an element in array that doesn’t exist. Or dividing a number by zero. These failure events are called Java exceptions.

An exception in Java is an unexpected event that happens and the program cannot continue normal behavior until the problem is addressed. These exception events are something that shouldn’t, but in some rare cases, do happen. When an exception does happen, we say the exception is thrown.

We can also provide code to run if an exception happens. This is called catching the exception. When we catch a thrown exception, we’re telling Java our catch block code makes every thing better and handles the problem gracefully. Catching exceptions gives our program a chance to recover from a problem, and continue normal execution.

exceptions-slides.006

All exceptions are represented with a class that are subtypes of the java.lang.Exception class. Exceptions are also subtypes of Throwable. Throwable is a catch-all class for all types of errors and includes the Error class. The Error class represents something that happens which we can’t do anything about. An example is the JVM is out of memory. In this video, we’re looking at exceptions only. Not the errors.

There are two types of exceptions. runtime exceptions and checked exceptions. runtime exceptions are exceptions that we should have prevented. We should never use a variable before it’s assigned, so we should never get a NullPointerException. We should iterate over arrays, so we should never get an ArrayIndexOutOfBoundsException. These are problems we should prevent using solid programming practices. Java will not force us to provide code to run if a runtime exception is thrown. Instead, the program will likely crash.

Checked exceptions are different. Java forces us to deal with these exceptional conditions. These are unlikely things that could happen in our application, no matter what we do. An example is FileNotFoundException. We could write everything perfectly, but someone might delete the file when we’re not looking. Java asks us to provide code to catch this exception when it’s thrown. We’ll cover how to catch exceptions soon.

For now, lets look at exceptions and how we trace them back to the problem. Let’s create an array with three numbers but try to print out four. This creates the runtime exception java.lang.ArrayIndexOutOfBoundsException. In this code, we’re forcing the error as an example. We know this isn’t how we should iterate over an array.

public static void main(String args[]) {
    int[] array = {3, 4, 5};
    for (int i=0; i<4; i++) {
        System.out.println(array[i]);
    }
}

When Java hits this error, it throws an exception and exits the program. This is a very simple stack trace. It states the runtime exception, in this case an ArrayIndexOutOfBoundsException. It also tells us which index this exception happened, so in this case 3. The only way we can tell this is from experience and knowing the exception message. We’ll look at other exception messages later in the video. The stack trace tells us the line in our code where things went bad. That’s where it says “at com.deegeu.constructors.NewClass.main” and the line number is 20.

3
4
5
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 3
	at com.deegeu.constructors.NewClass.main(NewClass.java:20)

If we go back to our code we can find line 20. Reading the stack trace for this case, we can see the exception, the bad value, and the line number. That should be enough to pin point the error.

We can make our call stack deeper by moving the error to a method outside the main method. Now the stack trace is deeper by one. The as we call methods within methods, this will get deeper. For some Java programs, this stack trace can be very deep. It really depends on where in our program we are.

public static void main(String args[]) {
    anotherMethod();
}
    
public static void anotherMethod() {
   int[] array = {3, 4, 5};
   for (int i=0; i<4; i++) {
       System.out.println(array[i]);
   } 
}

Not all stack traces are as kind our simple one. Some look like this.

2014-05-14 11:47:08,938 ERROR [org.jboss.as.ejb3.invocation] (EJB default - 3) JBAS014134: EJB Invocation failed on component MeasurementStreamQueryAsync for method public void com.deegeu.rest.MeasurementStreamQueryAsync.createQueryResults(org.neoninc.cds.domain.CdsQuery,java.lang.String,java.util.Date,javax.ws.rs.core.UriInfo): javax.ejb.EJBException: org.jboss.resteasy.spi.LoggableFailure: Unable to find contextual data of type: javax.ws.rs.core.UriInfo
                at org.jboss.as.ejb3.tx.CMTTxInterceptor.handleExceptionInOurTx(CMTTxInterceptor.java:190) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.as.ejb3.tx.CMTTxInterceptor.invokeInOurTx(CMTTxInterceptor.java:275) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.as.ejb3.tx.CMTTxInterceptor.required(CMTTxInterceptor.java:340) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.as.ejb3.tx.CMTTxInterceptor.processInvocation(CMTTxInterceptor.java:239) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.as.ejb3.component.interceptors.CurrentInvocationContextInterceptor.processInvocation(CurrentInvocationContextInterceptor.java:41) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.as.ejb3.component.invocationmetrics.WaitTimeInterceptor.processInvocation(WaitTimeInterceptor.java:43) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.as.ejb3.security.SecurityContextInterceptor.processInvocation(SecurityContextInterceptor.java:95) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.as.ejb3.component.interceptors.ShutDownInterceptorFactory$1.processInvocation(ShutDownInterceptorFactory.java:64) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.as.ejb3.component.interceptors.LoggingInterceptor.processInvocation(LoggingInterceptor.java:59) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.as.ee.component.NamespaceContextInterceptor.processInvocation(NamespaceContextInterceptor.java:50)
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.as.ejb3.component.interceptors.AdditionalSetupInterceptor.processInvocation(AdditionalSetupInterceptor.java:55) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.invocation.ContextClassLoaderInterceptor.processInvocation(ContextClassLoaderInterceptor.java:64) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:326) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.wildfly.security.manager.WildFlySecurityManager.doChecked(WildFlySecurityManager.java:439) [wildfly-security-manager-1.0.0.Final.jar:1.0.0.Final]
                at org.jboss.invocation.AccessCheckingInterceptor.processInvocation(AccessCheckingInterceptor.java:61) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.invocation.InterceptorContext.run(InterceptorContext.java:326) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.invocation.PrivilegedWithCombinerInterceptor.processInvocation(PrivilegedWithCombinerInterceptor.java:80) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.invocation.ChainedInterceptor.processInvocation(ChainedInterceptor.java:61) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.as.ee.component.ViewService$View.invoke(ViewService.java:185)
                at org.jboss.as.ee.component.ViewDescription$1.processInvocation(ViewDescription.java:182)
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.as.ejb3.component.interceptors.LogDiagnosticContextRecoveryInterceptor.processInvocation(LogDiagnosticContextRecoveryInterceptor.java:79) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.invocation.InterceptorContext.proceed(InterceptorContext.java:309) [jboss-invocation-1.2.1.Final.jar:1.2.1.Final]
                at org.jboss.as.ejb3.component.interceptors.AsyncFutureInterceptorFactory$1$1.runInvocation(AsyncFutureInterceptorFactory.java:87) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at org.jboss.as.ejb3.component.interceptors.AsyncInvocationTask.run(AsyncInvocationTask.java:73) [wildfly-ejb3-8.0.0.Final.jar:8.0.0.Final]
                at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145) [rt.jar:1.7.0_40]
                at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615) [rt.jar:1.7.0_40]
                at java.lang.Thread.run(Thread.java:724) [rt.jar:1.7.0_40]
                at org.jboss.threads.JBossThread.run(JBossThread.java:122) [jboss-threads-2.1.1.Final.jar:2.1.1.Final]
Caused by: org.jboss.resteasy.spi.LoggableFailure: Unable to find contextual data of type: javax.ws.rs.core.UriInfo
                at org.jboss.resteasy.core.ContextParameterInjector$GenericDelegatingProxy.invoke(ContextParameterInjector.java:54) [resteasy-jaxrs-3.0.6.Final.jar:]
                at com.sun.proxy.$Proxy104.getRequestUri(Unknown Source)
                at  com.deegeu.rest.MeasurementStreamQueryAsync.generateStructuredFileFromResults(MeasurementStreamQueryAsync.java:523) [classes:]

                ... 38 more

The “caused by” tells us that the exception we received above was really caused by this exception. We want to look at this line of code to solve the problem. You can have multiple “caused by” sections in a stack trace, but the last one will likely be your problem.

And then there are very long convoluted stack traces where the final exception stack trace isn’t our code. It’s in a library somewhere. In this case, we likely sent bad data to the library causing it to fail. What we want to do in this case is look for the last stack trace message that is coming from our code. The first line that references our code is likely the problem.

Our next question is how to we handle checked exceptions? I say “checked exceptions” because we rarely, if ever, try to catch runtime exceptions. If we’re trying to catch a runtime exception, we really need to think about what we’re trying to accomplish.

However, Java does force us to handle all checked exceptions. In Java, we can either “catch” checked exceptions using something called a “try-catch” block in code, or specify a requirement that any method calling our method must handle the exception.

The error looks like this if we do not catch the checked exception. This happens at compile time. Let’s look at handling exceptions using the specify requirement, since that one is the easiest.

public void myMethod() throws Exception {
        
}

If our method has the possibility of throwing an exception, we can specify the exception in the method declaration. We add the keyword “throws” and the exception class. We only need to do this for checked exceptions. Runtime exceptions do not need to be declared. When we add this code, we’re telling anyone calling our method they need to catch this exception.

Exceptions work like this. The exception is thrown in a method somewhere in our code. If we don’t catch the exception in this method, we declare our method throws the exception and Java passes the exception up to the calling method. If there’s code to catch the exception here, it will run the handling code. Otherwise it will keep working it’s way up the call stack until it reaches the main method, or a method that does catch the exception. If nothing catches the exception, the program crashes and reports the problem.

How do we catch an exception? We use a try-catch block. It starts with the keyword try, a code block to try, and then the keyword catch, the exception type, and the code to handle the exception. This code says, “try this code block, and if there’s an exception of this type catch it with this code block”. Once the exception is caught, we execute the next line of code after the catch.

try {
   // code that can throw an exception         
} catch (Exception e) {
   // code that handles the exception           
}
System.out.println(“after exception”);

The exception type is important. Our catch block applies only for the exception type we state after the catch keyword. So if we put FileNotFoundException, it will only apply for FileNotFoundExceptions and any possible FileNotFountException subclasses.

We can put different catch blocks for a single try block. This allows us to provide handling code specific to the exception. The exceptions we handle must be ordered from specific exceptions to general exceptions. The reason is Java will try to match the exception class from top to bottom. As soon as Java hits an exception it matches, it stop looking.

So if we put Exception as the first class like this, it doesn’t matter if there is a more specific Exception class later. Exception is the superclass, so this catch applies to Exception and any subtype – which is everything. Java will only run one catch block per exception.

Catching just the Exception type is a bad practice. The reason is, we’re telling Java this code handles this exception type. If we use the Exception superclass, that means we’re saying our code handles any error that can happen. There are not many cases where this is true. It’s not Pokemon, we don’t want to catch them all. Usually we’d want to recover from a file not found differently than a an error from parsing.

It’s very important we put our application back into a runnable state after catching exceptions. When we catch an exception, our catch block is run, and then the very next line of code is executed. So if we don’t completely recover from what ever problem threw the exception, we’re just going to create more problems.

try {
   // code that can throw an exception         
} catch (Exception e) {
            
}
System.out.println(“after exception”);

There are three things we might see in code we’re maintaining. The first is a blank catch block. This hides the problem, as if it never happened. It’s saying, “try this code, and if it fails, ignore the problem and hope no one notices”. What almost always happens is our application is now in an invalid state, and something bad will happen again later down the road in a completely different location. This makes the problem very hard to diagnose and fix. Don’t ever do it. If you don’t know how to handle the exception, specify the requirement for the calling class to handle it.

try {
   // code that can throw an exception         
} catch (Exception e) {
   System.out.println(“error happened”);           
}
System.out.println(“after exception”);

The next worse thing is, some developers will say “since I can’t have a blank catch block, I’ll add a log message”, or worse write a message to the console. That’s the same thing as a blank catch block. In this case, we are writing a note that no one is likely to see, and then putting the application in a state where something bad can happen later on. Again, if you don’t know how to handle the exception, specify the requirement for the calling class to handle it.

try {
   // code that can throw an exception         
} catch (Exception e) {
   throw new Exception(“new exception”);           
}
System.out.println(“after exception”);

Finally, we might see code like this. This is called catching and throwing a new exception. The problem with this is we are losing the stack trace. The exception in our try block is handled, and then we are throwing a new exception with a stack trace starting from here. If you want to log a message, and then rethrow an exception, this is how you want to do it. Just use the keyword throw with the same exception object. This will preserve the stack trace.

try {
   // code that can throw an exception         
} catch (Exception e) {
   System.out.println(“error happened”);
   throw e;           
}
System.out.println(“after exception”);

And that’s a whirlwind tour of Java exceptions. In the next video we’ll look at diagnosing common exceptions, and how to fix them.

Put any questions you have in the comments below. Liking the video helps me know what I’m doing right, so if you liked the video… you know what to do.

And with that, I’ll see you in the next tutorial!

<p><script async="" src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<!-- DeegeU - Right Side -->
<ins class="adsbygoogle" style="display:inline-block;width:336px;height:280px" data-ad-client="ca-pub-5305511207032009" data-ad-slot="5596823779"></ins>
<script>
(adsbygoogle = window.adsbygoogle || []).push({});
</script></p>

Tools Used

  • Java
  • NetBeans

Media Credits

All media created and owned by DJ Spiess unless listed below.

  • No infringement intended

Hustle by Kevin MacLeod is licensed under a Creative Commons Attribution license (https://creativecommons.org/licenses/by/4.0/)
Source: http://incompetech.com/music/royalty-free/index.html?isrc=USUAN1100793
Artist: http://incompetech.com/

Five Card Shuffle by Kevin MacLeod is licensed under a Creative Commons Attribution license (https://creativecommons.org/licenses/by/4.0/)
Source: http://incompetech.com/music/royalty-free/index.html?isrc=USUAN1100227
Artist: http://incompetech.com/

Get the code

The source code for “Java Exception Handling” can be found on Github. If you have Git installed on your system, you can clone the repository by issuing the following command:

 git clone https://github.com/deege/deegeu-java-intro.git

Go to the Support > Getting the Code page for more help.

If you find any errors in the code, feel free to let me know or issue a pull request in Git.

Don’t miss another video!

New videos come out every week. Make sure you subscribe!

Comments

comments

DJ Spiess

DJ Spiess

Your personal instructor

My name is DJ Spiess and I’m a developer with a Masters degree in Computer Science working in Colorado, USA. I primarily work with Java server applications. I started programming as a kid in the 1980s, and I’ve programmed professionally since 1996. My main focus are REST APIs, large-scale data, and mobile development. The last six years I’ve worked on large National Science Foundation projects. You can read more about my development experience on my LinkedIn account.

Pin It on Pinterest

Share This