Monday, June 30, 2014

MultiThreading

Many multithreading needs are related to building responsive user interfaces. For example, most word processing applications contain an “autosave” function. You can configure the word processor to save your documents every xminutes. 

The autosave executes automatically on schedule without needing your intervention. A save may take several seconds to execute, yet you can continue work without interruption.

The word processor code manages at least two threads. One thread, often referred to as the foreground thread, is managing your direct interaction with the word processor. Any typing, for example, is captured by code executing in the foreground thread. Meanwhile, a second, background thread is checking the clock from time to time. Once the configured number of minutes has elapsed, the second thread executes the code in the save function.

On a multiple-processor machine, multiple threads can actually run simultaneously, each thread on a separate processor. On a single-processor machine, threads each get a little slice of time from the processor (which can usually only execute one thing at a time), making the threads appear to execute simultaneously.

The challenge is when multiple threads need to share the same resource. If you are not careful, multithreaded solutions can generate incorrect answers or freeze up your application.

Creating and Running Threads

A thread is a lightweight subprocess, a smallest unit of processing. It is a separate path of execution. It shares the memory area of process.
  • Note: At least one process is required for each thread.
  • Threads share the same address space.
  • Thread is lightweight.
  • Cost of communication between the thread is low.
Threads share a common memory area. They don't allocate separate memory area so save memory, and context-switching between the threads takes less time than processes.

Life Cycle of a thread:

The life cycle of the thread is controlled by JVM. The thread states are as follows:
  1. New
    • A thread is in New state, if you create an instance of Thread class but before the invocation of start() method.
  2. Runnable
    • The thread is in Runnable state after invocation of start() method, but the thread scheduler has not selected it to be the running thread.
  3. Running
    • The thread is in Running state if the thread scheduler has selected it.
  4. Non-Runnable (Blocked)
    • This is the state when the thread is still alive, but is currently not eligible to run.
  5. Terminated
    • A thread is in Terminated or dead state when its run() method exits.



2 ways to create Threads in Java:

Java supplies two ways for you to initiate a separate thread.

The first requires you to extend the class java.lang.Thread and provide an implementation for the run method. Subsequently, you can call the start method to kick things off. At that point, code in the run method begins execution in a separate thread.


A second technique for spawning threads is to create an instance of a class that implements the interface java.lang.Runnable:
public interface Runnable {
   public void run();
}
You then construct a Thread object, passing the Runnable object as a parameter. Sending the message start to the Thread object initiates code in the run method. This second technique is often done using anonymous inner class implementations of Runnable.

A Thread is an object that manages information about a thread of execution(control flow that the thread scheduler manages).

start() method of Thread class is used to start a newly created thread. It performs following tasks:
  • A new thread starts with new callstack.
  • The thread moves from New state to the Runnable state.
  • When the thread gets a chance to execute, its target run() method will run.
Thread class itself implements the Runnable interface. If you extend Thread, you will need to override the run method in order for anything useful to happen.

Example: Creating threads by extending 'Thread' class.
First Thread:

