Javac · Java Tutorials - Exception Handling: Stack Memory Introduction

Exception Handling: Stack Memory Introduction

The stack and the heap are the two basic memory areas available when running your Java programs. If you have been following my tutorial series, then you should understand that object instances are stored in heap memory. Most objects have instance variables and those instance variables live on the heap as part of the object. Also, I discussed that there is a special area of the heap called the string literal pool where certain String instances are stored. For the most part, method invocations and local variables are stored in the stack memory. The subject of Java memory management is complicated and certain details are beyond the scope of this tutorial, so I am going to provide you with a general idea of how the stack works. One other important thing to note is that stack memory is created and allocated to an individual thread; I haven't discussed the concept of multi-threading in programs, so don't worry about that just yet.

Determining Stack Size

The amount of memory allocated to the stack is determined by the compiler based on criteria such as the number of methods, reference variables, local variables and so forth. There are other ways to increase the amount of thread stack size, such as the -Xss command line options specified when running the JVM. For example, java -Xss18m ClassName will allocate a crazy large 18 megabytes of stack memory space. The -X command line options are beyond the scope of this tutorial, but I just wanted to give you a taste of what is to come.

Creating the stack, deleting the stack.

Consider the following:
class MyClass {
      public static void main(String args[]) {
            int i = 10;
      }
}
When you run the JVM from the command line by executing the java MyClass, the very first thing that is placed on the stack is the main() method. The next thing placed on the stack is the reference variable args. After that the primitive variable i and its value are placed on the stack. Since no other statements exist, the stack is 'unwound' as main completes execution; i is removed, then args, then finally the main() method.

The Call Stack

The call stack is basically a list of all of the currently active methods. The granddaddy of all the methods on the call stack is the main method and if you have been following my tutorials, you have heard me refer to it as your program's entry point over and over again. The call stack is composed of frames, so the first frame in the call stack contains the 'call' (invocation) to the main method. Suppose inside of the main method there is a 'call' to invoke method A and that method A then makes a 'call' to invoke method B, then you would have three frames on the call stack beginning with main, A, then B. The main purpose for a call stack is to determine which method should return control once a method has terminated. When method B terminates, control is returned to method A, once method A terminates, control is returned to the main method.
How does all this relate to exeception handling? As you will learn in my upcoming tutorials, exceptions that occur in frames higher up the call stack can be passed down to frames lower in the call stack as it unwinds.

For the purposes of this tutorial, I will limit my explanation of the call stack to just that. After all, the real subject is exception handling so it is time to get back on track.



Open the command prompt (CMD - see the Getting Started ) and type in the following commands.

C:\Windows\System32>cd \
C:\>md Java
C:\>cd Java
C:\Java>
C:\Java>md ExceptionStack
C:\Java>cd ExceptionStack
C:\Java\ExceptionStack>Notepad ExceptionStack.java

Copy and Paste, or type the following code into Notepad and be sure to save the file when you are done.


class ExceptionStack {
    public static void main(String args[]) {
        System.out.println("Building up the stack:");
        StackTraceElement ste[] = Thread.currentThread().getStackTrace();
        for (StackTraceElement temp : ste) { System.out.println(temp.getMethodName()); }

        new One().invokeAnother();

        System.out.println("\nBack to main:");
        ste = Thread.currentThread().getStackTrace();
        for (StackTraceElement temp : ste) { System.out.println(temp.getMethodName()); }  
    }
}

class One {
    void invokeAnother() {
        System.out.println("\nNow the stack is:");     
        StackTraceElement ste[] = Thread.currentThread().getStackTrace();
        for (StackTraceElement temp : ste) { System.out.println(temp.getMethodName()); }    
	
        new Two().invokeOneMore();

        System.out.println("\nRemoved invokeOneMore:");      
        ste = Thread.currentThread().getStackTrace();
        for (StackTraceElement temp : ste) { System.out.println(temp.getMethodName()); }  
    }    
}

class Two {
    void invokeOneMore() {
        System.out.println("\nPutting more on the stack:");
        StackTraceElement ste[] = Thread.currentThread().getStackTrace();
        for (StackTraceElement temp : ste) { System.out.println(temp.getMethodName()); }    
    }  
}

Now switch back to the command prompt (CMD) and type in javac ExceptionStack.java and press Enter.
Now type in java ExceptionStack and press Enter.


C:\Java\ExceptionStack>javac ExceptionStack.java
C:\Java\ExceptionStack>java ExceptionStack
Building up the stack:
getStackTrace
main

Now the stack is:
getStackTrace
invokeAnother
main

Putting more on the stack:
getStackTrace
invokeAnother
main

Back to main:
getStackTrace
main


Final thoughts

The purpose of this tutorial was just to present you with a general idea of how the call stack works. As I continue my exception handling mini-series I will elaborate on many of the concepts from this tutorial.


Tutorials