📄 perf3.html
字号:
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
The profile option literally logs every object created on the heap, so
even just starting and stopping the small <CODE>TableExample3</CODE>
program results in a four megabyte report file. Although the heap analysis
tool uses a binary version of this file and provides a summary, there are
some quick and easy things you can learn from the text file without using
the heap analysis tool.
<BLOCKQUOTE>
<HR>
<STRONG>Note:</STRONG> To list all available options, use<BR>
<CODE>java -Xrunhprof:help</CODE>
<HR>
</BLOCKQUOTE>
<H4>View the Text File</H4>
Choose an editor that can handle large files and go to the end of this
file. There could be hundreds of thousands of lines, so use a shortcut
instead of scrolling, or search for the words <CODE>SITES BEGIN</CODE>.
You should see a list of lines that start with an increasing rank number
followed by two percentage numbers. The first entry in this list, should
look similar to the example below:
</FONT>
<PRE>
SITES BEGIN (ordered by live bytes)
Sun Dec 20 16:33:28 1998</PRE>
<TABLE BORDER=0 CELLSPACING=2 CELLPADDING=0>
<TR>
<TD><CODE></CODE></TD>
<TD COLSPAN=2 ALIGN=CENTER><CODE>percent</CODE></TD>
<TD COLSPAN=2 ALIGN=CENTER><CODE>live</CODE></TD>
<TD COLSPAN=2 ALIGN=CENTER><CODE>alloc'ed</CODE></TD>
<TD><CODE> stack </CODE></TD>
<TD><CODE> class </CODE></TD>
</TR>
<TR>
<TD><CODE>rank </CODE></TD>
<TD><CODE> self </CODE></TD>
<TD><CODE> accum </CODE></TD>
<TD><CODE> bytes </CODE></TD>
<TD><CODE> objs </CODE></TD>
<TD><CODE> bytes </CODE></TD>
<TD><CODE> objs </CODE></TD>
<TD><CODE> trace </CODE></TD>
<TD><CODE> name</CODE></TD>
</TR>
<TR>
<TD><CODE> 1 </CODE></TD>
<TD><CODE> 55.86% </CODE></TD>
<TD><CODE> 55.86% </CODE></TD>
<TD><CODE> 826516 </CODE></TD>
<TD><CODE> 5 </CODE></TD>
<TD><CODE> 826516 </CODE></TD>
<TD><CODE> 5 </CODE></TD>
<TD><CODE> 3981 </CODE></TD>
<TD><CODE> [S</CODE></TD>
</TR>
</TABLE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<P>
The <CODE>[S</CODE> notation at the end of the last line above indicates the
first entry is an array of the <CODE>short</CODE>, a primitive type. This is expected
with Swing or Abstract Window Toolkit (AWT) applications. The five count under
the <CODE>objs</CODE> header mean there are currently five of these arrays,
there have only been five in the lifetime of this application, and they take
up 826516 bytes. The reference key to this object is the value listed under
<CODE>stack trace</CODE>. To find where this object was created in this
example, search for <CODE>TRACE 3981</CODE>. You will see the following:
</FONT>
<PRE>
TRACE 3981:
java/awt/image/DataBufferUShort.<init>(
DataBufferUShort.java:50)
java/awt/image/Raster.createPackedRaster(
Raster.java:400)
java/awt/image/DirectColorModel.
createCompatibleWritableRaster(
DirectColorModel.java:641)
sun/awt/windows/WComponentPeer.createImage(
WComponentPeer.java:186)
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<P>
The <CODE>TableExample3</CODE> code sets a <CODE>scrollpane</CODE> that is
700 by 300. When you look at the source of <CODE>Raster.java</CODE>, which
is in the <CODE>src.jar</CODE> file, you find these statements at line 400:
</FONT>
<PRE>
case DataBuffer.TYPE_USHORT:
d = new DataBufferUShort(w*h);
break;
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<P>
The values <CODE>w</CODE> and <CODE>h</CODE> are the width and height from
the <CODE>createImage</CODE> call at the start of <CODE>TRACE 3981</CODE>.
The <CODE>DataBufferUShort</CODE> constructor creates and array of
<CODE>shorts</CODE> as follows:
</FONT>
<PRE>
data = new short[size];
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
where <CODE>size</CODE> is <CODE>w*h</CODE>. So, in theory there should be an
entry for an array of 210000 elements. You look for each instantiation of this
class by searching for <CODE>trace=3981</CODE>. One of the five entries will
look like this:
</FONT>
<PRE>
OBJ 5ca1fc0 (sz=28, trace=3979,
class=java/awt/image/DataBufferUShort@9a2570)
data 5ca1670
bankdata 5ca1f90
offsets 5ca1340
ARR 5ca1340 (sz=4, trace=3980, nelems=1,
elem type=int)
ARR 5ca1670 (sz=420004, trace=3981, nelems=210000,
elem type=short)
ARR 5ca1f90 (sz=12, trace=3982, nelems=1,
elem type=[S@9a2d90)
[0] 5ca1670
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<P>
You can see that the data value of this raster image references an array
<CODE>5ca1670</CODE> which in turns lists 210000 elements of a
<CODE>short</CODE> of size 2. This means 420004 bytes of memory are used
in this array.
<P>
From this data you can conclude that the <CODE>TableExample3</CODE> program
uses nearly 0.5Mb to map each table. If the example application is running
on a small memory machine, you should make sure you do not keep unnecessary
references to large tables or images that are built by the
<CODE>createImage</CODE> method.
<H4>The Heap Analysis Tool</H4>
The Heap Analysis tool can analyze the same data for you, but requires a
binary report file as input. You can generate a binary report file as
follows:
</FONT>
<PRE>
java -Xrunhprof:file=TableExample3.hprof,format=b
TableExample3
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<P>
To generate the binary report, close the <CODE>TableExample3</CODE> window.
The binary report file <CODE>TableExample3.hprof</CODE> is created when the
program exits. The Heap Analysis tool starts an HTTP Server that analyzes
the binary profile file and displays the results in HTML that you can view
with a browser.
<P>
You can get a copy of the Heap Analysis Tool from the
<A HREF="http://java.sun.com">java.sun.com</A> site.
Once you install it, you run shell and batch scripts in the installed
<CODE>bin</CODE> directory so you can start the Heap Analysis Tool
server as follows:
</FONT>
<PRE>
>hat TableExample3.hprof
Started HCODEP server on port 7000
Reading from /tmp/TableExample3.hprof...
Dump file created Tue Jan 05 13:28:59 PST 1999
Snapshot read, resolving...
Resolving 17854 objects...
Chasing references,
expect 35 dots.......................
Eliminating duplicate
references.........................
Snapshot resolved.
Server is ready.
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<P>
The above output tells you an HTTP server is started on port 7000
by default. To view this report enter the url
http://localhost:7000 or http://your_machine_name:7000 in your web
browser. If you have problems starting the server using the scripts, you
can alternatively run the application by including the <CODE>hat.zip</CODE>
classes file on your <CODE>CLASSPATH</CODE> and use the following command:
</FONT>
<PRE>
java hat.Main TableExample3.hprof
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<P>
The default report view contains a list of all the classes. At the bottom
of this initial page are the following two key report options:
</FONT>
<PRE>
Show all members of the rootset
Show instance counts for all classes
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<P>
If you select the <CODE>Show all members of the rootset</CODE> link, you see
a list of the following references because these reference are likely targets
for potential memory leaks.
</FONT>
<PRE>
Java Static References
Busy Monitor References
JNI Global References
JNI Local References
System Class References
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<P>
What youn look for here are instances in the application that have references
to objects that have a risk of not being garbage collected. This can sometimes
occur in the case of JNI if memory is allocated for an object, the memory is
left to the garbage collector to free up, and the garbage collector does not
have the information it needs to do it. In this list of references, you are
mainly interested in a large number of references to objects or objects of a
large size.
<P>
The other key report is the <CODE>Show instance counts for all classes</CODE>.
This lists the number of calls to a particular method. The <CODE>String</CODE>
and <CODE>Character</CODE> array objects, <CODE>[S</CODE> and <CODE>[C</CODE>,
are always going to be high on this list, but some objects are a bit more
intriguing. Why are there 323 instances of
<CODE>java.util.SimpleTimeZone</CODE> for example?
</FONT>
<PRE>
5109 instances of class java.lang.String
5095 instances of class [C
2210 instances of class java.util.Hashtable$Entry
968 instances of class java.lang.Class
407 instances of class [Ljava.lang.String;
323 instances of class java.util.SimpleTimeZone
305 instances of class
sun.java2d.loops.GraphicsPrimitiveProxy
304 instances of class java.util.HashMap$Entry
269 instances of class [I
182 instances of class [Ljava.util.Hashtable$Entry;
170 instances of class java.util.Hashtable
138 instances of class java.util.jar.Attributes$Name
131 instances of class java.util.HashMap
131 instances of class [Ljava.util.HashMap$Entry;
130 instances of class [Ljava.lang.Object;
105 instances of class java.util.jar.Attributes
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
To get more information on the <CODE>SimpleTimeZone</CODE> instances, click on
the link (the line beginning with 323). This will list all 323 references and
calculate how much memory has been used. In this example, 21964 bytes have
been used.
</FONT>
<PRE>
Instances of java.util.SimpleTimeZone
class java.util.SimpleTimeZone
java.util.SimpleTimeZone@0x004f48c0 (68 bytes)
java.util.SimpleTimeZone@0x003d5ad8 (68 bytes)
java.util.SimpleTimeZone@0x004fae88 (68 bytes)
.....
Total of 323 instances occupying 21964 bytes.
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
If you click on one of these <CODE>SimpleTimeZone</CODE> instances, you see
where this object was allocated.
</FONT>
<PRE>
Object allocated from:
java.util.TimeZoneData.<clinit>(()V) :
TimeZone.java line 1222
java.util.TimeZone.getTimeZone((Ljava/lang/String;)
Ljava/util/TimeZone;) :
TimeZone.java line (compiled method)
java.util.TimeZone.getDefault(
()Ljava/util/TimeZone;) :
TimeZone.java line (compiled method)
java.text.SimpleDateFormat.initialize(
(Ljava/util/Locale;)V) :
SimpleDateFormat.java line (compiled method)
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
In this example the object was allocated from <CODE>TimeZone.java</CODE>.
The source to this file is in the standard <CODE>src.jar</CODE> file, and
on examining this file, you can see that indeed there are nearly 300 of
these objects in memory.
</FONT>
<PRE>
static SimpleTimeZone zones[] = {
// The following data is current as of 1998.
// Total Unix zones: 343
// Total Java zones: 289
// Not all Unix zones become Java zones due to
// duplication and overlap.
//-------------------------------------------
new SimpleTimeZone(-11*ONE_HOUR,
"Pacific/Niue" /*NUT*/),
</PRE>
<FONT FACE="Verdana, Arial, Helvetica, sans-serif">
<P>
Unfortunately, you have no control over the memory used in this example
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -