Вы находитесь на странице: 1из 12

Memory Analysis Best Practices

Within Eclipse

Written by
Steven Haines

White Paper
© Copyright Quest® Software, Inc. 2008. All rights reserved.
This guide contains proprietary information, which is protected by copyright. The
software described in this guide is furnished under a software license or
nondisclosure agreement. This software may be used or copied only in accordance
with the terms of the applicable agreement. No part of this guide may be reproduced
or transmitted in any form or by any means, electronic or mechanical, including
photocopying and recording for any purpose other than the purchaser's personal use
without the written permission of Quest Software, Inc.

WARRANTY

The information contained in this document is subject to change without notice.


Quest Software makes no warranty of any kind with respect to this information.
QUEST SOFTWARE SPECIFICALLY DISCLAIMS THE IMPLIED WARRANTY OF THE
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. Quest Software
shall not be liable for any direct, indirect, incidental, consequential, or other damage
alleged in connection with the furnishing or use of this information.

TRADEMARKS

All trademarks and registered trademarks used in this guide are property of their
respective owners.

World Headquarters
5 Polaris Way
Aliso Viejo, CA 92656
www.quest.com
e-mail: info@quest.com
U.S. and Canada: 949.754.8000

Please refer to our Web site for regional and international office information.

Updated—June 2008
CONTENTS
CONTENTS ......................................................................................... 1
ABSTRACT ......................................................................................... 2
INTRODUCTION ................................................................................. 3
STATE OF THE MARKET ........................................................................... 4
MEMORY ANALYSIS WITH ECLIPSE ................................................... 5
NATURE OF JAVA MEMORY ISSUES .............................................................. 5
MEMORY ANALYSIS REQUIREMENTS ............................................................ 6
SUMMARY .......................................................................................... 8
ABOUT THE AUTHOR .......................................................................... 9
REFERENCES ...................................................................................... 9
ABOUT QUEST SOFTWARE, INC. ...................................................... 10
CONTACTING QUEST SOFTWARE ............................................................... 10
CONTACTING QUEST SUPPORT ................................................................. 10
ABSTRACT
The performance of many enterprise Java applications can typically be poor,
forcing affected companies to pay the high price of lost sales and tarnished
reputations. Fortunately, proactive attention to the performance of an
application while it is being developed can eliminate most performance issues
before your customers ever see them. This paper presents a strategy for
identifying memory leaks in Java applications from the comfort of the Eclipse
Java Integrated Development Environment (IDE). You will learn how the Java
garbage collector works, the nature of memory leaks, and how to avoid
them. You will also learn how to configure the automated analysis of unit test
case memory usage inside Eclipse, while learning strategies for isolating and
resolving memory leaks. Lastly, I will explain how to regularly generate
memory profiles in a repeatable fashion. Because everything runs from inside
Eclipse, you can generate memory profiles and summary reports with the
click of a mouse once Eclipse is configured.

2
INTRODUCTION
Performance for many enterprise Java applications today is astonishingly
poor. There are many things that we can do to address this problem, both
proactively as well as reactively. Traditionally, organizations have ignored
performance concerns when developing their Java applications, and instead
they spend dollars in a reactive manner—troubleshooting performance issues
as they arise. Unfortunately, correcting a problem once an application has
been deployed to a production environment is expensive and time-
consuming, as illustrated in Figure 1.

Figure 1. Cost to resolve Java application performance issues.


A better approach is to test the performance of your application as you are
developing it. There are several different code and memory profiling tools on
the market that can help identify performance issues, but most require that
you leave your Integrated Development Environment (IDE) and launch a
separate tool for testing performance. This process has worked well over the
years, but switching between tools and managing two sets of application
configurations (one for your IDE and one for your profiling tool) can be
cumbersome. In some cases, it might dissuade you from testing the
performance of your code as frequently as you should.
This white paper presents a strategy that you can employ to identify the
most common performance problems—memory leaks and poor memory
management—from the comfort of the most popular Java development IDE,
the Eclipse Java IDE.

3
State of the Market
The quality and performance of enterprise applications in our industry are
astonishingly poor, as illustrated by the following research analyst findings:
According to Forrester Research, nearly 85 percent of companies with
revenue of more than $1 billion reported incidents of significant
application performance problems.1 Survey respondents identified the
architecture and deployment as the primary causes of these
problems.2 Based on this survey, it seems that no matter how much
you tune your hardware and environment, application problems will
persist.
Infonetics Research found that medium-sized businesses (101 to 1,000
employees) are losing an average of one percent of their annual
revenues, or $867,000, to downtime. Application outages and
degradations are the biggest sources of downtime, costing these
companies $213,000 annually.3
The cost of outages and performance degradation can be calculated in
several ways, based on the type of application:
Business-to-consumer: a direct loss of sales revenue because of web
site abandonment and lack of consumer confidence
Business-to-business: a loss of credibility, which can eventually lead to
lost business partnerships
Internal applications: a loss of employee productivity
With respect to business-to-consumer applications, consider the typical
shopping pattern of modern-day consumers. They usually find an item at one
of the major retailers and then search for the best price online. In the end,
the prices do not usually vary more than five percent, so they choose a
vendor they trust within that range. However, if the vendor’s site is running
slow or makes finalizing the purchase too difficult, they simply move down
the list to the next preferred vendor. By and large, retailer loyalty has been
replaced by price competition and convenience. So even a minor site outage
could mean lost business.
In a business-to-business relationship, the stakes are much higher. Let’s say
you are one of several companies that sell widgets. If you have established a
relationship with a major retailer, the reliability and performance of your B2B
application is your livelihood. If the major retailer submits an order for
additional widgets and your application is unavailable or the order is lost, you
run the risk of losing the partnership—and the revenue. Continual application
problems mean lost accounts.
Slow or poorly performing internal applications can also impact the bottom
line. Employee productivity suffers when an application goes down or
responds slowly. More significantly, lost time can delay product delivery.
When that happens, your company can either delay the product release or
reduce the scope of the release to meet deadlines. Either option can lead to a
disaster.
4
MEMORY ANALYSIS WITH ECLIPSE

