Showing posts with label Profiling. Show all posts
Showing posts with label Profiling. Show all posts

Apr 26, 2010

Garbage Collection and Heap Memory Management with Java

This article has been prepared to understand the process of Garbage Collection. This includes how the JVM carry out the memory reclaim process from heap. This document also covers the JVM and Tomcat server settings and precautions need to take while coding which we can use to use the better heap memory.

Overview:

Mostly the programmers especially java people think that they are not at all required to worry about the internal memory allocation and freeing that memory. It is simply assumed that create the objects, use it and java will take care of the removing or freeing the allocated memory through the mechanism like Garbage Collection. Due to this it is assumed that Java has resolved one of the nasty problems that plague other programming languages—the dreaded memory leak. But the question is “Is it true?”

Enterprise applications written in the Java language involve complex object relationships and utilize large numbers of objects. Although, the Java language automatically manages memory associated with object life cycles, understanding the application usage patterns for objects is important. In particular, verify the following:


  • The application is not over-utilizing objects.
  • The application is not leaking objects.
  • The Java heap parameters are set properly to handle a given object usage pattern.

Understanding the effect of garbage collection is necessary to apply these management techniques

.

Garbage Collection

The garbage collector first performs a task called marking. The garbage collector traverses the application graph, starting with the root objects; those are objects that are represented by all active stack frames and all the static variables loaded into the system. Each object the garbage collector meets is marked as being used, and will not be deleted in the sweeping stage.

The sweeping stage is where the deletion of objects takes place. There are many ways to delete an object: The traditional C way was to mark the space as free, and let the allocator methods use complex data structures to search the memory for the required free space. This was later improved by providing a defragmenting system which compacted memory by moving objects closer to each other, removing any fragments of free space and therefore allowing allocation to be much faster:


clip_image002

For the last trick to be possible a new idea was introduced in garbage collected languages: even though objects are represented by references, much like in C, they don’t really reference their real memory location. Instead, they refer to a location in a dictionary which keeps track of where the object is at any moment.

Fortunately for us - but unfortunately for these garbage collection algorithms - our servers and personal computers got faster (and multiple) processors and bigger memory capacities. Compacting memory areas this large often was very taxing on the application, especially considering that when doing that, the whole application had to freeze due to the changes in the virtual memory map. Fortunately for us though, some smart people improved those algorithms in three ways: concurrency, parallelization and generational collection.


Garbage Collection Algorithms

There are around six basic garbage collection strategies with JDK 1.4.2 version and more that dozens of command line options for tuning and configuring it. The use of all the garbage collection algorithms are same that is to identify the memory blocks that are not reachable by the user programs resulting in the OutOfMemory issues. Below are the algorithms that are used for garbage collection.

1 – Reference Counting:

Each object has an associated reference count. This count indicates the number of active references to that object. If this count is zero, it is garbage and can be recycled. Whenever the reference is modified, the count is updated. Once this count is zero, the memory is reclaimed.

2 – Tracing Collectors:

Mostly the standard garbage collectors do not use Reference Counting. They will use some form of tracing collector’s algorithms. This algorithm will trace all objects starting from root until all reachable objects have been examined.

3 – Mark-Sweep collectors:

This is most basic form of collector algorithm. In this case the collector visits each node starting from root and marks each node. Once there are no any references, the collection is complete. The heap is swept and the objects not marked are reclaimed and returned to free list.

4 – Copying Collectors:

In this case, the heap is divided into equally sized semi spaces. One with active data and another with unused. Once the active space fills up, the objects are copied from active to unused space and the roles are flipped becoming unused space as active. This has advantages as it examines only active data. But will have a overhead of copying data from active to unused space.

5 – Heap Compaction:

In the copying collectors, the set of live objects can be compacted at the bottom of heap. This improves locality of reference and eliminates heap fragmentation and greatly reduces the cost of object allocation which eliminates the need to maintain free lists or look-aside lists or perform best-fit or first-fit algorithms and allocating N bytes is simple to add N to heal pointer.

6 – Mark-compact collectors:

The copying algorithm has excellent performance characteristics, but it has the drawback of requiring twice as much memory as a mark-sweep collector. The mark-compact algorithm combines mark-sweep and copying in a way that avoids this problem, at the cost of some increased collection complexity. Like mark-sweep, mark-compact is a two-phase process, where each live object is visited and marked in the marking phase. Then, marked objects are copied such that all the live objects are compacted at the bottom of the heap. If a complete compaction is performed at every collection, the resulting heap is similar to the result of a copying collector -- there is a clear demarcation between the active portion of the heap and the free area, so that allocation costs are comparable to a copying collector. Long-lived objects tend to accumulate at the bottom of the heap, so they are not copied repeatedly as they are in a copying collector.

JDK uses all of the algorithms in some sense. Early JDK used mark-sweep and mark-compact while version 1.2 and later employed a hybrid approach called generational approach. In this the heap is divided into multiple generations. Objects are created in young generation and the objects that meet some criteria are promoted to older generation. It can use different collection strategy for different generations separately.

By default, the 1.4.1 JDK divides the heap into two sections, a young generation and an old generation. (Actually, there is also a third section, the permanent space, which is used for storing loaded class and method objects.) The young generation is divided into a creation space, often called Eden, and two survivor semi-spaces, using a copying collector.

Reasons for OutOfMemoryError errors

1. You are out of memory. Add more to your heap.

2. You are out of memory. The code is hanging on to object references and a GC can’t do the job. Use the profiler to debug this code.

3. You ran out of file descriptors. This can happen if the threshold is too low.