//This class is made as a thread by extending "Thread" class.
public class FirstThread extends Thread 
{ 
  //This method will be executed when this thread is executed 
  public void run() 
  { 
    //Looping from 1 to 10 to display numbers from 1 to 10 
     for (int i=1; i<=10; i++) 
     { 
        //Displaying the numbers from this thread 
        System.out.println( "Messag from First Thread : " +i);      
        /*taking a delay of one second before displaying next number
        * 
        * "Thread.sleep(1000);" - when this  statement is executed, 
        * this thread will sleep for 1000  milliseconds (1 second) 
        * before executing the next statement. 
        * 
        * Since  we are making this thread to sleep for one second, 
        * we need to handle  "InterruptedException". Our thread 
        * may throw this exception if it is  interrupted while it 
        * is sleeping. 
        * 
        */ 

        try 
        { 
           Thread.sleep(1000); 
        } 
        catch (InterruptedException  interruptedException) 
        { 
          /*Interrupted exception will be thrown when a sleeping  
          * or waiting thread is interrupted. 
          */ 
          System.out.println( 
              "First Thread is interrupted when it is  sleeping"  
                          +interruptedException); 
        } 
      } 
   } 
} 
Second Thread: 
//This class is made as a thread by extending "Thread" class.  
public class SecondThread extends Thread 
{   
  //This method will be executed when this thread is executed   
  public void run()     
  {             
    //Looping from 1 to 10 to display numbers from 1 to 10      
    for (int i=1; i<=10; i++)        
    {           
       System.out.println( "Messag from Second Thread : " +i);                 
       /*taking a delay of one second before displaying next number 
       * "Thread.sleep(1000);" - when this statement is executed, 
       * this thread will sleep for 1000 milliseconds (1 second) 
       * before executing the next statement.             
       *              
       * Since we are making this thread to sleep for one second, 
       * we need to handle "InterruptedException". Our thread 
       * may throw this exception if it is interrupted while it 
       * is sleeping.             
       */           
       try          
       { 
           Thread.sleep (1000);          
       }            
       catch (InterruptedException interruptedException)            
       {                
          /*Interrupted exception will be thrown when a sleeping 
           * or waiting thread is interrupted.               
           */               
           System.out.println( 
                      "Second Thread is interrupted when it is sleeping"  
                           +interruptedException);           
       }        
    }   
  } 
}
Main Class: 
public class ThreadDemo 
{      
  public static void main(String args[])    
  {           
    //Creating an object of the first thread 
    FirstThread   firstThread = new FirstThread();              

    //Creating an object of the Second thread       
    SecondThread   secondThread = new SecondThread();            

    //Starting the first thread         
    firstThread.start();                
    //Starting the second thread        
    secondThread.start();   
  } 
}
Example: Creating threads using 'Runnable' interface. 
First thread:
// This class is made as a thread by implementing 
// "Runnable" interface. 
public class FirstThread implements Runnable 
{  
  //This method will be executed when this thread is executed   
  public void run()     
  {                 
    //Looping from 1 to 10 to display numbers from 1 to 10      
    for ( int i=1; i<=10; i++)       
    {           
        //Displaying the numbers from this thread
     System.out.println( "Messag from First Thread : " +i);  
       /*taking a delay of one sec before displaying next number
        *          
        * "Thread.sleep(1000);" - when this statement is executed,
        * this thread will sleep for 1000 milliseconds (1 second) 
        * before executing the next statement. 
        *    
        * Since we are making this thread to sleep for one second,
        * we need to handle "InterruptedException". Our thread 
        * may throw this exception if it is interrupted while it  
        * is sleeping. 
        *     
        */   
        try         
        {           
           Thread.sleep (1000);             
        }           
        catch (InterruptedException interruptedException)           
        {   
           /*Interrupted exception will be thrown when a sleeping 
            *or waiting thread is interrupted.   
            */      
            System.out.println( "First Thread is interrupted when it is sleeping" +interruptedException);           
        }   
    }   
  } 
}
Second thread:
//This class is made as a thread by implementing "Runnable" interface. 
public class SecondThread implements Runnable 
{   
   //This method will be executed when this thread is executed  
   public void run()    
   {            
      //Looping from 1 to 10 to display numbers from 1 to 10        
      for ( int i=1; i<=10; i++)         
      {             
  System.out.println( "Messag from Second Thread : " +i); 
        /*taking a delay of one sec before displaying next number 
         * 
         * "Thread.sleep(1000);" - when this stmt is executed,     
         * this thread will sleep for 1000 milliseconds (1 second)  
         * before executing the next statement.    
         *   
         * Since v r making this thread to sleep for one second, 
         * we need to handle "InterruptedException". Our thread 
         * may throw this exception if it is interrupted while it
         * is sleeping.  
         */             
         try            
         {              
             Thread.sleep(1000);            
         }          
         catch (InterruptedException interruptedException)          
         {              
            /*Interrupted exception will be thrown when a sleeping 
             *or waiting thread is interrupted. 
             */    
             System.out.println( "Second Thread is interrupted when it is sleeping" +interruptedException); 
         }      
      }     
    }  
}
Main class:
public class ThreadDemo 
{ 
     public static void main(String args[]) 
     { 
        //Creating an object of the first thread 
        FirstThread   firstThread = new FirstThread(); 
        //Creating an object of the Second thread 
        SecondThread   secondThread = new SecondThread(); 
        //Starting the first thread 
        Thread thread1 = new Thread(firstThread); 

        thread1.start(); 
        //Starting the second thread 
        Thread thread2 = new Thread(secondThread); 
        thread2.start(); 
     } 
}
Question: Can we start a thread twice??
No. After starting a thread, it can never be started again. If you do so, an IllegalThreadStateException is thrown.
Question: What if we call run() method directly instead start() method?
Invoking the run() method from main thread, the run() method goes onto the current call stack rather than at the beginning of a new call stack. There is no context-switching.
 Cooperative and Preemptive Multitasking

In a single-processor environment, individual threads each get a slice of time from the processor in which to execute. The question is, how much time does each thread get before another thread takes over? The answer depends upon many things, including which operating system you are using to run Java and your particular JVM implementation.

