Wednesday, September 8, 2010

Struts request lifecycle


Struts request lifecycle

In this section you will learn about the Struts controller classes – ActionServlet, RequestProcessor, ActionForm, Action,ActionMapping and ActionForward – all residing in org.apache.struts.action package and struts-config.xml – the Struts Configuration file. Instead of the traditional "Here is the class – go use it" approach, you will study the function of each component in the context of HTTP request handling lifecycle in Struts.

ActionServlet
The central component of the Struts Controller is the ActionServlet. It is a concrete class and extends the javax.servlet.HttpServlet. It performs two important things.

1. On startup, its reads the Struts Configuration file and loads it into memory in the init() method.
2. In the doGet() and doPost() methods, it intercepts HTTP request and handles it appropriately.
The name of the Struts Config file is not cast in stone. It is a convention followed since the early days of Struts to call this file as struts-config.xml and place it under the WEB-INF directory of the web application. In fact you can name the file anyway you like and place it anywhere in WEB-INF or its subdirectories. The name of the Struts Config file can be configured in web.xml. The web.xml entry for configuring the ActionServlet and Struts Config file is as follows.

<servlet>
<servlet-name>action</servlet-name>
<servlet-class>org.apache.struts.action.ActionServlet
</servlet-class>
<init-param>
<param-name>config</param-name>
<param-value>/WEB-INF/config/myconfig.xml</param-value>
</init-param>
<load-on-startup>1</load-on-startup>
</servlet>

In the above snippet, the Struts Config file is present in the WEB-INF/config directory and is named myconfig.xml. The ActionServlet takes the Struts Config file name as an init-param. At startup, in the init() method, the ActionServlet reads the Struts Config file and creates appropriate Struts configuration objects (data structures) into memory. For now, assume that the Struts Config file is loaded into a set of objects in memory, much like a properties file loaded into a java.util.Properties class.

Like any other servlet, ActionServlet invokes the init() method when it receives the first HTTP request from the caller. Loading Struts Config file into configuration objects is a time consuming task. If the Struts configuration objects were to be created on the first call from the caller, it will adversely affect performance by delaying the response for the first user. The alternative is to specify load-on-startup in web.xml as shown above. By specifying load-onstartup to be 1, you are telling the servlet container to call the init() method immediately on startup of the servlet container.

The second task that the ActionServlet performs is to intercept HTTP requests based on the URL pattern and handles them appropriately. The URL pattern can be either path or suffix. This is specified using the servlet-mapping in web.xml. An example of suffix mapping is as follows.

<servlet-mapping>
<servlet-name>action</servlet-name>
<url-pattern>*.do</url-pattern>
</servlet-mapping>

If the user types http://localhost:8080/xyz/submitCustomerForm.do in the browser URL bar, the URL will be intercepted and processed by the ActionServlet since the URL has a pattern *.do, with a suffix of "do". Once the ActionServlet intercepts the HTTP request, it doesn't do much. It delegates the request handling to another class called RequestProcessor by invoking its process()method. Most of the Struts Controller functionality is embedded in the process() method of RequestProcessor class. Mastery over this flowchart will determine how fast you will debug problems in real life Struts applications. Let us understand the request handling in the process() method step by step with an example covered in the next several sub sections.

RequestProcessor and ActionMapping

The RequestProcessor does the following in its process() method:

Step 1: The RequestProcessor first retrieves appropriate XML block for the URL from struts-config.xml. This XML block is referred to as ActionMapping in Struts terminology. In fact there is a class called ActionMapping in org.apache.struts.action package. ActionMapping is the class that does what its name says – it holds the mapping between a URL and Action. A sample ActionMapping from the Struts configuration file looks as follows.

A sample ActionMapping from struts-config.xml

<action path="/submitDetailForm"
type="mybank.example.CustomerAction"
name="CustomerForm"
scope="request"
validate="true"
input="CustomerDetailForm.jsp">
<forward name="success"
path="ThankYou.jsp"
redirect="true"/>
<forward name="failure" path="Failure.jsp" />
</action>