4. You have too many threads running. Some OS have limits to the number of threads which may be executed by the process. Refer to your OS docs to raise this threshold.

5. If you have a lot of servlets or JSPs, you may need to increase your permanent generation. By default it is 64M. Quadrupling it to be –XX:maxPermSize=256m can be good start.

6. Your OS limits the amount of memory your process may take.

7. The JVM has a bug. This has been known to happen with JVM1.2 and using EJBs with another servlet engine.

8. On the platform look for the java –X options. This may be very helpful.


Garbage Collection Tips and Memory Leaks in Coding Context

1 Small Objects:

Small objects are easy to allocate while large objects will be allocated directly in old generation heap area, take long to initialize and might cause fragmentation. It is always better to allocate small immutable objects. The mutable objects will eventually make your code more obscure at best, or fragment the memory and confuse GC at worst.

2 Non Uniformed Memory Access:

Keep your objects constrained to single thread as much as possible. This will increase the memory usage performance. The basic idea of Non Uniformed Memory Access is to provide increased performance for processors by allowing each processor to work with specific memory space.

3 Object Pools:

Allocation of majority of objects is faster. So there is no any need to have pools for objects as they create issues except for the reasons like creation and initialization of objects are more expensive like connections. The issues are like an unused object takes memory for no reason. Also synchronization is required to fetch an object which is slow process.

4 Finalizable Object:

When a finalizable object is allocated it is marked as such. When the application has no more references to it, the GC enqueue it in the object finalization queue. The JVM has a thread dedicated to removing elements from this queue and calling the finalize method on them; however, to keep the data integrity on the object, the GC does not claim it and traverses its tree as a live object! Only after the object’s finalize method gets called, the object and the references it contains are allowed to be claimed.

Memory

Leaks:
  • While the GC does a great job at removing unreachable objects, it doesn’t help against memory leaks as they might occur by sloppy code which leaves references to unused objects. The following list contains the common trouble-makers and some solutions:
  • Objects defined in higher scope than they should might stay will stay alive longer than expected. Always define the objects in the lowest scope possible for them.
  • Listeners for Observable objects which were not removed after their task was done will stay alive, receive events and spend processor and memory resources for no reason. Always make sure the listeners are removed from their Observable class when they are not needed anymore.
  • Always use the finally clause when removing references to listeners or other type of objects from usually persistent collections.
  • Instances of inner class contain references to their outer classes. You must be aware of this behavior and if you don’t use the outer class, define the inner class as static.
  • Using Maps, the kept object usually should remove themselves from the Map when their use is over which is often forgotten. Luckily WeakHashMap keeps the keys as weak references and should be used for such metadata.
  • And the use of finalize() method which might be extremely slow and delay the claiming of new memory spaces or even do worse and resurrect the finalize object.
  • If the Collection objects are used to store user defined objects, set the reference to null (for the root object) once you have finished with. This way the total memory will be available for garbage collection.

Tomcat Server Settings for Heap Usage

We can reset the heap memory size which is used by Tomcat server. This is achieved by setting the environmental variable CATALINA_OPTS in startup.sh. Below are the environmental variables which can be set to have max and min limit for heap memory usage by Tomcat and JVM.

1 - CATALINA_OPTS

This variable is used to set minimum and maximum heap memory that Tomcat uses. This variable is set in startup.sh for Linux and in startup.bat for Windows platforms. Below is the syntax for both

For Windows -

Set CATALINA_OPTS=”-Xms256m –Xmx1024m”

For UNIX –

export CATALINA_OPTS=”-Xms256m –Xmx1024m”

2 – JAVA_OPTS

This variable is used to set minimum and maximum heap memory that JVM uses. This is also set in startup.sh for Linux and startup.bat for Windows platforms. Below is the syntax to set in both environments

For Windows –

Set JAVA_OPTS=”-Xms256m –Xmx1024m”

For UNIX –

Export JAVA_OPTS=”-Xms256m –Xmx1024m”

In both of these settings –Xms indicates the minimum heap size Tomcat or JVM will use. And –Xmx indicates the maximum heap size that will be used. The setting of these parameters will also decide the garbage collection cycles. So this minimum and maximum number should be set accordingly. Also if the maximum limit is much more, it may happen that GC will take long to check the unreachable objects which will again cause the memory issues. So we should be cautious while setting the minimum and maximum limits.

Memory profiling Tools

There are various tools available which can carry out the profiling of memory used by java programs. Heap profiling provides the information about memory allocation footprints of the application. We can do following tasks through these tools –
  • Observer Garbage Collection cycles
  • Can observer memory utilizations
  • Can observer CPU utilizations
  • Can check the Object references

Some of the tools and utilities like jmap, jhat, NetBean’s profiler, JProbe etc can be used for such purposes. These can read the heap dump files also and can provide you the visual representations. This is the tool which can do all above functions and can provide many charts that will help developer to analyze the memory related issues in java code. Below is the graph that may be seen in JProbe.


clip_image004

The JProbe Memory Debugger allows developers to observe and record how an application is using memory as it runs. This, as with the Profiler, was surprisingly fast considering the overhead that is surely involved. A graph records memory usage (not unlike the Performance Monitor in Windows) at regular intervals that are user selectectable. Additionally, the Memory Leak Doctor will allow developers to take a more granular look at what is going on inside the application and help to identify the key causes.

Conclusion

By looking at the tips given above the developers can avoid the issues related to memory. Also the developers can make use of the available profiling tools which are helpful in identifying the memory leaks and improve the performance.


Garbage Collection and Heap Memory Management with Java