Most modern operating systems (including Unix variants and Windows) use preemptive multitasking, in which the operating system (OS) interrupts the currently executing thread. Information about the thread is stored, and the OS goes on to provide a slice of time to the next thread. In this environment, all threads will eventually get some attention from the thread scheduler.

The other possibility is that the operating system manages threads using cooperative multitasking. Cooperative multitasking depends on thread code behaving well by yielding time to other threads frequently. In a cooperative threading model, one poorly written thread could hog the processor completely, preventing all other threads from doing any processing. Threads may yield time by explicitly calling the yield method, by sleeping, when blocking (waiting) on IO operations, and when they are suspended, to mention a few ways.
            Thread.yield();

currentThread() method
The currentThread() method returns a reference to the currently executing thread object.
  1. class MultiThreads extends Thread{  
  2.  public void run(){  
  3.   System.out.println(Thread.currentThread().getName());  
  4.  }  
  5.  }  
  6.  public static void main(String args[]){  
  7.   MultiThreads t1=new MultiThreads();  
  8.   MultiThreads t2=new MultiThreads();  
  9.   
  10.   t1.start();  
  11.   t2.start();  
  12.  }  
  13. }  
The Join() method
The join() method waits for a thread to die. In other words, it causes the currently running threads to stop executing until the thread it joins with completes its task.

public void join()throws InterruptedExceptionpublic void join(long milliseconds)throws InterruptedException

  1. class Multi extends Thread{  
  2.  public void run(){  
  3.   for(int i=1;i<=5;i++){  
  4.    try{  
  5.     Thread.sleep(500);  
  6.    }catch(Exception e){System.out.println(e);}  
  7.   System.out.println(i);  
  8.   }  
  9.  }  
  10. public static void main(String args[]){  
  11.  Multi t1=new Multi();  
  12.  Multi t2=new Multi();  
  13.  Multi t3=new Multi();  
  14.  t1.start();  
  15.  try{  
  16.   t1.join();  
  17.  }
  18. catch(Exception e){System.out.println(e);}  
  19.   
  20.  t2.start();  
  21.  t3.start();  
  22.  }  
  23. }  

o/p: You can see, when t1 completes its task then t2 and t3 starts executing.
       1
       2
       3
       4
       5
       1
       1
       2
       2
       3
       3
       4
       4
       5
       5
The Thread class provides methods to change and get the name of a thread.
  1. public String getName(): is used to return the name of a thread.
  2. public void setName(String name): is used to change the name of a thread.
Examples:
t1.getName();t1.setName("Sonoo Jaiswal");
Priority of a Thread
Each thread have a priority. Priorities are represented by a number between 1 and 10. In most cases, thread scheduler schedules the threads according to their priority (known as preemptive scheduling). But it is not guaranteed because it depends on JVM specification that which scheduling it chooses.
  1. public static int MIN_PRIORITY
  2. public static int NORM_PRIORITY
  3. public static int MAX_PRIORITY
Default priority of a thread is 5 (NORM_PRIORITY). The value of MIN_PRIORITY is 1 and the value of MAX_PRIORITY is 10.
  1. m1.setPriority(Thread.MIN_PRIORITY);  
  2. m2.setPriority(Thread.MAX_PRIORITY); 
Daemon Thread
The daemon thread is a service provider thread. It provides services to the user thread. Its life depends on the user threads i.e. when all the user threads dies, JVM terminates this thread automatically.
  • It provides services to user threads for background supporting tasks. It has no role in life than to serve user threads.
  • Its life depends on user threads.
  • It is a low priority thread.
The sole purpose of the daemon thread is that it provides services to user thread for background supporting task. If there is no user thread, why should JVM keep running this thread. That is why JVM terminates the daemon thread if there is no user thread.
The java.lang.Thread class provides two methods related to daemon thread
  • public void setDaemon(boolean status): is used to mark the current thread as daemon thread or user thread.
  • public boolean isDaemon(): is used to check that current is daemon.
  1. class MyThread extends Thread{  
  2.  public void run(){  
  3.   System.out.println("Name: "+Thread.currentThread().getName());  
  4.   System.out.println("Daemon: "+Thread.currentThread().isDaemon());  
  5.  }  
  6.   
  7.  public static void main(String[] args){  
  8.   MyThread t1=new MyThread();  
  9.   MyThread t2=new MyThread();  
  10.   t1.setDaemon(true);  
  11.     
  12.   t1.start();  
  13.   t2.start();  
  14.  }  
  15. }  

Note: If you want to make a user thread as Daemon, it must not be started otherwise it will throw IllegalThreadStateException.

