[jboss-cvs] jboss-profiler/docbook/en/modules ...
Clebert Suconic
csuconic at jboss.com
Fri Nov 10 12:40:20 EST 2006
User: csuconic
Date: 06/11/10 12:40:20
Added: docbook/en/modules runtime.xml webinterface.xml
concept.xml memory.xml jvmti.xml compiling.xml
Log:
Adding docbook under jboss-profiler tree
Revision Changes Path
1.1 date: 2006/11/10 17:40:20; author: csuconic; state: Exp;jboss-profiler/docbook/en/modules/runtime.xml
Index: runtime.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="runtime">
<title>Runtime Profiler</title>
<sect1 id="conceptrun">
<title>Events covered during runtime analysis</title>
<para>When using the Runtime Profiler, you are interested in the behavior
of your methods during execution.</para>
<para>We extract information about method calls showing % information
relative to CPU and elapsed time. We also show information about memory
consumption from these methods.</para>
<para>Say, if a method allocates an object, you will have an enter-method
event, and a objectalloc during its execution.</para>
<para>Later on, when you have a GC operation we will have release objects
events. As we identified the object during its creation we can determine
where the object was created, so we can show if a method is generating
leaks or not.</para>
</sect1>
<sect1 id="log">
<title>Capturing Log Files</title>
<para>The interceptor stays sleeping, not consuming any resources from the
JVM until it receives a weak-up method.</para>
<para>This is done by the MBean at the WebConsole. (e.g.
http://localhost:8080/jmx-console).</para>
<para>You have to look for the bean mbean=Native-profiler</para>
<para>After you have selected the MBean you will be able to:</para>
<para><itemizedlist>
<listitem>
<para>pause - Temporarily stops data collection</para>
</listitem>
<listitem>
<para>stop - Definitely close all the files</para>
<para>After this point, you can't collect more data and you need to
restart your application server if you want to collect more.</para>
<para>After this point also, the application keeps running.</para>
</listitem>
<listitem>
<para>activate - Start/Resume capturing data</para>
</listitem>
</itemizedlist></para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center" fileref="images/Screenshot-MBean.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
</sect1>
<sect1>
<title>Installing the MBean</title>
<para>To install the Native MBean you need to copy
jboss-profiler-noAOP.sar into your /server/deploy directory</para>
</sect1>
<sect1>
<title>Installing the Native Library (DLL/SO)</title>
<para>The only thing needed to have access to the native library, is to
have defined LD_LIBRARY_PATH (if Linux) or under the PATH (for
Windows).</para>
<para>Although sometimes is hard to distribute native code under Linux. On
that case you would have to recompile the native code in your
library.</para>
<para>You can test if the installation works by doing a simple:</para>
<para><literallayout>java -XrunjbossInspector:/tmp Foo
If the only error message you get is Class Foo not found, your native library installation is working</literallayout></para>
<sect2>
<title>Compiling the Native Library</title>
<para>You have of course to download the source code from CVS
first.</para>
<para>After you have download it, you need to:</para>
<itemizedlist>
<listitem>
<para>Make sure you gnu/gcc works</para>
</listitem>
<listitem>
<para>Define JAVA_HOME to a JDK as we need access to some
includes</para>
</listitem>
<listitem>
<para>Under <jboss-profiler-src>/native/<platform>,
execute the compilation script</para>
</listitem>
</itemizedlist>
</sect2>
</sect1>
<sect1>
<title>Start/Stop/Pause using the API</title>
<para>It is possible to directly use a
org.jboss.profiler.threadcheck.StartupProfilerCheck to control the life
cycle of your profiling.</para>
<para>StartupProfilerCheck is defined at profilerConsole.jar. You have
three methods defined:</para>
<para><literallayout> private native static void startProfilerInternal();
private native static void pauseProfilerInternal();
private native static void stopProfilerInternal();
</literallayout></para>
<para>These three methods are defined at jbossInspector.dll (or .so for
Solaris or .jnilib for apple)</para>
</sect1>
</chapter>
1.1 date: 2006/11/10 17:40:20; author: csuconic; state: Exp;jboss-profiler/docbook/en/modules/webinterface.xml
Index: webinterface.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="webinterface">
<title>Webinterface</title>
<sect1 id="webinterface-runtime">
<title>Runtime Profiler</title>
<sect2>
<title>Running Application</title>
<para>To start analyzing after the deployment, open this URL into your
WEB-Browser.</para>
<para><link
linkend="???">http://localhost:8080/jboss-profiler</link></para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-Runtime.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>You will have to type the directory where you added the log files.
It was not possible to create a select button as this is a Web
application. The good thing about a WebApplication for a profiler, is
that you can have people analyzing data remotely. (This is a good tool
for consultants. support staff and architects that may not be on
site)</para>
</sect2>
<sect2>
<title>Selecting the Process ID</title>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center" fileref="images/Screenshot-PID.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>Besides the option to select any process id you might need, you
have also three extra options that will control how to analyze the
log-files into profilerâs object-model:</para>
<para><itemizedlist>
<listitem>
<para>Stack on objects</para>
<para>You can locate where objects are created if this feature is
enabled</para>
</listitem>
<listitem>
<para>Stack on methods</para>
<para>You can generate the iteration between methods callings. If
not activated you wonât have reference information between
methods.</para>
</listitem>
</itemizedlist><itemizedlist>
<listitem>
<para>Calculate releases on GC operations</para>
<para>If activated a complete reference between object ids and
methods ID. Itâs a good option to locate memory-leaks</para>
</listitem>
</itemizedlist></para>
<para>After submit this following processing screen will be
viewed.</para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-Servlet.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>Follow the link, and you will see Process-View/Methods view as
default: You can have this view by clicking on
ProcessView-methods.</para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-ProceessView_Methods-tracing.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>You can proceed from this view to each of steps described in the
following sections respectively.</para>
</sect2>
<sect2>
<title>Detailing methodâs execution</title>
<para>You can click on the arrow icon to detail methodâs execution: You
can repeat that operation as many times you want inside methodâs
execution. Clicking on methodâs name (a hyperlink) has the same
effect.</para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-MethodsDetail.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>After you got on methods detail, you can have four views about the
current graph:</para>
<itemizedlist>
<listitem>
<para>Critical Path</para>
</listitem>
</itemizedlist>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-CriticalPath.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<itemizedlist>
<listitem>
<para>Pie Chart</para>
</listitem>
</itemizedlist>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-PieChart.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<itemizedlist>
<listitem>
<para>Instances Created:</para>
<para>(There is an extra view that adds sub-methods events)</para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-InstancesCreated.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>On this view you have information about how many objects were
created and <emphasis role="bold">released</emphasis> on that slice
of the graph. You have a <emphasis role="bold">complete</emphasis>
information about memory-leaks.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>Memory operations (ProcessView->Memory)</para>
<para>On Process-View/Memory you can look at GC operations:</para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-ProcessView_Memory.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>You can detail a GC operation:</para>
<para>Byou</para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-GcDetail.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>You can look for Leaks, have information about Creations or
Threads on this view.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>Consolidated View</para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-ConsolidatedView.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>On consolidated view, after you set filter parameters, you can
generate a XML, XLS or zipped XML about the model:</para>
</listitem>
</itemizedlist>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center" fileref="images/Screenshot-XML.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
</sect2>
<sect2>
<title>Tracing</title>
<para>You can click on the "Tracing" field to detail the flow of
"transaction" which is a sequence of methods executed in each method,
and this following processing screen will be viewed.</para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-Tracing_Servlet.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>Follow the link, and you will see the following view.</para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-Tracing_View.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>The upper part (list view) of the view lists all transactions of
the clicked method. The lower part (search view) provides an interface
where you can set conditions for searching specific transactions. The
"search view" lists the following items.</para>
<itemizedlist>
<listitem>
<para>start method name</para>
<para>Name of the clicked method.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>transaction type</para>
<para>You can specify whether target transactions are complete or
not. "Transaction type" has 3 choices.</para>
<itemizedlist>
<listitem>
<para>complete</para>
<para>This choice picks up transactions which have completed
from start to finish.</para>
</listitem>
<listitem>
<para>incomplete</para>
<para>This choice picks up transactions which have aborted
halfway.</para>
</listitem>
<listitem>
<para>both</para>
<para>This choice picks up both "complete" and "incomplete"
transactions. (default)</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>search conditions</para>
<para>For setting conditions, you have 6 options. If you select more
than 1 option, target transactions will have to meet conditions of
all the selected options. "Search conditions" has 6 choices.</para>
<itemizedlist>
<listitem>
<para>Period where target transactions have started</para>
<para>Specify start time and finish time of the period as
follows.</para>
<para><emphasis role="bold">MM/dd/yyyy
hh:mm:ss:SSS</emphasis></para>
</listitem>
<listitem>
<para>Period where target transactions have finished</para>
<para>Specify start time and finish time of the period as
follows.</para>
<para><emphasis role="bold">MM/dd/yyyy
hh:mm:ss:SSS</emphasis></para>
</listitem>
<listitem>
<para>Any method(s) executed in target transactions</para>
<para>Specify any string which is a part of the method's name.
You can specify more than one string by separating them by
space(" "). If you do so, the tracer picks up transactions
executing all of them (AND condition), or transactions executing
at least one of them (OR condition).</para>
</listitem>
<listitem>
<para>Any method(s) <emphasis role="bold">not</emphasis>
executed in target transactions</para>
<para>Specify any string which is a part of the method's name.
You can specify more than one string by separating them by
space(" "). If you do so, the tracer picks up transactions not
executing any of them (NOR condition), or transactions not
executing all of them (NAND condition).</para>
</listitem>
<listitem>
<para>Duration of target transactions</para>
<para>Specify duration by millisecond (SSS), and the tracer
picks up transactions elapsing more than the duration.</para>
</listitem>
<listitem>
<para>Duration of any method executed in target
transactions</para>
<para>Specify duration by millisecond (SSS), and the tracer
picks up transactions including any method(s) elapsing more than
the duration.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
<para>Set conditions as you like and submit, and the tracer picks up
transactions meeting the conditions. The "list view" will be refreshed
to list them. The table has the following fields.</para>
<itemizedlist>
<listitem>
<para>Start Time</para>
<para>Start time of the transaction.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>End Time</para>
<para>Finish Time of the transaction.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>Total Time</para>
<para>Duration of the transaction by the millisecond.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>#Methods</para>
<para>The number of methods executed in the transaction.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>CPU</para>
<para>CPU usage time of the transaction in nanosecond.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>#Locks</para>
<para>The number of locks in the transaction if any. If not, this
field is empty.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>Lock Time</para>
<para>Duration of the locks in the transaction in millisecond. If
there is are no locks, this field is empty.</para>
</listitem>
</itemizedlist>
<para>You can click on the arrow icon to detail each transaction. You
will see "transaction details view".</para>
<figure>
<title></title>
<screenshot>
<screeninfo></screeninfo>
<mediaobject>
<imageobject>
<imagedata align="center"
fileref="images/Screenshot-Tracing_Detail.png" />
</imageobject>
</mediaobject>
</screenshot>
</figure>
<para>The table has the following fields.</para>
<itemizedlist>
<listitem>
<para>Methods Order</para>
<para>Methods executed in the transaction are listed in sequence.
Indented methods mean nests. If you have specified any executed
method(s) on "search view" mentioned above, it/they is/are drawn in
different color from other methods.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>Start Time</para>
<para>Start time of each method.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>End Time</para>
<para>Finish time of each method. If you have chose "both" or
"incomplete" of "transaction type" item on "search view", this field
says "NOT EXIT" for any incomplete methods.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>Total Time</para>
<para>Duration of each method by the millisecond. If you have chose
"both" or "incomplete" of "transaction type" item on "search view",
this field says "UNKNOWN" for any incomplete methods.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>CPU Time</para>
<para>CPU usage time of each method.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>#Locks</para>
<para>The number of locks in each method if any. If not, this field
is empty.</para>
</listitem>
</itemizedlist>
<itemizedlist>
<listitem>
<para>Lock Time</para>
<para>Duration of the locks in each method in millisecond. If there
is are no locks, this field is empty.</para>
</listitem>
</itemizedlist>
</sect2>
</sect1>
<sect1 id="webinterface-memory">
<title>Memory Profiler</title>
<para></para>
</sect1>
</chapter>
1.1 date: 2006/11/10 17:40:20; author: csuconic; state: Exp;jboss-profiler/docbook/en/modules/concept.xml
Index: concept.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="concept">
<title>Concept</title>
<sect1 id="Interceptors">
<title>How it Works</title>
<para>The idea is simple, an interceptor sends events to a LOG file.
Another application (WEB application) reads its contents and shows
analysis.</para>
<para>Most of the work is done by the Analysis tool, and that's a good
thing as the work of analyzing the application is done outside of the
JVM's runtime. What I have seen from users is that this increases the
possibility of analysis and the user ends up capturing more
information.</para>
<para>Also, the idea of the interceptor is to stay "sleeping" until
someone wakes him up. This is always done by MBeans and there is a MBean
that manages each interceptor.</para>
<figure id="how-it-works.fig">
<title>Flow of Log Files</title>
<mediaobject>
<imageobject>
<imagedata align="center" fileref="images/HowItWorks.jpg" />
</imageobject>
</mediaobject>
</figure>
</sect1>
<sect1 id="JVMPI">
<title>JVMPI - Java Virtual Machine Profiler Interface</title>
<para>JVMPI is the interface defined for profiler events until JVM 1.4.
It's still supported in JVM 1.5, but will be removed soon. JVMPI is an
experimental C interface where you can capture events like enter method,
exit method, class-loading.</para>
<para>When the interceptor is active, these events are saved in binary
files for later processing:</para>
<itemizedlist>
<listitem>
<para>ClassLoad</para>
</listitem>
<listitem>
<para>Enter Method / Enter Exit</para>
</listitem>
<listitem>
<para>Object Alloc/Object Release</para>
</listitem>
<listitem>
<para>GCStart/GCFinish</para>
</listitem>
</itemizedlist>
<sect2>
<title>Options</title>
<para><itemizedlist>
<listitem>
<para>Add the
-XrunjbossInspector:<directory>,<options...> as a
parameter to your JVM. (Sun's or IBM's JVM)</para>
<literallayout>Possible options include:
start=<prefix name>
include=<prefix name>
ignore=<prefix name>
socket=<server|IP>:<port>
uniqueNames=true
wakeupOnStartup=true
Start the profiler always after the JVM start.
This is useful for running testcases.
memory=true|false (default=true)
Disable ObjectAlloc and ObjectRelease events.
tracer=true|false (default=false)
Enable MethodEntry and MethodExit events of Exception and Erorr classes
</literallayout>
</listitem>
</itemizedlist></para>
<para>To weak up this interceptor you would have to use the MBean</para>
</sect2>
</sect1>
<sect1 id="JVMTI">
<title>JVMTI - Java Virtual Machine Tool Interface</title>
<para>JVMTI is the replacement for JVMTI after Java 5.</para>
<para>We will re implement events defined at JVMPI(<xref
linkend="JVMPI" />), but for now we are only using this to capture memory
profiler snapshots (<xref linkend="memory-snapshot" />)</para>
<sect2>
<title>Options</title>
<para><itemizedlist>
<listitem>
<para>Add the -agentlib:jbossAgent</para>
<literallayout>
There are no options at this time
</literallayout>
</listitem>
</itemizedlist></para>
<para>The MBean responsible for the control of the life cycle for the
memory profiler has also some utility methods</para>
<itemizedlist>
<listitem>
<para>forceGarbageCollector</para>
</listitem>
<listitem>
<para>getLoadedClasses</para>
</listitem>
<listitem>
<para>getObjects(Class)</para>
</listitem>
</itemizedlist>
</sect2>
</sect1>
<sect1>
<title>How it's compared to commercial tools</title>
<para>The first thing that differs JBossProfiler is its conception based
in LogFiles instead of wired protocols. This gives the tool more power
plus enabling remote teams to analyze remote scenarios with minimal setup
on servers.</para>
<para>Usually I say that JBossProfiler has <emphasis role="bold">enough
</emphasis>features to find bottlenecks.</para>
<para>Features that both JBossProfiler and Commercial Tools will
have:</para>
<itemizedlist>
<listitem>
<para>Tree Navigation over the graph of callings</para>
</listitem>
<listitem>
<para>Graph visualization of the graph of callings</para>
</listitem>
<listitem>
<para>% Identification of Bottlenecks</para>
</listitem>
</itemizedlist>
<para>There are of course features unique to JBossProfiler. Original
ideas:</para>
<itemizedlist>
<listitem>
<para>LogFile based</para>
<para>This is idea to support teams, where the problem is away from
your analysis tool.</para>
<para>Also, this seems to increase the power of analysis. Usually you
can analyze more data with JBossProfiler.</para>
</listitem>
<listitem>
<para>Memory Profiler based in Snapshot using only a server
MBean</para>
<para>A commercial profiler requires a front-end installed in order to
create the snapshot.</para>
</listitem>
<listitem>
<para>Object allocations and Object Releases referenced to
methods</para>
<para>I haven't seen that feature in any other profiler</para>
</listitem>
</itemizedlist>
<para>Usually commercial profilers are developer's tools, and of course
they have more developers features like nice integrations with IDEs and
Debuggers and views that can and sell lot of functionality. Well, we don't
want to compete with commercial profilers but we want to offer a nice view
about what is happening with your code and understand what is
happening.</para>
<para>Sometimes of course is more comfortable to use commercial tools but
you can always have the information you need with JBossProfiler</para>
</sect1>
</chapter>
1.1 date: 2006/11/10 17:40:20; author: csuconic; state: Exp;jboss-profiler/docbook/en/modules/memory.xml
Index: memory.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="memory">
<title>Memory Profiler</title>
<sect1 id="memconcept">
<title>Concept</title>
<para>The concept of the memory profiler is almost the same as the runtime
profiler. The only difference is that you can take several snapshots of
your memory during an execution.</para>
<para>You can extract a snapshot by using the MBean( <xref
linkend="usembean" />)</para>
<para>The CPU is frozen while the snapshot is being extracted, what
usually takes</para>
</sect1>
<sect1 id="memory-snapshot">
<title>Capturing a Snapshot</title>
<para>Steps to extract a snapshot:</para>
<para>- Add jbossAgent.dll to your path or libjbossAgent.so to your
LD_LIBRARY_PATH</para>
<para>- Add -agentlib:jbossAgent to your JVM 5 command line. (Java 5 at
least is required as JVMTI was introduced on Java 5)</para>
<para>- Go to JMX Console (http://localhost:8080/jmx-console) and look for
JBossProfiler:JVMTI MBean (mbean=JVMTIClass)</para>
<para>- Call heapSnapshot from JVMTIClass MBean. use P1 as a prefix, and
P2 as the extension. For instance P1=/tmp/log, and P2=mem. This will
create three files starting with log under /tmp, with
extension=.mem</para>
<para>- Use the JbossProfiler application
(http://localhost:8080/jboss-profiler) after you have installed
jboss-profiler.war to your /deploy directory.</para>
</sect1>
<sect1 id="file-formats">
<title>File formats</title>
<para>All the files used in the memory profiler are simple text files, CVS
like.</para>
<para>This way you can write your own tool to analyze the snapshot
generated.</para>
<sect2>
<title>Classes</title>
<para><itemizedlist>
<listitem>
<para>tagClass â An unique count id for the class</para>
</listitem>
<listitem>
<para>signature â The JNI signature for the class</para>
</listitem>
<listitem>
<para>tagClassLoader â The unique object id for the
classLoader</para>
</listitem>
</itemizedlist></para>
<para>Example:</para>
<para><literallayout>tagClass,signature,tagClassLoader
1,Ljava/io/BufferedWriter;,0
2,Ljava/util/Collections$ReverseComparator;,0
3,Ljava/lang/StringCoding$StringDecoder;,0
</literallayout></para>
</sect2>
<sect2>
<title>Objects</title>
<para><itemizedlist>
<listitem>
<para>ObjectTag â The Unique Count Id of an object</para>
</listitem>
<listitem>
<para>ClassTag â The Unique Count Id of the declaring class for
this object</para>
</listitem>
<listitem>
<para>Size â The size in bytes for this object</para>
</listitem>
</itemizedlist></para>
<para>Example:</para>
<para><literallayout>objectTag,classTag,size
1338,59,480
1339,106,88
1340,106,88
1341,106,88
</literallayout></para>
</sect2>
<sect2>
<title>References</title>
<para><itemizedlist>
<listitem>
<para>tagReferrer â ObjectTag for the object owning a
reference</para>
</listitem>
<listitem>
<para>tagReferred â ObjectTag for the object referenced</para>
</listitem>
<listitem>
<para>index â JVMTI sends this count that I didn't find any usage
for this. Itâs here for future usage.</para>
</listitem>
</itemizedlist></para>
<para>Example:</para>
<para><literallayout>tagReferrer, tagReferee,index
0,134,0
0,168,0
0,16,0
0,270,0
</literallayout></para>
</sect2>
</sect1>
</chapter>
1.1 date: 2006/11/10 17:40:20; author: csuconic; state: Exp;jboss-profiler/docbook/en/modules/jvmti.xml
Index: jvmti.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="jvmti">
<title>JVMTIInterface</title>
<sect1>
<title>Features</title>
<para>JVMTIInterface is class wrapping most features of JVMTI through a
Java interface. Using this interface you can inquiry things you wouldn't
be able using any regular Java API.</para>
<para>Things like:</para>
<itemizedlist>
<listitem>
<para>What are the current classes?</para>
</listitem>
<listitem>
<para>What are the current objects of a given class?</para>
</listitem>
<listitem>
<para>What is the memory state?</para>
</listitem>
</itemizedlist>
<para>This is very useful to improve testcases. You could "lock" your
memory setting an alarm if a test consumed more memory than expected. This
is relatively easy to use and this chapter is going to show examples in
how to do it.</para>
</sect1>
<sect1>
<title>The API</title>
<para>This section will show the most important methods part of the public
interface. These methods are very useful on JUnit tests.</para>
<para>Class <emphasis
role="bold">org.jboss.profiler.jvmti.JVMTIInterface</emphasis></para>
<table>
<title></title>
<tgroup cols="3">
<colspec align="center" />
<tbody>
<row>
<entry><emphasis role="bold">MethodName and
Signature</emphasis></entry>
<entry><emphasis role="bold">Description</emphasis></entry>
<entry><emphasis role="bold">Exposed through
MBean</emphasis></entry>
</row>
<row>
<entry>Class getClassByName(String className)</entry>
<entry>search for all classes and return the first class maching
className</entry>
<entry>N</entry>
</row>
<row>
<entry>Object[] getReferenceHolders(Object [] objects)</entry>
<entry>return all the objects holding references to the objects
passed by parameter</entry>
<entry>N</entry>
</row>
<row>
<entry>Class[] getLoadedClasses()</entry>
<entry>return all loaded classes</entry>
<entry>N</entry>
</row>
<row>
<entry>void notifyInventory(boolean notifyOnClasses, String
temporaryFileReferences, String temporaryFileObjects,
JVMTICallBack callback)</entry>
<entry>navigate through the entire HEAP sending results to
JVMTICallBack interface. This process needs temporary files during
its collection.</entry>
<entry>N</entry>
</row>
<row>
<entry>Object[] getReferenceHolders(Object [] objects)</entry>
<entry>return all the referenceHolders for the objects passed by
parameter.</entry>
<entry>N</entry>
</row>
<row>
<entry>Class[] getLoadedClasses()</entry>
<entry>return all loaded classes on the JVM.</entry>
<entry>N</entry>
</row>
<row>
<entry>Object[] getAllObjects(Class clazz)</entry>
<entry>return all objects on a given class.</entry>
<entry>N</entry>
</row>
<row>
<entry>Object[] getAllObjects(String className)</entry>
<entry>return all objects on all classes where
class.getName().equals(className). This is in case more than one
classLoader loads the same class.</entry>
<entry>N</entry>
</row>
<row>
<entry>void heapSnapshot(String basicFileName, String
suffix)</entry>
<entry>Exposes heap to files. Look at manual for more
details.</entry>
<entry>Y</entry>
</row>
<row>
<entry>String exploreClassReferences(...)</entry>
<entry>Report method. This method reports references to
classes.</entry>
<entry>Y</entry>
</row>
<row>
<entry>String exploreObjectReferences(String className, int
maxLevel, boolean useToString)</entry>
<entry>Report method. Will show a reference tree for objects
instanceof className.</entry>
<entry>Y</entry>
</row>
<row>
<entry>void forceReleaseOnSoftReferences()</entry>
<entry>Will allocate memory until an OutOfMemoryException happens,
release it, and forceGC. This will force SoftReferences to go
away.</entry>
<entry>Y</entry>
</row>
<row>
<entry>void forceGC()</entry>
<entry>Will force a FullGC by a JVMTI method (not System.gc) what
guarantees a FullGC execution.</entry>
<entry>Y</entry>
</row>
<row>
<entry>String listClassesHTMLReport()</entry>
<entry>Report Method. Will show duplications and every single
loaded class on the JVM</entry>
<entry>Y</entry>
</row>
<row>
<entry>String inventoryReport()</entry>
<entry>Report Method. Will show a summary of Objects allocations
per class. This method is very useful to inspect number of objects
and number of bytes for every single class on the system.</entry>
<entry>Y</entry>
</row>
<row>
<entry>String printObjects(String className)</entry>
<entry>Report Method. Will show a summary of every single object
instanceof ClassName.</entry>
<entry>Y</entry>
</row>
<row>
<entry>Map produceInventory()</entry>
<entry>Returns a WeakHashMap<Class,InventoryDataPoint>
summarizing the current JVM's inventory. This could be used by
compareInventories and be used on JUnit tests making sure the
system is not allocating more objects than expected.</entry>
<entry>N</entry>
</row>
<row>
<entry>boolean compareInventories(...)</entry>
<entry>Compares two distinct Inventories validating expected
boundaries defined by parameters.</entry>
<entry>N</entry>
</row>
</tbody>
</tgroup>
</table>
</sect1>
<sect1>
<title>Report example</title>
<para>if you use inventoryReport for example, you would have this
output:</para>
<informaltable>
<tgroup cols="3">
<tbody>
<row>
<entry>Class</entry>
<entry>#Instances</entry>
<entry>#Bytes</entry>
</row>
<row>
<entry>[C</entry>
<entry>75194</entry>
<entry>7294512</entry>
</row>
<row>
<entry>[I</entry>
<entry>2641</entry>
<entry>3226560</entry>
</row>
<row>
<entry>java.util.HashMap$Entry</entry>
<entry>128603</entry>
<entry>3086472</entry>
</row>
<row>
<entry>java.lang.String</entry>
<entry>111955</entry>
<entry>2686920</entry>
</row>
<row>
<entry>[Ljava.util.HashMap$Entry;</entry>
<entry>31239</entry>
<entry>2639088</entry>
</row>
<row>
<entry>[Ljava.lang.Object;</entry>
<entry>10456</entry>
<entry>1798312</entry>
</row>
<row>
<entry>java.util.HashMap</entry>
<entry>31199</entry>
<entry>1247960</entry>
</row>
<row>
<entry>[B</entry>
<entry>718</entry>
<entry>1247680</entry>
</row>
<row>
<entry>java.lang.reflect.Method</entry>
<entry>12799</entry>
<entry>1023920</entry>
</row>
<row>
<entry>javax.management.modelmbean.DescriptorSupport$CaseIgnoreString</entry>
<entry>45076</entry>
<entry>721216</entry>
</row>
<row>
<entry>org.jboss.mx.server.InvocationContext</entry>
<entry>9054</entry>
<entry>579456</entry>
</row>
<row>
<entry>javax.management.modelmbean.DescriptorSupport</entry>
<entry>19205</entry>
<entry>307280</entry>
</row>
<row>
<entry>[Ljava.lang.String;</entry>
<entry>14340</entry>
<entry>298104</entry>
</row>
</tbody>
</tgroup>
</informaltable>
</sect1>
<sect1>
<title>Testing MemoryLeaks</title>
<sect2>
<title>ClassLoader Leakage</title>
<para>This page shows why a classLoader reference would leak. Instead of
putting all these details here, I will just point the URL as a
reference:</para>
<para><link linkend="???"><ulink
url="http://wiki.jboss.org/wiki/Wiki.jsp?page=ClassLeakage">http://wiki.jboss.org/wiki/Wiki.jsp?page=ClassLeakage</ulink></link></para>
<para>As you can see on the URL, the classLoader won't be released
untill all your strong references are cleared. The only strong
references to a class or classLoader you don't need to release are
references to your own classes or your own classLoader. Like, if a user
makes a reference to a User's class on its JAR, GC will be able to
determine the whole group is self contained thus the package can be
released from the memory.</para>
<para>It's okay to make a reference for your user class, but if you are
writting a framework or anything that will be used by super classLoaders
using any sort of meta data and reflection, than you are highly
ellegible of creating what we call a redeployment leak. That means a
classLoader won't be garbage collected thus the class will never leave
the memory.</para>
<para>ideally all your references to a Class, ClassLoader needs to be a
WeakReference, and references to reflection will need to be a
SoftReference.</para>
<para>If you read the wiki page in detail you will realize that is
really hard to keep up with these constraints and if you don't have a
testcase is very likely you will create a redeployment leak some
day.</para>
<para>First thing you need in your test is an artificial classLoader.
JBossTest project has a super class (org.jboss.test.JBossMemoryTestCase)
you can use as base for this kind of test. In particular you need to use
the newClassLoaderMethod:</para>
<programlisting> protected static ClassLoader newClassLoader(Class anyUserClass) throws Exception
{
... This will create a regular classLoader
}
</programlisting>
<para>Than you have to execute your methods using this classLoader. You
could call a super method (using reflection). At the end, release every
single instance, you could call a forceGC and the classLoader would have
been released.</para>
<para>The secret on this type of test is to not use any strong reference
(do not use imports to your class), and use getClassByName(String name).
The class then is supposed to be released.</para>
<para>The following list is a simplified but real example:</para>
<programlisting>/**
* This class requires -agentlib:jbossAgent on JVM arguments on the JVM for
* working properly
*
* @author csuconic
*
*/
public class MemoryLeakTestCase extends TestCase {
public void testSample() throws Exception {
JVMTIInterface jvmti = new JVMTIInterface();
ClassLoader loader = newClassLoader();
Class theClass = loader.loadClass("org.jboss.serial.memory.test.SomePojo");
jvmti.forceGC();
// The class still on the memory
assertNotNull(jvmti.getClassByName("org.jboss.serial.memory.test.SomePojo"));
theClass = null;
loader = null;
jvmti.forceGC();
assertNull(jvmti.getClassByName("org.jboss.serial.memory.test.SomePojo"));
}
/** Will create a ClassLoader to be used by the test */
private static URLClassLoader newClassLoader() throws MalformedURLException {
String dataFilePath = MemoryLeakTestCase.class.getResource("test")
.getFile();
String location = "file://"
+ dataFilePath.substring(0, dataFilePath.length()
- "org.jboss.serial.memory.test".length());
StringBuffer newString = new StringBuffer();
for (int i = 0; i < location.length(); i++) {
if (location.charAt(i) == '\\') {
newString.append("/");
} else {
newString.append(location.charAt(i));
}
}
String classLocation = newString.toString();
URLClassLoader theLoader = URLClassLoader.newInstance(new URL[] { new URL(
classLocation) }, null);
return theLoader;
}
}
</programlisting>
<para>With JVMTI you can inquire about the objects/classes inventory and
assert about its expected state. As the classLoader wouldn't tell if you
if a class is loaded or not, the only way to do so is using an API
exposing DEBUG properties like JBossProfiler does through
JVMTIInterface.</para>
<para>If you look at the testcase above you will see these
operations:</para>
<itemizedlist>
<listitem>
<para>ClassLoader creation</para>
</listitem>
<listitem>
<para>loadClassOperation</para>
</listitem>
<listitem>
<para>forceGC</para>
</listitem>
<listitem>
<para>assertionNotNull (using jvmti.getClassByName)</para>
<para>So if the class was released by accident, like if something is
not holding the reference by accident. (maybe a too weak
scenario)</para>
</listitem>
<listitem>
<para>releasing references</para>
</listitem>
<listitem>
<para>forceGC</para>
</listitem>
<listitem>
<para>assertNull operation (using jvmti.getClassByName)</para>
<para>At this point there isn't any reference to the classLoader (or
to the class). So if a GC happens the class will be released from
the memory.</para>
</listitem>
</itemizedlist>
<para>This example is relatively simple and you could improve a lot on
top of that. If you need more concrete examples look at projects like
JBoss AOP, JBoss Serialization and JBoss MC. All these projects will
have a MemoryLeakTestCase validating scenarios like this.</para>
</sect2>
<sect2>
<title>Objects Leakage</title>
<para>Objects leakages are much easier to understand. But the problem
is, everybody think it's so easy to understand that every programmer in
the universe think that the GarbageCollection is always sufficient to
capture our garbage. Well, in few words the GC is capable to capture our
garbage, not our crap :-)</para>
<para>Most source of MemoryLeaks are Collections holding references when
they are supposed to release the information. Most times this happens
through publish/subscriber routines loosing some communication. Some
occasions the linked list scenario could also happen by accident.</para>
<para>The API to test Object Leakages is pretty simple, just two
methods:</para>
<itemizedlist>
<listitem>
<para>WeakHashMap<Class,InventoryDataPoint>
produceInventory</para>
</listitem>
<listitem>
<para> boolean compareInventories</para>
<para>Parameters:</para>
<itemizedlist>
<listitem>
<para>reportOutput You could set System.out here. The location
where logging information is going to be sent.</para>
</listitem>
<listitem>
<para>map1 The first snapshot</para>
</listitem>
<listitem>
<para>map2 The second snapshot</para>
</listitem>
<listitem>
<para>ignoredClasses Classes you want to ignore on the
comparisson. Used to ignore things you know are going to be
produced and you don't have control over the testcase</para>
</listitem>
<listitem>
<para>prefixesToIgnore Same thing as classes, but every classes
starting with these prefixes are going to be ignored</para>
</listitem>
<listitem>
<para>expectedIncreases An array of InventoryDataPoint with the
maximum number of instances each class could be
generating.</para>
</listitem>
</itemizedlist>
</listitem>
</itemizedlist>
<para>This is an example on how to validate memory leaks:</para>
<programlisting>public void testNotifyOnObjects() throws Exception {
class TestClass {
}
JVMTIInterface jvmti = new JVMTIInterface(); // The JVMTIWrapper used to
// produce inventories
TestClass keepr = new TestClass(); // at least one instance, so point2
// won't be null
Map firstMap = jvmti.produceInventory(); // The inventory of classes, this
// is
// HashMap<Class,InventoryDataPoint>
TestClass[] tests = new TestClass[1000];
for (int i = 0; i < 1000; i++) {
tests[i] = new TestClass(); // allocating 1000 objects
}
Map secondMap = jvmti.produceInventory(); // the second inventory
InventoryDataPoint point1 = (InventoryDataPoint) secondMap
.get(TestClass.class);
InventoryDataPoint point2 = (InventoryDataPoint) firstMap
.get(TestClass.class);
assertEquals(1000, point1.getInstances() - point2.getInstances()); // you
// can
// manually
// compare
// it
assertTrue(jvmti
.compareInventories(System.out, firstMap, secondMap,
new Class[] { WeakHashMap.class }, new String[] {
"[Ljava.util.WeakHashMap$Entry;", "java.lang.ref" },
new InventoryDataPoint[] { new InventoryDataPoint(TestClass.class,
2000) }));
assertFalse(jvmti
.compareInventories(System.out, firstMap, secondMap,
new Class[] { WeakHashMap.class }, new String[] {
"[Ljava.util.WeakHashMap$Entry;", "java.lang.ref" },
new InventoryDataPoint[] { new InventoryDataPoint(TestClass.class,
100) }));
}
</programlisting>
<para>Basically this test is:</para>
<orderedlist>
<listitem>
<para>Saving a first memory inventory snapshot, calling
produceInventory</para>
</listitem>
<listitem>
<para>Doing some operations. (allocating memory)</para>
</listitem>
<listitem>
<para>Doing comparissons on the snapshot</para>
</listitem>
</orderedlist>
<para>Anything allocating more memory than expected is going to generate
a failure on this testsuite.</para>
<para>With a testcase like that you are locking the doors of memory
leaks in your system.</para>
</sect2>
</sect1>
</chapter>
1.1 date: 2006/11/10 17:40:20; author: csuconic; state: Exp;jboss-profiler/docbook/en/modules/compiling.xml
Index: compiling.xml
===================================================================
<?xml version="1.0" encoding="UTF-8"?>
<chapter id="compiling">
<title>How to Compile Native Libraries</title>
<para>There are two native libraries for JBossProfiler, JVMTI and
JVMPI.</para>
<para>JVMPI is a API released for JVM 1.4, and is being replaced by a newer
and better version called JVMTI.</para>
<para>We are still supporting both versions as JVMPI is the only native way
to extract performance metrics from JVM 1.4.</para>
<sect1>
<title>Requirements</title>
<para>In case you are using windows, you will need cygwin installed in
order to compile either JVMPI or JVMTI.</para>
<para>You will then need g++ and gcc installed. </para>
<para>You also need JAVA_HOME defined to a valid JDK 1.4 (JVMPI) or JDK
1.5 (JVMPI and JVMTI), as some includes will be used under JDK
directory.</para>
</sect1>
<sect1 id="compiling-JVMPI">
<title>Compiling JVMPI Module</title>
<para>Under jvmti-lib there are one directory for each platform. (linux,
solaris, macos and win32).</para>
<para>Go the directory that represents your platform and call ./compile.sh.</para>
</sect1>
<sect1 id="compiling-JVMTI">
<title>Compiling JVMTI Module</title>
<para>Under jvmpi-lib there are one directory for each platform. (linux,
solaris, macos and win32).</para>
<para>Go the directory that represents your platform and call ./compile.sh.</para>
<para></para>
</sect1>
</chapter>
More information about the jboss-cvs-commits
mailing list