This article has been prepared to understand the process of Garbage Collection. This includes how the JVM carry out the memory reclaim process from heap. This document also covers the JVM and Tomcat server settings and precautions need to take while coding which we can use to use the better heap memory.

Overview:

Mostly the programmers especially java people think that they are not at all required to worry about the internal memory allocation and freeing that memory. It is simply assumed that create the objects, use it and java will take care of the removing or freeing the allocated memory through the mechanism like Garbage Collection. Due to this it is assumed that Java has resolved one of the nasty problems that plague other programming languages—the dreaded memory leak. But the question is “Is it true?”

Enterprise applications written in the Java language involve complex object relationships and utilize large numbers of objects. Although, the Java language automatically manages memory associated with object life cycles, understanding the application usage patterns for objects is important. In particular, verify the following:


  • The application is not over-utilizing objects.
  • The application is not leaking objects.
  • The Java heap parameters are set properly to handle a given object usage pattern.

Understanding the effect of garbage collection is necessary to apply these management techniques

.

Garbage Collection

The garbage collector first performs a task called marking. The garbage collector traverses the application graph, starting with the root objects; those are objects that are represented by all active stack frames and all the static variables loaded into the system. Each object the garbage collector meets is marked as being used, and will not be deleted in the sweeping stage.

The sweeping stage is where the deletion of objects takes place. There are many ways to delete an object: The traditional C way was to mark the space as free, and let the allocator methods use complex data structures to search the memory for the required free space. This was later improved by providing a defragmenting system which compacted memory by moving objects closer to each other, removing any fragments of free space and therefore allowing allocation to be much faster:


clip_image002

For the last trick to be possible a new idea was introduced in garbage collected languages: even though objects are represented by references, much like in C, they don’t really reference their real memory location. Instead, they refer to a location in a dictionary which keeps track of where the object is at any moment.

Fortunately for us - but unfortunately for these garbage collection algorithms - our servers and personal computers got faster (and multiple) processors and bigger memory capacities. Compacting memory areas this large often was very taxing on the application, especially considering that when doing that, the whole application had to freeze due to the changes in the virtual memory map. Fortunately for us though, some smart people improved those algorithms in three ways: concurrency, parallelization and generational collection.


Garbage Collection Algorithms

There are around six basic garbage collection strategies with JDK 1.4.2 version and more that dozens of command line options for tuning and configuring it. The use of all the garbage collection algorithms are same that is to identify the memory blocks that are not reachable by the user programs resulting in the OutOfMemory issues. Below are the algorithms that are used for garbage collection.

1 – Reference Counting:

Each object has an associated reference count. This count indicates the number of active references to that object. If this count is zero, it is garbage and can be recycled. Whenever the reference is modified, the count is updated. Once this count is zero, the memory is reclaimed.

2 – Tracing Collectors:

Mostly the standard garbage collectors do not use Reference Counting. They will use some form of tracing collector’s algorithms. This algorithm will trace all objects starting from root until all reachable objects have been examined.

3 – Mark-Sweep collectors:

This is most basic form of collector algorithm. In this case the collector visits each node starting from root and marks each node. Once there are no any references, the collection is complete. The heap is swept and the objects not marked are reclaimed and returned to free list.

4 – Copying Collectors:

In this case, the heap is divided into equally sized semi spaces. One with active data and another with unused. Once the active space fills up, the objects are copied from active to unused space and the roles are flipped becoming unused space as active. This has advantages as it examines only active data. But will have a overhead of copying data from active to unused space.

5 – Heap Compaction:

In the copying collectors, the set of live objects can be compacted at the bottom of heap. This improves locality of reference and eliminates heap fragmentation and greatly reduces the cost of object allocation which eliminates the need to maintain free lists or look-aside lists or perform best-fit or first-fit algorithms and allocating N bytes is simple to add N to heal pointer.

6 – Mark-compact collectors:

The copying algorithm has excellent performance characteristics, but it has the drawback of requiring twice as much memory as a mark-sweep collector. The mark-compact algorithm combines mark-sweep and copying in a way that avoids this problem, at the cost of some increased collection complexity. Like mark-sweep, mark-compact is a two-phase process, where each live object is visited and marked in the marking phase. Then, marked objects are copied such that all the live objects are compacted at the bottom of the heap. If a complete compaction is performed at every collection, the resulting heap is similar to the result of a copying collector -- there is a clear demarcation between the active portion of the heap and the free area, so that allocation costs are comparable to a copying collector. Long-lived objects tend to accumulate at the bottom of the heap, so they are not copied repeatedly as they are in a copying collector.

JDK uses all of the algorithms in some sense. Early JDK used mark-sweep and mark-compact while version 1.2 and later employed a hybrid approach called generational approach. In this the heap is divided into multiple generations. Objects are created in young generation and the objects that meet some criteria are promoted to older generation. It can use different collection strategy for different generations separately.

By default, the 1.4.1 JDK divides the heap into two sections, a young generation and an old generation. (Actually, there is also a third section, the permanent space, which is used for storing loaded class and method objects.) The young generation is divided into a creation space, often called Eden, and two survivor semi-spaces, using a copying collector.

Reasons for OutOfMemoryError errors

1. You are out of memory. Add more to your heap.

2. You are out of memory. The code is hanging on to object references and a GC can’t do the job. Use the profiler to debug this code.

3. You ran out of file descriptors. This can happen if the threshold is too low.

4. You have too many threads running. Some OS have limits to the number of threads which may be executed by the process. Refer to your OS docs to raise this threshold.

5. If you have a lot of servlets or JSPs, you may need to increase your permanent generation. By default it is 64M. Quadrupling it to be –XX:maxPermSize=256m can be good start.