Note: If you have to perform multiple tasks by multiple threads,have multiple run() methods.
Few Questions:
Q1: Valid constructors for Thread? 
Thread(Runnable r, String name) 
Thread() 

Q2: Which method must be defined by class implementing Runnable interface? 
public void run() 

Q3: Which will contain the body of the thread? 
run() method

Q4: What are the three methods of the Object class?
notiy()
notifyAll()
wait(long msecs) 

start() and terminate() methods are defined in class Thread. 
start() method registers a thread in a thread scheduler.

wait() causes current thread to wait until another thread invokes the notify() method or   the notifyAll() method for this object.

Synchronization

One of the biggest pitfalls with multithreaded development is dealing with the fact that threads run in nondeterministic order. 

Each time you execute a multithreaded application, the threads may run in a different order that is impossible to predict. The most challenging result of this nondeterminism is that you may have coded a defect that surfaces only once in a few thousand executions, or once every second full moon.


Two threads that are executing code do not necessarily move through the code at the same rate. One thread may execute five lines of code before another has even processed one. The thread scheduler interleaves slices of code from each executing thread.


All this code interleaving means that you may encounter synchronization issues. If two threads go after the same piece of data at the same time, the results may not be what you expect.


When you send the message join to a thread, execution in the current thread halts until that thread completes.


Synchronized

A thread should be able to execute the entire method, start to finish, without any other thread interfering. You can accomplish this in Java through use of the synchronized method modifier.

public synchronized void withdraw(BigDecimal amount) {
   if (amount.compareTo(balance) > 0)
      return;
   balance = balance.subtract(amount);
}
This implementation of synchronization in Java is known as mutual exclusion. Another way you can refer to the code protected by mutual exclusion is as a critical section. 

In order to ensure that the method code executes mutually exclusively, Java places a lock on the object in which the thread's code is executing. 

While one thread has a lock on an object, no other thread can obtain a lock on that object. Other threads that try to do so will block until the lock is released. The lock is released when the method completes execution.

Java uses a concept known as monitors to protect data. A monitor is associated with each object; this monitor protects the object's instance data. A monitor is associated with each class; it protects the class's static data. When you acquire a lock, you are acquiring the associated monitor; only one thread can acquire a lock at any given time.
You should always try to lock the smallest amount of code possible, otherwise you may experience performance problems while other threads wait to obtain a lock. If you are creating small, composed methods as I've repetitively recommended, you will find that locking at the method level suffices for most needs.
You can lock at a smaller atomicity than an entire method by creating a synchronized block. You must also specify an object to use as a monitor by enclosing its reference in parentheses after the synchronized keyword.
The following implementation of withdraw is equivalent to the above implementation.
public void withdraw(BigDecimal amount) {
   synchronized(this) {
      if (amount.compareTo(balance) > 0)
         return;
      balance = balance.subtract(amount);
   }
}
synchronized block requires the use of braces, even if it contains only one statement.
You can declare a class method as synchronized. When the VM executes a class method, it will obtain a lock on the Class object for which the method is defined.
Synchronized Collections
When you work with the Java 2 Collection Class Framework with classes such as ArrayList, LinkedList, and HashMap, you should be cognizant of the fact that they are not thread-safe—the methods in these classes are not synchronized.
ArrayList, LinkedList and HashMap ----> not thread-safe
Vector and HashTable ----> synchronized
Instead, you can use utility methods in the class java.util.Collections to enclose a collection instance in what is known as a synchronization wrapper. The synchronization wrapper obtains locks where necessary on the targetcollection and delegates all messages off to the collection for normal processing.
Example of adding Synchronization Wrapper:
import java.util.Collections;
List<Search> queue = Collections.synchronizedList(new LinkedList<Search>());
Adding the synchronization wrapper doesn't require you to change any code.

JAR files

When you learned about the Java classpath, you learned to add class folders (or directories) to your classpath. A class folder contains discrete class files that Java looks for when it needs to load a class.

Your classpath can include JARs in addition to, or instead of, class folders.

A JAR (Java ARchive) is a single file that collects Java class files and other resources needed at run time. 

You can create JARs using the jar command-line utility executable supplied in your Java bin directory. You can also create JARs using Ant.

The usage of JARs falls under the category of 'deployment'.

The jar utility combines class files and other resources (such as images or property files) into a single file with an extension of .jar. The utility creates JARs as ZIP files, a file format you are likely familiar with. A ZIP file uses a standard compression algorithm to reduce the overall space requirements.