Step 2: The RequestProcessor looks up the configuration file for the URL pattern /submitDetailForm. (i.e. URL path without the suffix do) and finds the XML block (ActionMapping) shown above. The type attribute tells Struts which Action class has to be instantiated. The XML block also contains several other attributes. Together these constitute the JavaBeans properties of the ActionMapping instance for the path /submitDetailForm. The above ActionMapping tells Struts to map the URL request with the path /submitDetailForm to the class mybank.example.CustomerAction. The Action class is explained in the steps ahead. For now think of the Action as your own class containing the business logic and invoked by Struts. This also tells us one more important thing. Since each HTTP request is distinguished from the other only by the path, there should be one and only one ActionMapping for every path attribute. Otherwise Struts overwrites the former ActionMapping with the latter.

ActionForm

Another attribute in the ActionMapping that you should know right away is name. It is the logical name of the ActionForm to be populated by the RequestProcessor. After selecting the ActionMapping, the RequestProcessor instantiates the ActionForm. However it has to know the fully qualified class name of the ActionForm to do so. This is where the name attribute of ActionMapping comes in handy. The name attribute is the logical name of the ActionForm. Somewhere else in struts-config.xml, you will find a declaration like this:

<form-bean name="CustomerForm"
type="mybank.example.CustomerForm"/>

This form-bean declaration associates a logical name CustomerForm with the actual class mybank.example.CustomerForm.

Step 3: The RequestProcessor instantiates the CustomerForm and puts it in appropriate scope – either session or request. The RequestProcessor determines the appropriate scope by looking at the scope attribute in the same ActionMapping.

Step 4: Next, RequestProcessor iterates through the HTTP request parameters and populates the CustomerForm properties of the same name as the HTTP request parameters using Java Introspection. (Java Introspection is a special form of Reflection using the JavaBeans properties. Instead of directly using the reflection to set the field values, it uses the setter method to set the field value and getter method to retrieve the field value.)

Step 5: Next, the RequestProcessor checks for the validate attribute in the ActionMapping. If the validate is set to true, the RequestProcessor invokes the validate() method on the CustomerForm instance. This is the method where you can put all the html form data validations. For now, let us pretend that there were no errors in the validate() method and continue. We will come back later and revisit the scenario when there are errors in the validate() method.

Action

Step 6: The RequestProcessor instantiates the Action class specified in the ActionMapping (CustomerAction) and invokes the execute() method on the CustomerAction instance. The signature of the execute method is as follows.

public ActionForward execute(ActionMapping mapping,ActionForm form,HttpServletRequest request,HttpServletResponse response) throws Exception

Apart from the HttpServletRequest and HttpServletResponse, the ActionForm is also available in the Action instance. This is what the ActionForm was meant for; as a convenient container to hold and transfer data from the http request parameter to other components of the controller, instead of having to look for them every time in the http request.

The execute() method itself should not contain the core business logic irrespective of whether or not you use EJBs or any fancy middle tier. The first and foremost reason for this is that business logic classes should not have any dependencies on the Servlet packages. By putting the business logic in the Action class, you are letting the  javax.servlet.* classes proliferate into your business logic. This limits the reuse of the business logic, say for a pure Java client. The second reason is that if you ever decide to replace the Struts framework with some other presentation framework (although we know this will not happen), you don't have to go through the pain of modifying the business logic. The execute() method should preferably contain only the presentation logic and be the starting point in the web tier to invoke the business logic. The business logic can be present either in protocol independent Java classes or the Session EJBs.

The RequestProcessor creates an instance of the Action (CustomerAction), if one does not exist already. There is only one instance of Action class in the application. Because of this you must ensure that the Action class and its attributes if any are thread-safe. General rules that apply to Servlets hold good. The Action class should not have any writable attributes that can be changed by the users in the execute() method.

Tuesday, September 7, 2010

What is Log4j

What is Log4j

Log4j is a tool to help the programmer output log statements to a variety of output targets.
With log4j it is possible to enable logging at runtime without modifying the application binary.

What are the components of Log4j

Log4j has three main components: loggers, appenders and layouts.

ü        There are six different level of logging supported by logger component (TRACE, DEBUG, INFO, WARN, ERROR, FATAL)
ü        Appender specifies the destination where the logging information should go for example Console, File, Email, Database etc.
ü        The layout is responsible for formatting the logging request according to the user's wishes

How to use Log4j

1.        Create a java project
2.        Add latest log4j jar file to the class path (log4j-1.2.14.jar)
3.        Create log4.properties in your 'src' folder. When the application is executed log4j.properties is automatically detected in 'src' folder.

### direct log messages to stdout ###

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.Target=System.out

log4j.appender.stdout.layout=org.apache.log4j.PatternLayout

log4j.appender.stdout.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n