6. Your OS limits the amount of memory your process may take.

7. The JVM has a bug. This has been known to happen with JVM1.2 and using EJBs with another servlet engine.

8. On the platform look for the java –X options. This may be very helpful.


Garbage Collection Tips and Memory Leaks in Coding Context

1 Small Objects:

Small objects are easy to allocate while large objects will be allocated directly in old generation heap area, take long to initialize and might cause fragmentation. It is always better to allocate small immutable objects. The mutable objects will eventually make your code more obscure at best, or fragment the memory and confuse GC at worst.

2 Non Uniformed Memory Access:

Keep your objects constrained to single thread as much as possible. This will increase the memory usage performance. The basic idea of Non Uniformed Memory Access is to provide increased performance for processors by allowing each processor to work with specific memory space.

3 Object Pools:

Allocation of majority of objects is faster. So there is no any need to have pools for objects as they create issues except for the reasons like creation and initialization of objects are more expensive like connections. The issues are like an unused object takes memory for no reason. Also synchronization is required to fetch an object which is slow process.

4 Finalizable Object:

When a finalizable object is allocated it is marked as such. When the application has no more references to it, the GC enqueue it in the object finalization queue. The JVM has a thread dedicated to removing elements from this queue and calling the finalize method on them; however, to keep the data integrity on the object, the GC does not claim it and traverses its tree as a live object! Only after the object’s finalize method gets called, the object and the references it contains are allowed to be claimed.

Memory

Leaks:
  • While the GC does a great job at removing unreachable objects, it doesn’t help against memory leaks as they might occur by sloppy code which leaves references to unused objects. The following list contains the common trouble-makers and some solutions:
  • Objects defined in higher scope than they should might stay will stay alive longer than expected. Always define the objects in the lowest scope possible for them.
  • Listeners for Observable objects which were not removed after their task was done will stay alive, receive events and spend processor and memory resources for no reason. Always make sure the listeners are removed from their Observable class when they are not needed anymore.
  • Always use the finally clause when removing references to listeners or other type of objects from usually persistent collections.
  • Instances of inner class contain references to their outer classes. You must be aware of this behavior and if you don’t use the outer class, define the inner class as static.
  • Using Maps, the kept object usually should remove themselves from the Map when their use is over which is often forgotten. Luckily WeakHashMap keeps the keys as weak references and should be used for such metadata.
  • And the use of finalize() method which might be extremely slow and delay the claiming of new memory spaces or even do worse and resurrect the finalize object.
  • If the Collection objects are used to store user defined objects, set the reference to null (for the root object) once you have finished with. This way the total memory will be available for garbage collection.

Tomcat Server Settings for Heap Usage

We can reset the heap memory size which is used by Tomcat server. This is achieved by setting the environmental variable CATALINA_OPTS in startup.sh. Below are the environmental variables which can be set to have max and min limit for heap memory usage by Tomcat and JVM.

1 - CATALINA_OPTS

This variable is used to set minimum and maximum heap memory that Tomcat uses. This variable is set in startup.sh for Linux and in startup.bat for Windows platforms. Below is the syntax for both

For Windows -

Set CATALINA_OPTS=”-Xms256m –Xmx1024m”

For UNIX –

export CATALINA_OPTS=”-Xms256m –Xmx1024m”

2 – JAVA_OPTS

This variable is used to set minimum and maximum heap memory that JVM uses. This is also set in startup.sh for Linux and startup.bat for Windows platforms. Below is the syntax to set in both environments

For Windows –

Set JAVA_OPTS=”-Xms256m –Xmx1024m”

For UNIX –

Export JAVA_OPTS=”-Xms256m –Xmx1024m”

In both of these settings –Xms indicates the minimum heap size Tomcat or JVM will use. And –Xmx indicates the maximum heap size that will be used. The setting of these parameters will also decide the garbage collection cycles. So this minimum and maximum number should be set accordingly. Also if the maximum limit is much more, it may happen that GC will take long to check the unreachable objects which will again cause the memory issues. So we should be cautious while setting the minimum and maximum limits.

Memory profiling Tools

There are various tools available which can carry out the profiling of memory used by java programs. Heap profiling provides the information about memory allocation footprints of the application. We can do following tasks through these tools –
  • Observer Garbage Collection cycles
  • Can observer memory utilizations
  • Can observer CPU utilizations
  • Can check the Object references

Some of the tools and utilities like jmap, jhat, NetBean’s profiler, JProbe etc can be used for such purposes. These can read the heap dump files also and can provide you the visual representations. This is the tool which can do all above functions and can provide many charts that will help developer to analyze the memory related issues in java code. Below is the graph that may be seen in JProbe.


clip_image004

The JProbe Memory Debugger allows developers to observe and record how an application is using memory as it runs. This, as with the Profiler, was surprisingly fast considering the overhead that is surely involved. A graph records memory usage (not unlike the Performance Monitor in Windows) at regular intervals that are user selectectable. Additionally, the Memory Leak Doctor will allow developers to take a more granular look at what is going on inside the application and help to identify the key causes.

Conclusion

By looking at the tips given above the developers can avoid the issues related to memory. Also the developers can make use of the available profiling tools which are helpful in identifying the memory leaks and improve the performance.


Sep 22, 2009

GWT Profiling and Debugging Techniques

Profiling

The JVM is designed with a means to get information on running processes (JVMPI, and the newer JVMTI). Using these mechanisms many Java tools can report on exactly what is going on when a Java application is executing. This information includes number of objects in use, memory, threads, garbage collection and so on. Profiling can be invaluable in tuning and troubleshooting an application. The end goal of profiling is to determine exactly what is happening with an application at runtime, in great detail, and identify performance metrics and bottlenecks.