Advantages of using JAR:
  • Deployment speed. Transferring or installing a few files is considerably faster than transferring or installing thousands of files.
  • Compression. Disk requirements are smaller; smaller files are downloaded faster.
  • Security. When working in secure environments, you can attach a digital signature to a JAR.
  • Pluggability. You can organize JARs around reuse interests. JARs can be components or complete API sets.
  • Versioning. You can attach vendor and version information to JARs.
  • Simplified execution. You can designate a JAR to be “Java executable.” A user of the JAR does not need to know an entry class name.
JARs are the basis for deploying classes to a web server or enterprise Java installation.

To create a JAR for the SIS application, first navigate to the classes directory. Then execute:
jar cvf sis.jar *

In the above jar command, the options cvf (cv, and f) tell the JAR command to create a new JAR, to provide verbose output (not necessary but useful), and to use a filename of sis.jar. The * at the end of the command tells the jar program to archive all files in the current directory and all subdirectories. 

You can execute the commandjar with no arguments to display a brief summary of the command and its proper usage.

After executing the jar cvf command, you should have a file named sis.jar. Under Windows, you can open this JAR using WinZip. Under any platform, you can use the jar command to list the contents of the JAR.
jar tvf sis.jar

The only difference in the command is the option t (list table of contents) instead of c.

You can extract files from the JAR using the command option x (i.e., jar xvf).

Once you have added classes to a JAR, you can add the JAR to your classpath. Java will dig into the JAR file to look for classes it needs to load. 
For example, suppose you deploy sis.jar to the directory /usr/sis. You can execute the SIS application using the command:
java -cp /usr/sis/sis.jar sis.ui.Sis

In order for Java to find a class within a JAR, its path information must match the package information. To locate the class com.jimbob.ach.Ach, Java must be able to find an entry in the JAR with the complete pathnamecom/jimbob/ach/Ach.class.

The jar utility adds a manifest file, META-INF/MANIFEST.MF, to the ZIP file. The manifest file contains information about the contents of the JAR (i.e., meta-information).

One use for the manifest file is to indicate a “main” class. If you specify a main class, you can initiate an application by providing only the JAR name. You can accomplish this by first creating a separate manifest file with the contents:
Main-Class: sis.ui.Sis

Make sure you include a blank line as the last line of this file! Otherwise Java may not recognize the manifest entry.

When you create the JAR, specify the manifest file using the command:
jar cvmf main.mf sis.jar *

The m option stands for manifest. If you now, look at the file MANIFEST.MF in sis.jar, it should look something like this:
Manifest-Version: 1.0
Created-By: 1.5.0 (Sun Microsystems Inc.)
Main-Class: sis.ui.Sis

You can now initiate the SIS application using the simplified command:
java -jar sis.jar

You can manipulate JARs (and ZIP files) programmatically. Java supplies a complete API in the package java.util.zip to help you accomplish this. 

The java.util.zip package contains tools to both read and write JARs. This allows you to write unit tests against JAR operations about as simply as if you were testing against text files.

Tuesday, June 10, 2014

Exception Handling in Java

Imagine you’re about to board an airplane to Geneva to attend an important conference. At the last minute, you learn that the flight has been cancelled because the pilot is not feeling well. Fortunately, the airline quickly arranges for an alternative pilot, allowing the flight to take off at its originally scheduled time. What a relief.

This example illustrates how exceptional conditions can modify the initial flow of an action and demonstrates the need to handle those conditions appropriately. 

In Java, an exceptional condition (like the illness of a pilot) can affect the normal code flow (airline flight operation). In this context, the arrangement for an alternative pilot can be compared to an exception handler.

Exceptions are objects that are thrown by an application or the Java Virtual Machine (JVM) when an error of some sort occurs. Java provides a wide range of predefined exceptions and allows the developer to declare and create their own exception classes.

Examples of exception cases: trying to access an array position not available, checked exceptions(gives compile time errors, if not handled properly), stack overflow error, etc.

  • ArrayIndexOutofBoundsException - thrown at run time.
  • Checked exception, FileNotFoundException, thrown by FileInputStream is not "caught" by code.
  • StackOverflowError at run time. A method calls itself recursively.
3 types:

  1. Program Errors - internal flaws in code
  2. Improper use of code - 
  3. Resource-related failures

When the error is not caught, the continued execution of the program can lead to unpredictably and possibly disastrous consequences.

Traditional Approach:

A traditional approach to handling exceptions is to return an error code from a procedure. For example, a function may normally return a zero(0) if it executed without an error. If an error occurs, a non-zero value(-1) would be returned. Problems with this approach:
  • Be unaware that the function returns an error code.
  • Forget to check for an error
  • Ignore the error completely
Another approach : "catch" errors

When a routine detects an error, it "throws" an exception object. The exception object is then returned to the caller which then catches and handles the error.