log4j.rootLogger=all, stdout



4.        Create a java class LogManager.java as shown below
package training;

import org.apache.log4j.Logger;

public class LoggingManager {

        private static Logger log = Logger.getLogger(LoggingManager.class);

        public static void main(String args[]){

                log.trace("Trace");

                log.debug("Debug");

                log.info("Info");

                log.warn("Warn");

                log.error("Error");

                log.fatal("Fatal");

        }

}



5.        Execute the LoggingManager class you should see output like below
11:46:57,409 TRACE LoggingManager:9 - Trace

11:46:57,409 DEBUG LoggingManager:10 - Debug

11:46:57,409  INFO LoggingManager:11 - Info

11:46:57,409  WARN LoggingManager:12 - Warn

11:46:57,409 ERROR LoggingManager:13 - Error

11:46:57,409 FATAL LoggingManager:14 - Fatal


How to configure Log4j

Let's look at the configuration in log4j.properties file

log4j.appender.stdout=org.apache.log4j.ConsoleAppender

log4j.appender.stdout.Target=System.out


The above lines specify that all the logging messages should be handled by ConsoleAppender i.e. they will be printed on the console. An appender specifies where your log messages are written to. There is a wide choice of appenders available and custom appenders can be created as well.

Console Appender Logs to a console
File Appender Logs to file
SMTP Appender Logs by email
RollingFileAppender Logs to a file, starts a new file once the max size is reached. (An alternative is the DailyRollingFileAppender  which creates on file per day)


We can find all options on the following API page:
http://logging.apache.org/log4j/docs/api/org/apache/log4j/AppenderSkeleton.html


The layout specifies how a log message looks like, the below line defines which layout to be used.
log4j.appender.stdout.layout = org.apache.log4j.PatternLayout


The best up-to-date documentation about available layouts can be found in the API documentation:
http://logging.apache.org/log4j/docs/api/org/apache/log4j/Layout.html

Another parameter of pattern layout defines how the information to be logged.
log4j.appender.stdout.layout.ConversionPattern  =  %d{ABSOLUTE} %5p %c{1}:%L - %m%n

%d {ABSOLUTE}   Used to output the date of the logging event.  ABSOLUTE specifies the date formatter
%p Used to output priority of the logging event. %5p means the priority of the logging event should be left justified to a width of five characters
%c Used to output the category of the logging event.
%L Used to output the line number from where the logging request was issued.
%m Used to output the application supplied message associated with the logging event.
%n Outputs the platform dependent line separator character or characters


The options to influence the layout are explained in the API documentation:
http://logging.apache.org/log4j/docs/api/org/apache/log4j/PatternLayout.html

The below line configures the log level for logger,
log4j.rootLogger = all, stdout


For programmatically setting the log level use below line
Logger.getRootLogger().setLevel(Level.WARN)
all All levels including custom levels
trace development only, can be used to follow the program execution.
debug developing only, for debugging purpose
info Production optionally, Course grained (rarely written information), I use it to print that a configuration is initialized, a long running import job is starting and ending.
warn Production, simple application error or unexpected behavior. Application can continue. I warn for example in case of bad login attempt, unexpected data during import jobs
error Production, application error/exception but application can continue. Part of the application is probably not working.
fatal Production, fatal application error/exception, application cannot continue, for example database is down.




Monitoring Memory in Java

There are a couple of options for measuring the amount of memory a program uses. The simplest one, which does not require any tools and works even with production systems, is the Verbose GC log.

Verbose GC Log

The Verbose GC log is defined when the JVM process is started. There are a couple of switches that can be used:

1.        -verbose:gc — prints basic information about GC to the standard output

2.        -XX:+PrintGCTimeStamps — prints the times that GC executes

3.        -XX:+PrintGCDetails — prints statistics about different regions of memory in the JVM

4.        -Xloggc:<file> — logs the results of GC in the given file

The following is an example of the output generated for Tomcat running in the default configuration with all of the previous switches enabled:

1.854: [GC 1.854: [DefNew: 570K->62K(576K), 0.0012355 secs] 2623K->2175K(3980K), 0.0012922 secs]
1.871: [GC 1.871: [DefNew: 574K->55K(576K), 0.0009810 secs] 2687K->2229K(3980K), 0.0010752 secs]
1.881: [GC 1.881: [DefNew: 567K->30K(576K), 0.0007417 secs] 2741K->2257K(3980K), 0.0007947 secs]
1.890: [GC 1.890: [DefNew: 542K->64K(576K), 0.0012155 secs] 2769K->2295K(3980K), 0.0012808 secs]