The Limitations of Hosted Mode Profiling

Profiling GWT though, is once again a bit different from what you might expect. With GWT you have access to the standard Java profiling you are likely accustomed to, but only in hosted mode. Using a Java profiler, when working in hosted mode, as you normally would (from within an IDE, or separately), yields only an intermediate sort of reference point. What happens in Java, before the GWTCompiler optimizes things, is not representative of what will happen in JavaScript. You might catch any glaring problems with your code using this method, but you will not be able to tweak end result performance.

In web mode, a JavaScript profiler can be used. This type of profiling does operate against the end result code of your application, and can yield a great deal of performance, and troubleshooting information, but also has it's own GWT related differences.

Web Mode Profiling

For detailed information, and or troubleshooting purposes when working with GWT projects in web mode, you will want to use a JavaScript profiling tool. The Mozilla Venkman Project and Firebug are two examples of excellent JavaScript debugging and profiling tools.

Problem:

How do I profile a running GWT application in web mode?

Solution:

In order to profile GWT code in web mode you first need to make sure to use the -style command line parameter with the GWT compiler and set the format to PRETTY or DETAILED. PRETTY is the recommended setting for normal profiling. If you need extra troubleshooting help, or for any other reason want extra verbosity, you can use DETAILED. If you are using the “Compile/Browse” button from the GWTShell, you can also pass the -style parameter to the shell, which will in turn hand it off to the compiler. If you leave things in the default style setting of OBF (obfuscated), you do not stand much of a chance of following the output. Ultimately after you have profiled your code, before you deploy it to a production environment, you will want to switch back and compile with the OBF style.

For example purposes we will use the Firebug “web development” plug-in for Mozilla Firefox. Firebug includes CSS and DOM inspection tools, network traffic monitoring capabilities, HTML tools, and more, in addition to excellent JavaScript profiling capabilities. Firebug can be used on all platforms where Firefox is available.