The try, catch, and finally blocks constitute the core of the exception handling mechanism used in Java.

The Throwable class is the superclass of all errors and exceptions in the Java language.
java.lang.Object
  extended by java.lang.Throwable
Direct Known Subclasses:
Error, Exception
Only objects that are instances of this class (Throwable class or one of its sub-classes) are thrown by the Java Virtual Machine or can be thrown by the Java throw statement. Similarly, only this class or one of its sub-classes can be the argument type in a catch clause. 
Checked Exceptions - Exceptions that need to be dealt with in the code.
Unchecked Exceptions - Exceptions that do not need to be dealt with in the code. They include exceptions, such as division by zero and array subscripting errors.

A checked exception requires the client to either catch the exception or explicitly pass it up the call hierarchy.

Uncaught exceptions are propagated to the next higher context until they are caught or they are thrown from main, where an error message and stack trace will be printed.

Traditional try-catch-finally block:

Creating try-catch-finally blocks
When you work with exception handlers, you often hear the terms try, catch, and finally. Before you start to work with these concepts, I’ll answer three simple questions:

■ Try what?
              First you try to execute your code. If it does not execute as planned, you handle the exceptional conditions using a catch block.
■ Catch what?
              You catch the exceptional event arising from the code enclosed within the try
block and handle the event by defining appropriate exception handlers.
■ What does finally do?
              Finally, you execute a set of code, in all conditions, regardless of whether the
code in the try block throws any exceptions. 


A try block is used to surround code that might throw exceptions.

The catch blocks are added after a try block to "catch" exceptions. The statements in the catch block provide blocks of code to "handle" the error. Only one catch block is ever executed when an exception is thrown.

A finally clause can optionally be used after the catch blocks. It is guaranteed to execute even if code within a try or a catch block throws or does not throw an exception. The finally clause is guaranteed to run and generally contains "clean-up" code.

A finally block will not execute if the System.exit method is invoked in a try or catch block.

Using Exceptions, you get two benefits:
a) Your normal flow of execution is separated from exception handling code, as the exception handling is done within catch blocks.
b) Exceptions also help in providing stack trace so that actual cause of exception can be easily traced.

For a try block, you can define multiple catch blocks, but only a single finally block.

Multiple catch blocks are used to handle different types of exceptions.

finally block is used to define cleanup code—code that closes and releases resources, such as file handlers and database or network connections.

Example:


public class MainClass {
  public static void main(String args[]) {
    int urAns, urDiv;
    try {
      urDiv = 0;
      urAns = 25 / urDiv;
      System.out.println("Division is successful");
    } 
    catch (ArithmeticException e) {
      System.out.println("Division by zero not Possible!");
    }
finally {
System.out.println("Finally block executed");
}
    System.out.println("This will print out after Exception Handling");

  }
}

o/p:
Division by zero not Possible!
Finally block executed
This will print out after Exception Handling

Will a finally block execute even if the try/catch block defines a return statement?

A finally block will execute even if the code in the try block or any of the catch blocks defines a return statement.

There are a few scenarios in Java in which a finally block does not execute:
■ Application termination—The try or the catch block executes System.exit, which terminates the application
■ Fatal errors—A crash of the JVM or the OS

What happens if both a catch and a finally block define return statements?

If both catch and finally blocks define return statements, the calling method will receive a value from the finally block. This is only when catch and finally block just returns literals.

What happens if a finally block modifies the value returned from a catch block?

If a catch block returns a primitive data type, the finally block can’t modify the value being returned by it. Control in the catch block copies the value of returnVal to be returned before it executes the finally block, so the returned value is not modified when finally executes. It is pass-by-value.

public class TestExceptionsExample {
    
    int getInt() {
    int returnVal = 10;
        try {
            String[] students = {"Harry", "Paul"};
            System.out.println("Initial Value: " + returnVal);
            System.out.println(students[5]);
        }
        catch (Exception e) {
            System.out.println("About to return in Catch block :" + returnVal);
            return returnVal;
        }
        finally {
            returnVal += 10;
            System.out.println("Return value in finally block:" + returnVal);
        }
        return returnVal;
    }
    public static void main(String args[]) {
        TestExceptionsExample var = new TestExceptionsExample();
        System.out.println("In Main: " + var.getInt());
    }

}

o/p:
Initial Value: 10
About to return in Catch block :10
Return value in finally block:20

In Main: 10

When the finally block executes, it can access the value of the object referred in the catch block and can modify it. The modified value is returned to the method main.
Remember that primitives are passed by value and objects are passed by reference.

public class TestExceptionsExample {
    