The most important set of numbers is located in the second column after the second -> (e.g., in the top line shown it is 2623K->2175K(3980K). These numbers indicate that as a result of GC, we are using around 2200K of memory at the end of each GC cycle.

This trace is not an indication of a memory leak—it shows a short-term trend with less then a second between samples, and that's why we must observe long-term trends. However, if the Verbose GC log showed that the program was using around 2200K of memory after running for two days, and after running for 10 days it was using 2GB of memory (even after GC had just run), we could then conclude that there's a memory leak.

All the information that needs to be collected in order to determine if a memory leak exists can be found in the results of the Verbose GC logs.

Monitoring the Java Process

The following approach works for any Java process, including standalone clients as well as application servers like JBoss and servlet containers like Tomcat. It is based on starting the Java process with JMX monitoring enabled and attaching with the JMX monitoring tools. We'll use Tomcat in the following example.

To start Tomcat or the Java process with JMX monitoring enabled, use the following options when starting JVM:

·        -Dcom.sun.management.jmxremote — enables JMX monitoring

·        -Dcom.sun.management.jmxremote.port=<port> — controls the port for JMX monitoring

Note that if you're on a production system, you'll most likely want to secure your JVM before running it with these parameters. For that, you can specify these additional options:

·        com.sun.management.jmxremote.ssl

·        com.sun.management.jmxremote.authenticate

Once started, you can use JConsole or VisualVM to attach to the process. Note that later JDK 6 versions include VisualVM.

Heap Dump

A heap dump is a list of objects in the memory of JVM as well as the content of the memory occupied by those objects. It preserves the value of any attributes of the objects, including references to other objects. In other words, a heap dump gives you a complete picture of the memory.

There are multiple tools that allow you to dump heap in a Java process:

·        If you're using JDK 6, you can use tool called jmap on any platform.

·        If you're using JDK 5, the situation is slightly more complex:

·        If you're running UNIX (Linux, Solaris, OS X) with JDK 5 you can use jmap.

·        If you're using JDK 5 update 14 or later, you can use the -XX:+HeapDumpOnCtrlBreak option when starting JVM, then use the CTRL+BREAK key combination on Windows (or CTRL + \ on UNIX) to dump the heap.

·        If you're running Windows and using JDK 5 pre-update 14, you'll soon wish you weren't. Trying to reproduce the problem with a more recent JDK is probably the best bet here.

Some tools like VisualVM and memory profilers allow you to initiate a heap dump from the GUI, but you don't need any fancy tools here—jmap will do just fine. As it provides the most general case, we'll use jmap in the next example.

Before you dump heap, be sure to keep the following issues in mind:

·        Programs in the JVM should be paused for the duration of the heap dump, which might take anywhere from ten seconds to several minutes. Many enterprise applications—and users of those applications—don't take kindly to pauses that long, which may cause various timeouts to expire. So don't try this at home or in production (unless the application is already a goner)!

·        Heap dumps are saved on disk, and the files might be fairly large. A good rule is to make sure that you have at least twice the size of the physical memory free on the disk before you initiate a memory dump.

With those final words of caution out of the way, you should now be ready to run the following command:

        jmap -heap:live,format=b,file=FILENAME PID

Note that the -F option, which will dump non-responsive programs, might be useful on UNIX systems, but is not available on Windows. Note also that JDK 6 includes the option +XX:+HeapDumpOnOutOfMemoryError that will dump heap whenever the OutOfMemoryError alert is encountered. This can be a useful option, but keep in mind that it has the potential to consume significant amounts of disk space.

You now have a heap dump in the file FILENAME and are ready to analyze it.

What's In "Leaked" Memory?

With the heap dump complete, we can now take a look at the memory and find out what's really causing the memory leak.

Suppose that objects are holding references to each other as illustrated by the picture below. For the sake of easy calculation, let's assume that each object is 100 bytes, so that all of them together occupy 600 bytes of memory.

Now, suppose that the program holds reference to object A for a prolonged period of time. As a result, objects B, C, D, E, and F are all ineligible for garbage collection, and we have the following amount of memory leaking:

·        100 bytes for object A

·        500 bytes for objects B, C, D, E and F that are retained due to the retention of object A

So, holding reference to object A causes a memory leak of 600 bytes. The shallow heap of object A is 100 bytes (object A itself), and the retained heap of object A is 600 bytes.

Although objects A through F are all leaked, the real cause of the memory leak is the program holding reference to object A. So how can we fix the root cause of this leak? If we first identify that object F is leaked, we can follow the reference chain back through objects D, C and A to find the cause of the memory leak. However, there are some complications to this "follow the reference chain" process:

·        Reference chains can be really long, so manually following them can be time consuming

·        An object is sometimes retained by more than one object, and there can even be circles involved as shown in the picture below:

If we start following inbound references from object F in this example, we have to choose between following object C or object D. In addition, there's the possibility of getting caught in a circle by repeatedly following the path between objects D, E and B. On this small diagram it's easy to see that the root cause is holding object A, but when you're dealing with a situation that involves hundreds of thousands of objects (as any self-respecting memory leak does) you quickly realize that manually following the reference chain be very complex and time consuming.

This is where some shortcuts can come in handy:

·        If we had a tool that allowed us to play a "what would happen if I remove this reference" type of guessing game, we could run experiments that help locate the cause. For example, we could see that if we removed reference from "Cause of Leak" to A in the diagram above, objects A through F would all be freed. Some tools (like Quest's JProbe) have this capability.

·        If the memory leak is large and we have a tool that allows us to sort objects by retained heap, we'll get an even greater head start because the objects with the largest retained heap are usually the cause of large memory leaks.

Now that we understand what memory leaks are and how they can be corrected, let's find out how to fix them by analyzing heap dumps.

Tools for Dealing with Heap Dumps

Tools often provide a few extra helpful features –

·        Present a better summary of heap statistics.

·        Sort objects by retained heap. In other words, some tools can tell you the memory usage of an object and all other objects that are referenced by it, as well as list the objects referenced by other objects. This makes it much faster to diagnose the cause of a memory leak.

·        Function on machines that have less memory then the size of the heap dump. For example, they'll allow you to analyze a 16GB heap dump from your server on a machine with only 1GB of physical memory.

VisualVM is nice tool that gives you just enough to resolve memory leaks, and it shows heap dumps and relations between objects in graphical form.

Feature-wise, one step above VisualVM is the Eclipse Memory Analyzer Tool (MAT), a free tool that includes a lot of additional options. Although it's still in incubation phase as of publication of this article, MAT is free and we've found it to be extremely useful.

Commercial products like JProfiler, YourKit, and JProbe are also excellent tools for debugging memory leaks. These applications include a few options that go above and beyond VisualVM and MAT, but they're certainly not necessary to successfully debug memory leaks.

Dealing with Memory Leaks


What is it?

Memory leaks occur when a program never stops using an object, thus keeping a permanent reference to it. For Example –

class MemoryLeak {
private static List<Double> memoryLeakList = new ArrayList<Double>();
public static void main(String[] args){
        double d = 0.0;
        // infinite loop would eventually run out of memory
        while(true){
                Double dbl = new Double(d);
                memoryLeakList.add(dbl);
                d++;
}
}

}

If you run this program, When no more memory is remaining, an OutOfMemoryError alert will be thrown and generate an exception like this -
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space at
MemoryLeak.main(MemoryLeak.java:7)

In the example above, we continue adding new elements to the list memoryLeakArea without ever removing them. In addition, we keep references to the memoryLeakArea, thereby preventing GC from collecting the list itself. So although there is GC available, it cannot help because we are still using memory. The more time passes the more memory we use, which in effect requires an infinite amount memory for this program to continue running.

This is an example of unbounded memory leak—the longer the program runs, the more memory it takes. So even if the memory size is increased, the application will still run out of memory at a later date.

Determining if an application has a memory leak

To understand what is going on, we need to familiarize ourselves with how the JVM uses system memory for its heap. When running java.exe, you can use certain options to control the startup and maximum size of the garbage-collected heap (-ms and -mx, respectively). The Sun JDK 1.1.8 uses a default 1 MB startup setting and a 16 MB maximum setting. The IBM JDK 1.1.8 uses a default maximum setting of one-half the total physical memory size of the machine. These memory settings have a direct impact on what the JVM does when it runs out of memory. The JVM may continue growing the heap rather than wait for a garbage collection cycle to complete.

So for the purposes of finding and eventually eliminating a memory leak, we are going to need better tools than task monitoring utility programs. Memory debugging programs can come in handy when you're trying to detect memory leaks. These programs typically give you information about the number of objects in the heap, the number of instances of each object, and the memory being using by the objects. In addition, they may also provide useful views showing each object's references and referrers so that you can track down the source of a memory leak.

This example I have taken from http://java.dzone.com

Not every OutOfMemoryError alert indicates that a program is suffering from a memory leak. Some programs simply need more memory to run. In other words, some OutOfMemoryError alerts are caused by the load, not by the passage of time, and as a result they indicate the need for more memory in a program rather than a memory leak.

To distinguish between a memory leak and an application that simply needs more memory, we need to look at the "peak load" concept. When program has just started no users have yet used it, and as a result it typically needs much less memory then when thousands of users are interacting with it. Thus, measuring memory usage immediately after a program starts is not the best way to gauge how much memory it needs! To measure how much memory an application needs, memory size measurements should be taken at the time of peak load—when it is most heavily used.

The graph below shows the memory usage in a healthy Java application that does not suffer from memory leaks, with the peak load occurring around 10 AM and application usage drastically decreasing at 5 PM. Naturally, the peak load on business applications often correlates with normal business hours.

JVM Performance Tuning


The application server, being a Java process, requires a Java virtual machine (JVM) to run, and to support the Java applications running on it. As part of configuring an application server, you can fine-tune settings that enhance system use of the JVM

Heap Size

The allocation of memory for the JVM is specified using -X options
Options Meaning
-Xms initial java heap size
-Xmx maximum java heap size
-Xmn the size of the heap for the young generation



It is good practice with server-side Java applications like Resin to set the minimum -Xms and maximum -Xmx heap sizes to the same value.

For efficient garbage collection, the -Xmn value should be lower than the -Xmx value.

Heap size does not determine the amount of memory your process uses. If you monitor your java process with an OS tool like top or taskmanager, you may see the amount of memory you use exceed the amount you have specified for -Xmx. -Xmx limits the java heap size, java will allocate memory for other things, including a stack for each thread. It is not unusual for the total memory consumption of the VM to exceed the value of -Xmx.

Stack Size

Each thread in the VM get's a stack. The stack size will limit the number of threads that you can have, too big of a stack size and you will run out of memory as each thread is allocated more memory than it needs.
Options Meaning
-Xss the stack size for each thread


-Xss determines the size of the stack: -Xss1024k. If the stack space is too small, eventually you will see an exception java.lang.StackOverflowError.

JVM Runtime Data Areas


The Java virtual machine defines various runtime data areas that are used during execution of a program. Some of these data areas are created on Java virtual machine start-up and are destroyed only when the Java virtual machine exits. Other data areas are per thread. Per-thread data areas are created when a thread is created and destroyed when the thread exits

Stack

Stack is a memory place where the methods and the local variables are stored. Variable references (either primitive or object references) are stored in the Stack. Each thread has a private stack, which stores frames.

The following exceptional conditions are associated with Java virtual machine stacks

·        If the computation in a thread requires a larger Java virtual machine stack than is permitted, the Java virtual machine throws a StackOverflowError.

·        If Java virtual machine stacks can be dynamically expanded, and expansion is attempted but insufficient memory can be made available to effect the expansion, or if insufficient memory can be made available to create the initial Java virtual machine stack for a new thread, the Java virtual machine throws an OutOfMemoryError


Heap
Heap is a memory place where the objects and its instance variable are stored. Each time an object is created in Java it goes into the area of memory known as heap.


Information about HEAP
·        The heap is created on virtual machine start-up.
·        Heap storage for objects is reclaimed by an automatic storage management system (known as a garbage collector); objects are never explicitly deallocated.
·        The heap may be of a fixed size or may be expanded as required by the computation and may be contracted if a larger heap becomes unnecessary.
·        The memory for the heap does not need to be contiguous.

A Java virtual machine implementation may provide the programmer or the user control over the initial size of the heap, as well as, if the heap can be dynamically expanded or contracted, control over the maximum and minimum heap size.

The following exceptional condition is associated with the heap:

·        If a computation requires more heap than can be made available by the automatic storage management system, the Java virtual machine throws an OutOfMemoryError

Heap and stack are the two main memories that JVM is concerned as far as memory allocation by the OS (operating system) is concerned. Stack and heap are the memories allocated by the OS to the JVM that runs in the system.

The primitive variables like int and double are allocated in the stack, if they are local method variables and in the heap if they are member variables (i.e. fields of a class). In Java methods local variables are pushed into stack when a method is invoked and stack pointer is decremented when a method call is completed. In a multi-threaded application each thread will have its own stack but will share the same heap. This is why care should be taken in your code to avoid any concurrent access issues in the heap space. The stack is 'threadsafe' (each thread will have its own stack) but the heap is not 'threadsafe' unless guarded with synchronization through your code.

Method Area
It is shared among all threads. It stores per-class structures such as the runtime constant pool, field and method code. It is logically part of the heap. Memory for class (static) variables and methods declared in the class is also taken from it.

Runtime Constant Pool Or Constant Pool
It is a per-class or per-interface runtime representation of the constant_pool table. The JVM maintains a per-type constant pool, including literals (string, integer, and floating point constants). Each runtime constant pool is allocated from the JVM method area.

Frame or Stack Frame

Frame holds local variables (including parameters), operand stack and partial results, and plays a part in method invocation and return. A new frame is created each time a method is invoked and is destroyed on method completion. Each frame has a reference to the runtime constant pool of the class of the current method.

PC Register
The Java virtual machine can support many threads of execution at once. Each Java virtual machine thread has its own pc (program counter) register. At any point, each Java virtual machine thread is executing the code of a single method, the current method for that thread. If that method is not native, the pc register contains the address of the Java virtual machine instruction currently being executed. If the method currently being executed by the thread is native, the value of the Java virtual machine's pc register is undefined. The Java virtual machine's pc register is wide enough to hold a returnAddress or a native pointer on the specific platform.

An Example –
class Memory {
        static int x;                                                 /* static stack storage*/
public static void main(String[] args){                
Memory memory = new Memory();         /* dynamic heap storage*/
                int y =0;                                         /* dynamic  stack storage */
                String myString = new String("Memory");        /* dynamic  heap storage */
}
}
When you create an object using the new operator, for example memory = new Memory();, it allocates memory for the memory object on the heap. The stack memory space is used when you declare automatic variables.

Note, when you do a string initialization, for example String myString;, it is a reference to an object so it will be created using new and hence it will be placed on the heap.

Memory space for objects is always allocated in heap. Objects are placed on the heap. Built-in datatypes like int, double, float and parameters to methods are allocated on the stack.

Most commonly used Java method or Function


****************************************************************************************************************************************
public static String getDisplayDate(String dt_str) {
                if (dt_str != null) {
                        int mm, yy;
                        String yys = "", mms = "", dds = "";
                        Calendar cal = Calendar.getInstance();
                        cal.setTime(java.sql.Date.valueOf(dt_str));

                        dds = "" + cal.get(Calendar.DATE);
                        mm = cal.get(Calendar.MONTH) + 1;
                        mms = "" + mm;
                        yy = cal.get(Calendar.YEAR);
                        yys = "" + yy;

                        if (dds.length() < 2)
                                dds = "0" + dds;
                        if (mms.length() < 2)
                                mms = "0" + mms;
                        return dds + "/" + mms + "/" + yys;
                } else
                        return null;
        }
****************************************************************************************************************************************
        public static String getDisplayDate(Date dt_str) {
                return getDisplayDate(dt_str + "");
        }
****************************************************************************************************************************************
        public static String getInstancePath(javax.servlet.http.HttpServletRequest request) {
                String servername = request.getRequestURI();
                servername = servername.substring(0, servername.lastIndexOf('/'));
                return "http://"
                        + request.getServerName()
                        + ":"
                        + request.getServerPort()
                        + servername;
        }
****************************************************************************************************************************************
        public static String getServerPath() {
                ResourceBundle rbundle = ResourceBundle.getBundle("Application");
                String serverName = rbundle.getString("servername");
                String serveruri = rbundle.getString("serveruri");
                return "http://" + serverName + "/" + serveruri;

        }
****************************************************************************************************************************************
        public static String getPortalURL() {
                ResourceBundle rbundle = ResourceBundle.getBundle("Application");
                return rbundle.getString("portaldoclink");

        }
****************************************************************************************************************************************
        public static String intArrToString(int[] arr, String sep) {
                StringBuffer str = new StringBuffer();
                if (arr != null) {
                        for (int i = 0; i < arr.length; i++) {
                                str.append(arr[i]);
                                str.append(sep);
                        }
                        str.setLength(str.length() - sep.length());
                        return str.toString();
                } else {
                        return null;
                }
        }
****************************************************************************************************************************************
        public static String remNewLineChar(String checkStr) {
                String finalstr = "";

                if (checkStr != null)
                        for (int i = 0; i < checkStr.length(); i++) {
                                if ((checkStr.charAt(i) == 13) && (checkStr.charAt(i + 1) == 10)) {
                                        i++;
                                        finalstr += "\\n";
                                } else
                                        finalstr += checkStr.charAt(i);
                        }
                return finalstr;
        }

****************************************************************************************************************************************        
public static String[] splitstr(String inpstr, String sep) {
                if (inpstr != null) {
                        StringTokenizer str = new StringTokenizer(inpstr, sep);
                        int count = str.countTokens();
                        String arr_str[] = new String[count];
                        for (int i = 0; i < count; i++) {
                                arr_str[i] = str.nextToken(sep);
                        }
                        return arr_str;
                } else
                        return null;
        }
****************************************************************************************************************************************
        public static int[] toIntArr(String[] strarr) throws Exception {
                int a[] = null;
                if (strarr != null) {
                        a = new int[strarr.length];
                        for (int i = 0; i < strarr.length; i++) {
                                try {
                                        if (strarr[i] != null && !(strarr[i].trim().equals("")))
                                                a[i] = Integer.parseInt(strarr[i].trim());
                                        else
                                                a[i] = 0;
                                } catch (Exception ex) {
                                        throw new Exception("Error while trying to parseInt " + strarr[i]);
                                }
                        }
                }
                return a;
        }
****************************************************************************************************************************************
        public static String toString(String str) {

                if ((str != null) && !(str.trim().equals(""))) {
                        int first = 0;
                        int next = 0;
                        int indexap = 0;
                        str = str.trim();
                        while ((!(next < 0)) && (next < str.length())) {

                                indexap = str.indexOf("'", first);
                                if (!(indexap < 0)) {
                                        str = str.substring(0, indexap) + "'" + str.substring(indexap);
                                }
                                next = indexap;
                                first = next + 2;
                        }
                        first = 0;
                        next = 0;
                        indexap = 0;
                        str = str.trim();
                        while ((!(next < 0)) && (next < str.length())) {

                                indexap = str.indexOf("\"", first);
                                if (!(indexap < 0)) {
                                        str = str.substring(0, indexap) + "\"" + str.substring(indexap);
                                }
                                next = indexap;
                                first = next + 2;
                        }

                        return "'" + str + "'";
                } else {
                        return null;
                }

        }
****************************************************************************************************************************************
        public String toTrim(String str) {
                int next = 0;
                int indexap = 0;
                str = str.trim();
                while ((!(next < 0)) && (next < str.length())) {
                        indexap = str.indexOf("  ");
                        if (!(indexap < 0)) {
                                if (str.substring(indexap) != null
                                        && !(str.substring(indexap).trim().equals(""))) {
                                        str = str.substring(0, indexap) + " " + str.substring(indexap).trim();
                                }
                        }
                        next = indexap;

                }
                while ((!(next < 0)) && (next < str.length())) {
                        indexap = str.indexOf("\n");
                        if (!(indexap < 0)) {
                                if (str.substring(indexap) != null
                                        && !(str.substring(indexap).trim().equals(""))) {
                                        str = str.substring(0, indexap) + " " + str.substring(indexap).trim();
                                }
                        }
                        next = indexap;

                }
                while ((!(next < 0)) && (next < str.length())) {
                        indexap = str.indexOf("\r");
                        if (!(indexap < 0)) {
                                if (str.substring(indexap) != null
                                        && !(str.substring(indexap).trim().equals(""))) {
                                        str = str.substring(0, indexap) + " " + str.substring(indexap).trim();
                                }
                        }
                        next = indexap;

                }
                return str;
        }
****************************************************************************************************************************************
        public int getNoOfdays(Timestamp t1, Timestamp t2) {
                try {
                        if (t1 == null)
                                t1 = getCurrentTS();
                        if (t2 == null)
                                t2 = getCurrentTS();
                } catch (Exception e) {
                }
                Long l1 = new Long(t1.getTime());
                Long l2 = new Long(t2.getTime());
                Double d2 = new Double((l1.doubleValue() - l2.doubleValue()) / 86400000);
                return d2.intValue();
        }
****************************************************************************************************************************************