Nature of Java Memory Issues


A common problem that has plagued Java developers since the advent of the
Java Virtual Machine (JVM) is the occurrence of memory leaks. We all
thought that memory leaks would disappear in Java because of its automatic
garbage collection. Many of our memory leaks actually did go away, but
because of the very nature of garbage collection, entirely new types of
memory leaks emerged. The garbage collector functions by performing a
process called the reachability test, as shown in Figure 2.

Figure 2. Reachability Test performed by the Java garbage collector.


The reachability test traverses over all objects currently alive in the heap. It
first examines objects directly visible by all active threads in the JVM, which
is referred to as the root set. It then follows all object references from
objects in the root set to other objects in the heap, repeating the process
until it has successfully identified all reachable objects. Objects that are
unreachable are freed and their memory is reclaimed by the JVM. The
process resolves C++ style memory leaks in which an object is created and
its reference is destroyed before its underlying memory is freed.
Java references all objects—saving primitive types, their wrappers and
strings by reference— by reference, which means that as long as there is a
reference to an object in the heap, the garbage collector will be unable to
reclaim its memory. This forces us to define a new object state: live. A live
object is an object to which you are knowingly maintaining a reference. In
other words, it is an object that you expect to use in your application. If you
inadvertently maintain a reference to an object that you do not expect to use
in your application, then you have introduced a Java memory leak. Initially,
this might not seem that problematic because, at its core it is simply an
object management issue. However, because Java references all objects by
reference, object reference mismanagement can happen quite easily. For

5
example, if you add an object to a collections class (an object container
found in the java.util package, such as ArrayList or HashMap) then the
collections class will maintain a reference to that object until you explicitly
tell the collections class to remove that reference. Consider the following
code:
public class MyClass {

private ArrayList list = new ArrayList();

public void addFoo( Object foo ) {


list.add( foo );
}

public void processFoo( Object foo ) {


// Get foo out of the list
Object fooRef = list.get( foo );

// Do something with fooRef


...

// Done with fooRef, destroy it


fooRef = null;
}
}
In this example, the addFoo() method adds an object named foo to the
internal ArrayList. The processFoo() method loads foo out of the ArrayList,
does something with it, and then destroys it. The problem is that while you
may expect foo to be removed from the heap (or at least eligible for garbage
collection), foo will, in actuality, remain in the heap, and its memory will
never have a chance to be reclaimed. This is because the ArrayList is still
maintaining its own reference to foo. When the processFoo() method calls
the ArrayList’s get() method and assigns the object to fooRef, this simply
introduces a new reference to the foo object. Now one reference is held by
the ArrayList, and one reference is held by the fooRef. So when fooRef is set
to null to destroy the reference, this only destroys the fooRef reference, not
the ArrayList’s reference. The proper solution is to explicitly call the
ArrayList’s remove() method to tell the ArrayList to destroy its internal
reference to foo. Because of the nature of Java’s object management and
how easy it is to inadvertently maintain lingering object references, memory
leaks abound in Java applications.

Memory Analysis Requirements