Installation of Firebug is the same as that for any Firefox plug-in, select the .xpi file from the Firebug website (http://www.getfirebug.com/), and allow it to install. Once installed, the Firefox “Tools” element on the top menu will include a new Firebug sub-menu. To see Firebug in action, after it is installed, you simply invoke Tools->Firebug->Open Firebug. Figure 1 is a screen shot of the Firebug Console window open, on the lower half of a browser screen.

Figure 1 Firebug running in the lower half of the Firefox browser, Console section open

To use Firebug with a GWT application you simply direct your browser to the GWT application and open Firebug. The simplest way to do this, assuming Firefox is your default browser, is to invoke web mode from the GWTShell via the Compile/Browse button. Using a GWT app in the shell, and invoking web mode, will invoke the GWT compiler and open a browser window directed at the compiled code (and still run any service servlets in the hosted mode shell). Then you can start Firebug (recall, Tools->Firebug) and learn a great deal of useful information about your application.

Discussion:

Using the Firebug Console you can inspect many of the components of a running AJAX application. This includes XmlHttpRequest (XHR) calls, XML errors and JavaScript information. The XHR information, request and response, including the headers, is useful in understanding how the GWT moving parts are operating. This can be invaluable in terms of troubleshooting. For example, Figure 2 shows several XHR calls made while running GWTTestMe.

Figure 2 Firebug screen shot showing XHR POST operations, including full HTTP headers, in the Console

From the Firebug Console, as seen in Figure 2, we see several important GWT details. First, the “Headers” section shows the XHR response and request headers. These indicate that a POST response was returned from a local “Apache-Coyote” server, at the path http://localhost:8888/[MODULE_NAME]/[SERVICE_NAME]. This shows us exactly where our GWT RPC is ending up, if we were using -noserver we would expect to see our external server instance being invoked here. Also the POST request includes the “referer,” which denotes exactly which of the hash named “cache.html” files was used (which specific compiled version of the application). Finally, in the “Post” and “Response” sections we see the GWT IsSerializable/Serializable objects that are passed across the wire. These are not specifically profiling tasks, but are handy related features of Firebug that can be extremely useful when working on GWT applications.


Tip

Also note that when using Firebug you can use the Console XHR information to see if “content-encoding” gzip compression is in use. This compression can greatly reduce the size of textual content client user-agents have to download. Because HTML and JavaScript are text, compression should be used (it is the default on most HTTP 1.1 servers and clients, but you should check to make sure that it is working properly).

The Firebug Console can capture many of the details details you may ever want to know about a running GWT application. The HTML, CSS, and DOM sections of Firebug are also very useful, and somewhat self-explanatory. Additionally the Net section provides network traffic and asset size relation information about each part of a running application. And, the Script section provides not only insight into the JavaScript being used, but also a full fledged debugger, with breakpoints and variable contents. Though debugging in JavaScript can be helpful, it is usually more valuable for GWT developers to debug things as Java in hosted mode, something we will come to in the next section. To “profile” a JavaScript based application, you engage the Profiler by clicking on the “Profile” link in Firebug to start and stop the profiler's data collection process.

By clicking on Profile a first time, you tell the profiler to begin paying attention. At that point you can then click around your application and perform some tasks. Then when you click Profile again, you instruct the profiler to stop and display the collected data in the Console. It is this data that can help you understand how your GWT application is working. Figure 3 is a screen shot showing the results of the Firebug profiler, which includes such concepts such as the number of calls each function received, percentage, time, and what file each is in. (Note that “own time” means time inside the function specified without recursive calls to other functions, while “time” means total time including recursive calls.)

Figure 3 Firebug Profiler screen shot showing sortable profiling data collection results

The manual profiling method using Firebug is often helpful, but you may also want to use it in a more automated fashion. To do so, you can include JavaScript methods to start and stop the profiler using the Firebug Console API. In GWT terms, if you are concerned, or curious, about a particular section of code you can use JSNI with the Console API to automatically stop and start the profiler in exact areas you specify. This, in addition to being automatic, focuses the results to just the specific portions of code you are interested in.

Once you have collected profiling data with Firebug you can then inspect the results to understand exactly how your application is operating. You need to keep in mind though, that what you are seeing is your code as optimized by the GWT compiler (unless you are using JSNI). This is key because you have to remember that the GWT compiler is fairly smart. The “optimizations” it performs should mean that you will not ever have much to “fix” as a result of your profiling, if you are using standard GWT code and allowing the compiler to do its job.

Profiling a standard GWT application, as JavaScript in web mode, is more about understanding the network calls, optimizing the number of HTTP requests made, and gleaning information to troubleshoot problems, than it is about making changes and optimizing code. You should generally see many core GWT functions at the top of the stack in your profiler results. These things you are not going to improve upon unless you start hacking on the toolkit itself. Farther down the line you should see your controller methods as JavaScript functions (again, if you are using a client side controller in the canonical GWT manner), and your actual serializable objects. Also, you will see service proxy functions and all other details concerning everything GWT is doing to manipulate the DOM, invoke RPC, and so on.

Overall Firebug, and other such JavaScript profiling tools, are very important to the GWT developer. You can use these tools to see the whole picture when it comes to your GWT application, making sure your code does what you expect. Along with profiling, another arguably even more important development tactic is debugging.

Debugging

The hosted mode browser is a running Java process, as is the GWT shell. There is a harness between these components that propagates browser based events to GWT projects running in the shell. Using this approach, you can run your GWT project and use a standard Java debugger in a variety of ways. The most common means to debug a Java project are either to run the project in process inside of an IDE, or to connect an IDE to a remotely running Java process with the Java Platform Debugger Architecture (JPDA) interface enabled and listening for connections.

These same methods can be used with GWT, to connect to, and debug your programs, through the GWT shell.

Many modern IDEs have all sorts of support for running applications, even servers, in process with the IDE; and then debugging from there. It's good to also be aware, however, that you can debug external processes pretty easily as well. This is made possible by the Java Platform Debugger Architecture (JPDA - http://java.sun.com/j2se/1.5.0/docs/guide/jpda/architecture.html).

Basically, modern JVMs have a set of profiling interfaces (one for the front end, and one for the back end), and a protocol, that work together to enable external debugging. JVMs include a native interface implementation, based on JVMTI, on the back end, and a Java interface based on JDI is used for front end debugging. The protocol that enables communication between the two layers is JDWP. Using this setup debuggers can easily connect to remote Java processes, and perform their typical beloved duties.

Problem:

How do I configure the JVM to allow a remote process to be debugged.

Solution:

Use the JPDA support built into the JVM to pass the appropriate options to the Java process on the command line, and then connect to that process with a debugger.

Discussion:

To demonstrate the concepts, let's step through an example using GWT-Maven to launch a GWT project, and then debug that project from Eclipse. To begin, an external Java process needs to be running, and that process must have been configured to pass the -Xdebug and -Xrunjdwp options to the JVM at startup (optionally the newer -agentlib:jdwp option is preferable on Java 5.0 and above VMs).

The exact options used for this example, which are passed automatically via Maven and the GWT-Maven plugin using the gwt:debug goal, are as follows:


-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=3408,suspend=y

More detail about all of the options is available in the JPDA documentation ( http://java.sun.com/j2se/1.5.0/docs/guide/jpda/conninv.html#Invocation).

Basically, in this case, we are telling whatever Java process we run with these options to start and wait for a debugger to connect before continuing. Because we will be using GWT-Maven here the Java process we are controlling will ultimately be the GWTShell. On the command line this looks like what is shown in figure 4 (notice the process stopped, and is waiting for a connection on port 3408):

Figure 4 Shell session showing JVM waiting for debugger connection.

Once the process is waiting for a debugger to connect, the stage is set. The next thing to do is simply to connect with a debugger to the port shown - this is where Eclipse comes in. To connect with Eclipse you must use the "Run dialog," and select new "Remote Java Application." From there simply specify a name for the project, and the port as shown in figure 5.

Figure 5 Configuration dialog for Eclipse that demonstrates connecting to a remote process for debugging.

(Note* this screen shot shows port 1941 from a previous run, in this case it would need to be changed to 3408 to connect to the process started above.)

With that, all the pieces are in place, the JVM is running as the back end, and the IDE has connected as the front end. In this example the GWTShell continues along and launches the application, and from there you can click around to exercise the Java code. As with any typical debugging you can use breakpoints and step into and out of the code, and inspect the state as you go. Though the screen shot in figure 6 is small, you get the idea with the blue breakpoint dot and green highlighted code line:

Figure 6 Typical Eclipse debugger in use showing breakpoints.

In total the technique is very easy once you understand the roles of the components. Though this example used GWT, and GWT-Maven (something where external debugging comes in very handy), keep in mind that these concepts can be applied to any external Java process (a Tomcat server, a JBoss server, a Swing app, even an Applet - with a few caveats).

Other Debugging Tools


GWT Profiling and Debugging Techniques

Profiling

The JVM is designed with a means to get information on running processes (JVMPI, and the newer JVMTI). Using these mechanisms many Java tools can report on exactly what is going on when a Java application is executing. This information includes number of objects in use, memory, threads, garbage collection and so on. Profiling can be invaluable in tuning and troubleshooting an application. The end goal of profiling is to determine exactly what is happening with an application at runtime, in great detail, and identify performance metrics and bottlenecks.


The Limitations of Hosted Mode Profiling

Profiling GWT though, is once again a bit different from what you might expect. With GWT you have access to the standard Java profiling you are likely accustomed to, but only in hosted mode. Using a Java profiler, when working in hosted mode, as you normally would (from within an IDE, or separately), yields only an intermediate sort of reference point. What happens in Java, before the GWTCompiler optimizes things, is not representative of what will happen in JavaScript. You might catch any glaring problems with your code using this method, but you will not be able to tweak end result performance.

In web mode, a JavaScript profiler can be used. This type of profiling does operate against the end result code of your application, and can yield a great deal of performance, and troubleshooting information, but also has it's own GWT related differences.

Web Mode Profiling

For detailed information, and or troubleshooting purposes when working with GWT projects in web mode, you will want to use a JavaScript profiling tool. The Mozilla Venkman Project and Firebug are two examples of excellent JavaScript debugging and profiling tools.

Problem:

How do I profile a running GWT application in web mode?

Solution:

In order to profile GWT code in web mode you first need to make sure to use the -style command line parameter with the GWT compiler and set the format to PRETTY or DETAILED. PRETTY is the recommended setting for normal profiling. If you need extra troubleshooting help, or for any other reason want extra verbosity, you can use DETAILED. If you are using the “Compile/Browse” button from the GWTShell, you can also pass the -style parameter to the shell, which will in turn hand it off to the compiler. If you leave things in the default style setting of OBF (obfuscated), you do not stand much of a chance of following the output. Ultimately after you have profiled your code, before you deploy it to a production environment, you will want to switch back and compile with the OBF style.

For example purposes we will use the Firebug “web development” plug-in for Mozilla Firefox. Firebug includes CSS and DOM inspection tools, network traffic monitoring capabilities, HTML tools, and more, in addition to excellent JavaScript profiling capabilities. Firebug can be used on all platforms where Firefox is available.

Installation of Firebug is the same as that for any Firefox plug-in, select the .xpi file from the Firebug website (http://www.getfirebug.com/), and allow it to install. Once installed, the Firefox “Tools” element on the top menu will include a new Firebug sub-menu. To see Firebug in action, after it is installed, you simply invoke Tools->Firebug->Open Firebug. Figure 1 is a screen shot of the Firebug Console window open, on the lower half of a browser screen.

Figure 1 Firebug running in the lower half of the Firefox browser, Console section open

To use Firebug with a GWT application you simply direct your browser to the GWT application and open Firebug. The simplest way to do this, assuming Firefox is your default browser, is to invoke web mode from the GWTShell via the Compile/Browse button. Using a GWT app in the shell, and invoking web mode, will invoke the GWT compiler and open a browser window directed at the compiled code (and still run any service servlets in the hosted mode shell). Then you can start Firebug (recall, Tools->Firebug) and learn a great deal of useful information about your application.

Discussion:

Using the Firebug Console you can inspect many of the components of a running AJAX application. This includes XmlHttpRequest (XHR) calls, XML errors and JavaScript information. The XHR information, request and response, including the headers, is useful in understanding how the GWT moving parts are operating. This can be invaluable in terms of troubleshooting. For example, Figure 2 shows several XHR calls made while running GWTTestMe.

Figure 2 Firebug screen shot showing XHR POST operations, including full HTTP headers, in the Console

From the Firebug Console, as seen in Figure 2, we see several important GWT details. First, the “Headers” section shows the XHR response and request headers. These indicate that a POST response was returned from a local “Apache-Coyote” server, at the path http://localhost:8888/[MODULE_NAME]/[SERVICE_NAME]. This shows us exactly where our GWT RPC is ending up, if we were using -noserver we would expect to see our external server instance being invoked here. Also the POST request includes the “referer,” which denotes exactly which of the hash named “cache.html” files was used (which specific compiled version of the application). Finally, in the “Post” and “Response” sections we see the GWT IsSerializable/Serializable objects that are passed across the wire. These are not specifically profiling tasks, but are handy related features of Firebug that can be extremely useful when working on GWT applications.


Tip

Also note that when using Firebug you can use the Console XHR information to see if “content-encoding” gzip compression is in use. This compression can greatly reduce the size of textual content client user-agents have to download. Because HTML and JavaScript are text, compression should be used (it is the default on most HTTP 1.1 servers and clients, but you should check to make sure that it is working properly).

The Firebug Console can capture many of the details details you may ever want to know about a running GWT application. The HTML, CSS, and DOM sections of Firebug are also very useful, and somewhat self-explanatory. Additionally the Net section provides network traffic and asset size relation information about each part of a running application. And, the Script section provides not only insight into the JavaScript being used, but also a full fledged debugger, with breakpoints and variable contents. Though debugging in JavaScript can be helpful, it is usually more valuable for GWT developers to debug things as Java in hosted mode, something we will come to in the next section. To “profile” a JavaScript based application, you engage the Profiler by clicking on the “Profile” link in Firebug to start and stop the profiler's data collection process.

By clicking on Profile a first time, you tell the profiler to begin paying attention. At that point you can then click around your application and perform some tasks. Then when you click Profile again, you instruct the profiler to stop and display the collected data in the Console. It is this data that can help you understand how your GWT application is working. Figure 3 is a screen shot showing the results of the Firebug profiler, which includes such concepts such as the number of calls each function received, percentage, time, and what file each is in. (Note that “own time” means time inside the function specified without recursive calls to other functions, while “time” means total time including recursive calls.)

Figure 3 Firebug Profiler screen shot showing sortable profiling data collection results

The manual profiling method using Firebug is often helpful, but you may also want to use it in a more automated fashion. To do so, you can include JavaScript methods to start and stop the profiler using the Firebug Console API. In GWT terms, if you are concerned, or curious, about a particular section of code you can use JSNI with the Console API to automatically stop and start the profiler in exact areas you specify. This, in addition to being automatic, focuses the results to just the specific portions of code you are interested in.

Once you have collected profiling data with Firebug you can then inspect the results to understand exactly how your application is operating. You need to keep in mind though, that what you are seeing is your code as optimized by the GWT compiler (unless you are using JSNI). This is key because you have to remember that the GWT compiler is fairly smart. The “optimizations” it performs should mean that you will not ever have much to “fix” as a result of your profiling, if you are using standard GWT code and allowing the compiler to do its job.

Profiling a standard GWT application, as JavaScript in web mode, is more about understanding the network calls, optimizing the number of HTTP requests made, and gleaning information to troubleshoot problems, than it is about making changes and optimizing code. You should generally see many core GWT functions at the top of the stack in your profiler results. These things you are not going to improve upon unless you start hacking on the toolkit itself. Farther down the line you should see your controller methods as JavaScript functions (again, if you are using a client side controller in the canonical GWT manner), and your actual serializable objects. Also, you will see service proxy functions and all other details concerning everything GWT is doing to manipulate the DOM, invoke RPC, and so on.

Overall Firebug, and other such JavaScript profiling tools, are very important to the GWT developer. You can use these tools to see the whole picture when it comes to your GWT application, making sure your code does what you expect. Along with profiling, another arguably even more important development tactic is debugging.

Debugging

The hosted mode browser is a running Java process, as is the GWT shell. There is a harness between these components that propagates browser based events to GWT projects running in the shell. Using this approach, you can run your GWT project and use a standard Java debugger in a variety of ways. The most common means to debug a Java project are either to run the project in process inside of an IDE, or to connect an IDE to a remotely running Java process with the Java Platform Debugger Architecture (JPDA) interface enabled and listening for connections.

These same methods can be used with GWT, to connect to, and debug your programs, through the GWT shell.

Many modern IDEs have all sorts of support for running applications, even servers, in process with the IDE; and then debugging from there. It's good to also be aware, however, that you can debug external processes pretty easily as well. This is made possible by the Java Platform Debugger Architecture (JPDA - http://java.sun.com/j2se/1.5.0/docs/guide/jpda/architecture.html).

Basically, modern JVMs have a set of profiling interfaces (one for the front end, and one for the back end), and a protocol, that work together to enable external debugging. JVMs include a native interface implementation, based on JVMTI, on the back end, and a Java interface based on JDI is used for front end debugging. The protocol that enables communication between the two layers is JDWP. Using this setup debuggers can easily connect to remote Java processes, and perform their typical beloved duties.

Problem:

How do I configure the JVM to allow a remote process to be debugged.

Solution:

Use the JPDA support built into the JVM to pass the appropriate options to the Java process on the command line, and then connect to that process with a debugger.

Discussion:

To demonstrate the concepts, let's step through an example using GWT-Maven to launch a GWT project, and then debug that project from Eclipse. To begin, an external Java process needs to be running, and that process must have been configured to pass the -Xdebug and -Xrunjdwp options to the JVM at startup (optionally the newer -agentlib:jdwp option is preferable on Java 5.0 and above VMs).

The exact options used for this example, which are passed automatically via Maven and the GWT-Maven plugin using the gwt:debug goal, are as follows:


-Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,server=y,address=3408,suspend=y

More detail about all of the options is available in the JPDA documentation ( http://java.sun.com/j2se/1.5.0/docs/guide/jpda/conninv.html#Invocation).

Basically, in this case, we are telling whatever Java process we run with these options to start and wait for a debugger to connect before continuing. Because we will be using GWT-Maven here the Java process we are controlling will ultimately be the GWTShell. On the command line this looks like what is shown in figure 4 (notice the process stopped, and is waiting for a connection on port 3408):

Figure 4 Shell session showing JVM waiting for debugger connection.

Once the process is waiting for a debugger to connect, the stage is set. The next thing to do is simply to connect with a debugger to the port shown - this is where Eclipse comes in. To connect with Eclipse you must use the "Run dialog," and select new "Remote Java Application." From there simply specify a name for the project, and the port as shown in figure 5.

Figure 5 Configuration dialog for Eclipse that demonstrates connecting to a remote process for debugging.

(Note* this screen shot shows port 1941 from a previous run, in this case it would need to be changed to 3408 to connect to the process started above.)

With that, all the pieces are in place, the JVM is running as the back end, and the IDE has connected as the front end. In this example the GWTShell continues along and launches the application, and from there you can click around to exercise the Java code. As with any typical debugging you can use breakpoints and step into and out of the code, and inspect the state as you go. Though the screen shot in figure 6 is small, you get the idea with the blue breakpoint dot and green highlighted code line:

Figure 6 Typical Eclipse debugger in use showing breakpoints.

In total the technique is very easy once you understand the roles of the components. Though this example used GWT, and GWT-Maven (something where external debugging comes in very handy), keep in mind that these concepts can be applied to any external Java process (a Tomcat server, a JBoss server, a Swing app, even an Applet - with a few caveats).

Other Debugging Tools


Text Widget

Copyright © Vinay's Blog | Powered by Blogger

Design by | Blogger Theme by