    StringBuilder getStringBuilder() {
        StringBuilder returnVal = new StringBuilder("Raghu");
        try {
            String[] students = {"Harry", "Paul"};
            System.out.println("Initial Value: " + returnVal);
            System.out.println(students[5]);
        }
        catch (Exception e) {
            System.out.println("About to return in Catch block : " + returnVal);
            return returnVal;
        }
        finally {
            returnVal.append("nath");
            System.out.println("Return value in finally block : " + returnVal);
        }
        return returnVal;
    }
    public static void main(String args[]) {
        
        TestExceptionsExample var = new TestExceptionsExample();
        System.out.println("In Main : " + var.getStringBuilder());
    }
}

o/p:
Initial Value: Raghu
About to return in Catch block : Raghu
Return value in finally block : Raghunath

In Main : Raghunath

Watch out for code that returns a value from the catch block and modifies it in the finally block. If a catch block returns a primitive data type, the finally block can’t modify the value being returned by it. If a catch block returns an object, the finally block can modify the value being returned by it.

Notes to remember:

■ A try block may be followed by multiple catch blocks, and the catch blocks may be followed by a single finally block.
■ A try block may be followed by either a catch or a finally block or both. But a finally block alone would not suffice if code in the try block throws a checked exception. In this case, you need to catch the checked exception or declare it to be thrown by your method. Otherwise your code won’t compile.
■ The try, catch, and finally blocks can’t exist independently.
■ The finally block can’t appear before a catch block.
■ A finally block always executes, regardless of whether the code throws an exception.

Can I rethrow an exception or the error I catch?

You can do whatever you want with an exception. Rethrow it, pass it on to a method, assign it to another variable, so on.

When you rethrow a checked exception, it’s treated like a regular thrown checked exception, meaning that all the rules of handling a checked exception apply to it.

You can rethrow a runtime exception, but you’re not required to catch it, nor must you modify your method signature to include the throws clause. The simple reason for this rule is that RuntimeExceptions aren’t checked exceptions, and they may not be caught or declared to be thrown by your code.

If a method does not wish to handle the checked exceptions thrown by a method it calls, it can throw these exceptions using the throws clause in its own method signature.

I can create nested loops, so can I create nested try-catch blocks too?

The simple answer is yes, you can define a try-catch-finally block within another try-catch-finally block. Theoretically, the levels of nesting for the try-catch-finally blocks have no limits.


Categories of exceptions:

■ Exceptions are divided into three categories: checked exceptions, runtime (or unchecked exceptions), and errors. These three categories share IS-A relationships
(inheritance).

■ Subclasses of the class java.lang.RuntimeException are categorized as runtime
exceptions.
■ Subclasses of the class java.lang.Error are categorized as errors.
■ Subclasses of the class java.lang.Exception are categorized as checked exceptions if they are not subclasses of class java.lang.RuntimeException.
■ The class java.lang.RuntimeException is a subclass of the class java.lang.Exception.
■ The class java.lang.Exception is a subclass of the class java.lang.Throwable.
■ The class java.lang.Error is also a subclass of the class java.lang.Throwable.
■ The class java.lang.Throwable inherits the class java.lang.Object.

Checked exceptions:

■ A checked exception is an unacceptable condition foreseen by the author of a method, but outside the immediate control of the code.
■ FileNotFoundException is a checked exception. This exception is thrown if the file that the code is trying to access can’t be found.
■ All checked exceptions are a subclass of the java.lang.Exception class, not a subclass of java.lang.RuntimeException. It’s interesting to note, however, that the class java.lang.RuntimeException itself is a subclass of the class java.lang.Exception.
■ If a method calls another method that may throw a checked exception, either it
must be enclosed within a try-catch block or the method should declare this
exception to be thrown in its method signature.

Runtime exceptions:

■ Runtime exceptions represent programming errors. These occur from inappropriate use of another piece of code. For example, NullPointerException is a runtime exception that occurs when a piece of code tries to execute some code on a variable that hasn’t been assigned an object and points to null. Another example is ArrayIndexOutOfBoundsException, which is thrown when a piece of code tries to access an array of list elements at a nonexistent position.
■ A runtime exception is a subclass of java.lang.RuntimeException.
■ A runtime exception isn’t a part of the method signature, even if a method may
throw it.
■ A runtime exception may not necessarily be caught by a try-catch block.