Reviewing problems that can emerge as a result of improper object reference
management raises this question: How do you properly manage your object
references? The answer is to comprehensively analyze the way your
applications use memory. The best strategy for achieving this is to design
test cases that exercise your application’s functionality, just as you should
normally be doing. But, after your test cases prove that your code is
functionally correct, you need to profile those test cases to see whether you
6
are inadvertently leaving objects on the heap. Your profiling tool should be
able to:
Take a snapshot of the heap before your code runs
Take a snapshot of the heap after your code runs
Show you the differences between the two snapshots
Do all of this through an automated process
Even though you might need to investigate the contents of a heap in isolation
-- when exploring a production issue from a heap dump, for example -- it is
much easier to identify problems if you are able to see the differences
between two heaps. Furthermore, when you are examining the objects in a
heap in a development environment, it’s inefficient to regularly sift through
an entire heap. The best strategy is to compute the difference between the
“before” heap and the “after” heap, and then verify that new objects are
expected to be in the heap. If they’re not, then you have identified a memory
leak and can resolve it!
It is essential, however, to perform these memory analyses through an
automated process. I love performance testing, but I know that I am not
regularly going to profile each unit test manually. So I need a process that
will generate these profiles for me on a regular basis. This may sound like a
moot point, but as soon as you have 100 or more unit tests, are you really
going to have the time to check them once a week, let alone each time they
are executed?
In addition to automated memory analysis, your memory analysis tool should
provide you with a rich user interface for investigating the results of the
analysis reports interactively. Automated reports provide starting points for
your investigation by identifying objects left in the heap as a result of your
test case. However, keep in mind that only you, as the developer of the
code, can properly understand these “lingering objects” in the context of
your application and determine whether there is truly a memory leak.
The interface for the memory analysis tool should also be intuitive so you can
quickly find specific objects in the heap, and view the source code that
allocated those objects. In addition, it should show you what objects are
holding these references and what will happen if you remove this reference.
For example, will the memory leak, in fact, be resolved?
Finally, although switching between your Eclipse Java IDE and your profiling
tool is a reasonable option to profile your code, you will be more likely to
follow the best practice of profiling your code if you can do so from within
your IDE. After all, if you have to launch another tool, add new test cases to
your test harness, and perform the analysis, you are much less likely to do it
regularly than if you can simply press a button from within your IDE.

7
SUMMARY
The performance of many enterprise Java applications is typically poor, but
through proactive means we can find performance problems as we build our
applications—when they are easy and inexpensive to fix. This paper
presented a strategy for identifying and resolving memory leaks in your
applications. With the help of a profiling tool that offers a certain level of
automation, you can be sure that performance tests are executed
consistently and in a reproducible fashion. Also, if you choose to adopt the
practice of using a profiler that can seamlessly integrate with your Eclipse
Java IDE, profiling your application code can be convenient enough for you to
execute on a regular basis. By adopting this strategy, you will be able to
write more efficient code and help the entire Java community reduce the
currently abysmal performance statistics.

8
ABOUT THE AUTHOR
Steven Haines is the founder and CEO of GeekCap, Inc., which provides
professional services, software solutions development, certification programs
and e-learning through formal online courses. Subjects such as Spring,
Hibernate, Google and Web Toolkit. Previously, Haines was the Java EE
Domain Expert at Quest Software, where he defined the expert rules and
views used to monitor the performance of enterprise Java applications and
application servers. During his tenure at Quest, Haines created a Java EE
performance-tuning professional services organization, which improved the
performance of and resolved critical production issues for many Fortune 500
companies. He is the author of Pro Java EE 5 Performance Management and
Optimization (Apress), Java 2 Primer Plus (Sams), and Java 2 From Scratch
(Que), and shares author credits on Java Web Services Unleashed. Haines is
the Java host on Pearson Education’s online IT resource, Informit.com, where
he posts weekly articles and blogs. He is a Java community editor on
InfoQ.com, where he posts weekly articles covering breaking news. Haines
has taught all facets of Java programming at the University of California,
Irvine, and at Learning Tree University. Look for his latest digital shortcut
book, Agile Java Development with Test-Driven Development and Continuous
Integration, this winter on Informit.com. Haines can be reached at
steve@javasrc.com.

REFERENCES
1. Forrester, "Best Practices In Problem Management", June 23, 2004,
Jean-Pierre Garbani.

2. Network World, "New apps can be a real pain in the net", July 21,
2003, Denise Dubie.

3. Infonetics, “The Costs of Downtime: North American Medium


Businesses,” March 9, 2006.

9
ABOUT QUEST SOFTWARE, INC.
Quest Software, Inc., a leading enterprise systems management vendor,
delivers innovative products that help organizations get more performance
and productivity from their applications, databases, Windows infrastructure
and virtual environments. Through a deep expertise in IT operations and a
continued focus on what works best, Quest helps more than 90,000
customers worldwide meet higher expectations for enterprise IT. Quest’s
Foglight® application management solution unifies IT services with end users
and the business, resolves problems faster to reduce downtime, and lowers
the operating cost of managing applications. Quest Software can be found in
offices around the globe and at www.quest.com.

Contacting Quest Software


Phone: 949.754.8000 (United States and Canada)
Email: info@quest.com
Mail: Quest Software, Inc.
World Headquarters
5 Polaris Way
Aliso Viejo, CA 92656
USA
Web site: www.quest.com
Please refer to our Web site for regional and international office information.

Contacting Quest Support


Quest Support is available to customers who have a trial version of a Quest
product or who have purchased a commercial version and have a valid
maintenance contract. Quest Support provides around the clock coverage
with SupportLink, our web self-service. Visit SupportLink at
http://support.quest.com

From SupportLink, you can do the following:

Quickly find thousands of solutions (Knowledgebase articles/documents).


Download patches and upgrades.
Seek help from a Support engineer.
Log and update your case, and check its status.

View the Global Support Guide for a detailed explanation of support


programs, online services, contact information, and policy and procedures.
The guide is available at: http://support.quest.com/pdfs/Global Support
Guide.pdf

10

Вам также может понравиться