Errors:
■ An error is a serious exception, thrown by the JVM as a result of an error in the
environment state, which processes your code. For example, NoClassDefFound-
Error is an error thrown by the JVM when it is unable to locate the .class file it is
supposed to run.
■ StackOverflowError is another error, thrown by the JVM when the size of the
memory required by the stack of the Java program is greater than what the JRE
has offered for the Java application. This error usually occurs as a result of infinite
or highly nested loops.
■ An error is a subclass of the class java.lang.Error.
■ An error need not be a part of a method signature.
■ Though you can handle the errors syntactically, there is little that you can do
when these errors occur. For example, when the JVM throws OutOfMemory-
Error, your code execution will halt, even if you define an exception handler
for it.

Commonly occurring exceptions, categories, and classes:

■ ArrayIndexOutOfBoundsException is a runtime exception that’s thrown when a piece of code tries to access an array position out of its bounds—when an array is accessed either at a position less than 0 or at a position greater than or equal to its length.

■ IndexOutOfBoundsException is a runtime exception that’s thrown when a piece of code tries to access a list position that’s out of its bounds—when the position is either less than 0 or greater than or equal to the list’s size.

■ The class ArrayIndexOutOfBoundsException extends the class java.lang.IndexOutOfBoundsException, which extends the class java.lang.RuntimeException.

■ In typical programming conditions, the ArrayIndexOutOfBoundsException
shouldn’t be thrown programmatically.

■ One of the main reasons for the JVM taking the responsibility for throwing this exception itself is that this exception isn’t known until runtime and depends on the array or list position that’s being accessed by a piece of code. Most often, a variable is used to specify this array or list position, and its value may not be known until runtime.

■ ClassCastException is a runtime exception. java.lang.ClassCastException
extends java.lang.RuntimeException.
■ ClassCastException is thrown when an object fails an IS-A test with the class
type it is being cast to.
■ You can use the operator instanceof to verify whether an object can be cast to
another class before casting it.

■ IllegalArgumentException is a runtime exception. java.lang.Illegal-
ArgumentException extends java.lang.RuntimeException.
■ IllegalArgumentException is thrown to specify that a method has been passed
illegal or inappropriate arguments.
■ Even though IllegalArgumentException is a runtime exception, programmers
usually use this exception to validate the arguments that are passed to a
method, and the exception constructor is passed a descriptive message specifying
the exception details.

■ IllegalStateException is a runtime exception. java.lang.IllegalState-
Exception extends java.lang.RuntimeException.
■ IllegalStateException may be thrown programmatically.
■ As a programmer, you can throw IllegalStateException to signal to the calling
method that the method that’s being requested for execution isn’t ready to
start its execution or is in a state in which it can’t execute.
■ For example, you can throw IllegalStateException from your code if an
application tries to modify an SMS that has already been sent.

■ NullPointerException is a runtime exception. The class java.lang.Null-
PointerException extends java.lang.RuntimeException.
■ NullPointerException is thrown by the JVM if you try to access a method or
variable of an uninitialized reference variable.

■ NumberFormatException is a runtime exception. java.lang.NumberFormat-
Exception extends java.lang.IllegalArgumentException. java.lang.Illegal-
ArgumentException extends java.lang.RuntimeException.
■ You can throw NumberFormatException from your own method to indicate that
there’s an issue with the conversion of a String value to a specified numeric
format (decimal, octal, hexadecimal, or binary).

■ Runtime exceptions arising from any of the following may throw ExceptionIn-
InitializerError:
– Execution of an anonymous static block
– Initialization of a static variable
– Execution of a static method (called from either of the previous two items)
■ The error ExceptionInInitializerError can be thrown only by an object of a
runtime exception.
■ ExceptionInInitializerError can’t be thrown if a static initializer block
throws an object of a checked exception, because the Java compiler is intelligent
enough to determine this condition and it doesn’t allow you to throw an
unhandled checked exception from a static initialization block.

■ StackOverflowError is an error. java.lang.StackOverflowError extends
java.lang.VirtualMachineError.
■ Because StackOverflowError extends VirtualMachineError, it should be left
to be managed by the JVM.
■ The StackOverflowError error is thrown by the JVM when a Java program calls
itself so many times that the memory stack allocated to execute the Java program
“overflows.”

■ NoClassDefFoundError is an Error. java.lang.NoClassDefFoundError extends
java.lang.LinkageError. java.lang.LinkageError extends java.lang.Error.
■ NoClassDefFoundError is thrown by the JVM or a ClassLoader when it is
unable to load the definition of a class required to create an object of the class.
■ Don’t confuse the exception thrown by Class.forName(), used to load the
class, and NoClassDefFoundError thrown by the JVM. Class.forName() throws
ClassNotFoundException.

■ OutOfMemoryError is thrown by the JVM when it’s unable to create objects on the
heap and the garbage collector may not be able to free more memory for the JVM.