Virtual Machine Level Analysis¶
Maxine contains an experimental extension to support analysis of code executing on the virtual machine (VM). Since the VM is itself written in Java, the analysis is applicable, in principle, to the VM itself, the platform (JDK) and the application.
The analysis is implemented primarily by advising the execution of the bytecodes. This is similar to systems like AspectJ except that the advice is applied to the bytecodes and not to language-level constructs. However, since the translation of language-level constructs to bytecodes is well-defined, language-level advising could, in principle, be added as a separate layer. Certain other VM runtime operations, for example, garbage collection, thread start/end can also be advised.
The Virtual Machine Level Analysis (VMA) project is currently
implemented as an extension to Maxine in the com.oracle.max.vm.ext.vma
and com.oracle.max.vma.tools
projects.
The implementation exploits the flexibility inherent in the Maxine VM by
defining custom versions of several existing Maxine schemes, and
building a custom VM image.
Currently bytecode advising is limited to code generated by the (template) JIT compiler, although it is expected to be added to the optimizing compiler in due course.
VMA shares some similarity with aspects of the JVMTI API, most notably the method entry/exit and field access/watch capabilities and some of the runtime advice, e.g. thread start/end. Eventually, the redundant features may be removed and the two implementations merged. In the interim, some analyses can benefit from both systems, using Maxine’s Java JVMTI interface JJVMTI.
There is the beginnings of VMA for Graal in the
com.oracle.max.vm.ext.vma
project.
However, it should be considered experimental.
Architecture¶
To facilitate experimentation the VMA architecture is highly flexible and configurable. The system contains four basic components:
- a custom version of the T1X JIT compiler (VMAT1X) that uses custom templates for adding advice at bytecode translation time.
- the VMA runtime which invokes methods in an advice handling class that can be specified either at VM image build time or loaded dynamically as a VM extension.
- a store interface that supports the persistent storage of advice data for offline analysis, with an implementation that can
- be specified at runtime.
- a tool that can execute queries against the data in the persistent store.
Note that advising is disabled while in the scope of a handler execution, to prevent recursive entry from instrumented code that may be shared by the handler.
Building a VMA-enabled image¶
mx image @vma-t1x
This VM image includes the custom VMA schemes but does not specify an
advice handler which must, therefore be loaded dynamically using the VM
extension mechanism.
By default advising is enabled, and if no handler or built into the VM
Image or loaded as a VM extension, the VM will abort. To disable
advising set -XX:-VMA
option.
Running a VMA-enabled image¶
A VMA-enabled image can be run in the usual way with the max vm
command.
When advising is enabled (the default), the VMAT1X compiler is used for
compiling dynamically loaded classes.
This compiler will use the advice-enabled T1X templates.
By default all methods in dynamically loaded classes are processed by
VMAT1X.
However, this can be controlled more precisely with the -XX:VMAMI
and
-XX:VMAMX
options.
Both options take values that are regular expressions in the format
expected by java,util.regex.Pattern
.
The -XX:VMAMI
option specifies methods to include and -XX:VMAMX
specifies methods to exclude.
If -XX:VMAMI
is unset, all methods are candidates for processing with
VMAT1X, otherwise only those methods that match the pattern.
In either case, if the -XX:VMAMX
is also set, it excludes any method
in the candidate set that matches its pattern.
The syntax of a method pattern is
qualified_classname#methodnameunqualified_param_class_1, unqualified_param_class_2, ...
.
Note that the parameter list braces must be escaped, as must the square
braces in any array class specifier.
The wildcard specifier .
can be used to match all method names and/or
signatures.
The exact set of bytecodes that have advice applied during compilation
can also be controlled with options.
By default, all bytecodes are advised but, depending on the desired
analysis, a subset is usually more appropriate.
While it is possible to be quite specific about exactly which bytecodes
will be advised, there are some predefined configurations set via the
VMAConfig
option that are easier to use, e.g.:
entry
: advises after method entryentryexit
: advises after method entry and before return, including return by thrown exceptionmonitor
: advises the acquisition and release of monitors.read
: advises any access to an object’s state. An access is defined as any read of an object’s fields or its metadata or, if an array, it’s elements.write
: advises any write to an object’s fields or, if an array, any of its elements.objectaccess
: advises the creation of objects and all access sites.objectuse
: advises the creation of objects and all usage sites. A use is defined as any load or store of the object reference, or any access.
The VMAConfig
options accepts a list of these configurations and
aggregates them into a single set of the appropriate bytecodes to be
advised.
The specific bytecode advice controls are -XX:VMABI
and -XX:VMABX
and behave very similarly to the class controls.
Their argument is a regular expression matching bytecodes to be included
or excluded, respectively.
To provide control over enabling before/after advice a bytecode may be
suffixed by :A
, :B
or :AB
.
Note that while all the bytecodes in the standard set defined by the JVM
can be individually controlled, the VMAdviceHandler
interface
aggregates the advice for collections of similar bytecodes into a single
method.
For example, one can advice just the ICONST_0
and ICONST_2
bytecodes, but the advice for both will be directed to the
VMAdviceHandler.adviseBeforeConstLoad
method.
The aggregating methods do not provide a way to distinguish which
bytecode generated the advice.
Recording Time¶
Certain handlers can optionally gather timing information, notably
SyncStoreVMAdviceHandler
and VMLogStoreVMAdviceHandler
.
The VMATime
option provides a standard way to specify how time is
gathered.
If the option value is none, time is not recorded.
If the value starts with wallns
, then wall clock time is gathered
using System.nanoTime
.
If the value starts with wallms
, then wall clock time is gathered
using System.currentTimeMillis
.
VMLogStoreVMAdviceHandler
requires the advice records to be ordered in
the per-thread persistent stores, so that the analysis tool can
reproduce a global order.
As well as wall time, this can be achieved by a globally unique id,
which can be enabled by setting the option value to ida
.
This variant has considerably less overhead that gathering wall clock
time, yet tracks wall clock time quite closely.
The TimeTestVMAdviceHandler
can be used to compare the two values over
a run.
Thread Advising¶
By default all application threads are enabled for advice.
However a subset can be enabled by using the VMATI
and VMATX
options.
Sampled Advising¶
By default advising is on all the time which, evidently, has a significant performance impact on the application. Sampled advising, which is enabled by the -XX:VMASample option only enables advising periodically during the VM execution. The option value is a string of the form initialperiod,interval,period, all of which are optional. The interval value denotes the time, in milliseconds, between advising periods. The period value denotes the length of the advising period. The VM starts with advising enabled for initialperiod. If not specified the values default to 50, 50 and 10, respectively.
VM Options Summary¶
VMA
: boolean valued option that enables/disables advising in the VM. Default istrue
.VMAMI=p
:p
is a regular expression pattern specifying methods to include for instrumentation.VMAMX=p
: regular expression pattern specifying methods to exclude for instrumentation. OverridesVMAMI
.VMAXJDK
: boolean valued option that excludes all JDK classes from instrumentation.VMABI=p
:p
is a regular expression pattern of bytecodes to include for instrumentation.VMABX=p
:p
is a regular expression pattern of bytecodes to exclude for instrumentation. OverridesVMABI
.VMAConfig=c
:c
is a comma spearated list of configuration names that instrument for specific analyses.VMATI=p
:p
is a regular expression pattern of threads to have advising enabled.VMATX=p
:p
is a regular expression pattern of threads to have advising disabled. Overrides VMATI.VMATime=none|wallns|wlaams|ida}
: specify how time is recorded in certain advice handlers. Default iswallns
.VMASample=initialperiod,interval,period
: run in sampling mode. Defaults to50,50,10
.
Standard Handlers¶
Several existing handlers are provided, most notably handlers that store
the generated advice to an external file for offline analysis.
The default location for the external store is a directory vmastore in
the current working directory that the VM is launched in.
This can be changed by setting the -Dmax.vma.store.dir
property.
SyncStoreVMAdviceHandler
is a simple, but inefficient, handler that
synchronously stores the advice record to the store, and incurs
per-advice synchronization overhead as all threads access the same
store.
Output goes to the shared store file named vm in the store directory.
VMLogStoreVMAdviceHandler
uses a custom instance of the VMLog
class
to store advice records in per-thread buffers.
When the buffer is full it is flushed to a file in a compact textual
format, that can be processed with the QueryAnalysis
tool.
VMLogStoreVMAdviceHandler
adds a small, but generally consistent,
overhead to the execution of each bytecode.
Assuming the use of the default text-based store, it also causes object
allocation as internal objects are converted into String
representations when the records are flushed.
The maximum latency occurs when the store buffer is flushed to the
file.
Note: this handler requires that some of its code to be included in
the boot image as it adds some VM thread local variables, and these
cannot be added at runtime.
This handler operates in per-thread mode throughout the store process,
thereby avoiding almost all synchronization overhead.
Developers can define additional handlers for specific purposes that
may, for example, do all analysis internally in the VM.
An example is CBCVMAdviceHandler
that simply counts the advice calls
and outputs a summary at the end of
execution.
ThreadLocalVMAdviceHandler
analyses object use for thread
locality.
Evidently such handlers incur much less CPU overhead that those that
externalize the data, but may incur additional memory costs.
Handlers that only handle a subset of the advice calls should subclass
NullVMAdviceHandler
which defines a null implementation of each advice
method.
Note that CBCVMAdviceHandler
can be used to estimate the size of the
persistent store that would be created by VMLogStoreVMAdviceHandler
or
SyncStoreVMAdviceHandler
, since the store will contain approximately
the same number of lines as the number of advice counts reported. On
average a trace line in the store is 16 bytes in length.
Per-Object State¶
One of the issues for analysis tools, either online or offline, is
associating analysis-specific state with an object, for example a unique
identifier.
The standard approach is to use a Map
but this has problems both with
the space overhead and the fact that the map keeps objects reachable,
which perturbs the behavior of the garbage collector.
An WeakHashMap can mitigate the latter problem but perturbs the garbage
collector in a different way and provides no guarantee of object lookup
if the object is collected.
VMA provides a solution to this by using a custom Maxine object layout
scheme, XOhm
, to provide extra header words for use by VMA handlers.
Evidently this has some impact on the behavior of the system, for
example, making garbage collection more frequent owing to the increased
object size.
However, the overhead is as minimal as can be achieved.
By default, one extra word is provided and basic access to the state
word is provided by the ObjectState
class.
Support for unique identifiers is provided through the ObjectId
interface and support for marking bits through the ObjectBitSet
interface.
The class SimpleObjectState
implements both of these
interface.
Additional words can be included by setting the
max.vm.layout.xohm.words
system property on the image build.
For example setting -Dmax.vm.layout.xohm.words=2
would provide a total
of two additional header words, one for use by ObjectId
and
ObjectBitSet
and one for use by the handler.
Access to the additional words is through the ObjectVars
interface.
The class VarsObjectState
extends SimpleObjectState
to implement
this interface.
Note that only scalar values can be stored in the extra header words as
they are not scanned by the garbage collector.
Handlers that need to use an persistent object id to represent an
object, should subclass ObjectStateAdapter
which implements all the
VMAdviceHandler
methods that take Object
types as arguments.
Unique identifiers are assigned to objects returned by the NEW family of
bytecodes.
Objects passed as arguments to the other methods are checked for a uuid
having been assigned and, if not, the abstract method unseenObject
,
which must be implemented the handler, is called.
The adapter also handles unique id generation for ClassLoader
instances,
since these may be user defined.
Specifying handlers¶
Handlers can either be built into the boot image or loaded dynamically as a VM extension.
Building handlers into the boot image¶
To build an advice handler into the boot image set the
max.vma.handler.class system
property to the fully qualified name of a
class that extends VMAdviceHandler
, e.g.:
mx --Jp @-Dmax.vma.handler.class=com.oracle.max.vm.ext.vma.handler.store.sync.h.SyncStoreVMAdviceHandler image @vma-t1x
A short form is available for the standard handlers using the max.vma.handler property:
null
:NullVMAdviceHandler
syncstore
:SyncStoreVMAdviceHandler
vmlogstore
:VMLogStoreVMAdviceHandler
cbc
:CBCVMAdviceHandler
tl
:ThreadLocalVMAdviceHandler
When creating a new handler it is important to prevent it being included
in the boot image by default.
This is achieved by adding a Package
class to the handler package that
specifies inclusion only when the -Dmax.vma.handler.class
option
matches the handler in question.
See the the existing handlers for an example.
Dynamically loaded handlers¶
Follow the instructions for building a VM extension JAR file, using one of the included handlers as an example, the load the handler at runtime, e.g.:
mx vm -vmextension:yourhandler.jar ...
Also, look at one of the Eclipse JAR file creation descriptions for the existing handlers, in the file with extension jardesc. Note that all referenced classes that are not already included in the boot image must be specified in the jar file, as the VM extension mechanism has no search path support.
Instrumenting JDK classes in the Boot Image¶
It is possible to instrument JDK methods that were included in the boot image. This occurs transparently if such a JDK method is in set of methods specified to be instrumented. This is implemented on VM startup by deoptimizing the methods in the boot image. Note that this can greatly increase the quantity of generated advice and also has an impact on the performance of the handlers themselves since, although advising is disabled in the scope of a handler, the JDK method is no longer optimized.
Note that the -XX:+VMAXJDK
can be used to suppress instrumentation of
all JDK methods. Setting this option is the easiest way to just
instrument all application methods.
VMA and Handler Initialization¶
VMA overrides the standard run scheme, JavaRunScheme
, with
VMAJavaRunScheme
, to interpose on the VM startup to perform VMA
specific initialization.
VMAdviceHandler
defines an initialise(MaxineVM.Phase phase)
method
that normally should be overridden in a handler, and this method is
called from VMAJavaRunScheme
.
The only phases that are of interest are BOOTSTRAPPING
, RUNNING
and
TERMINATING
.
BOOTSTRAPPING
is only relevant for the case where the handler is being
included in the boot image, and provides an opportunity to allocate and
initialize certain data structures in the boot heap.
Other initialization must be performed in the RUNNING
phase.
In order for the handler to influence the behavior of the system, for
example,to customize the bytecodes that are advised, the handler’s
initialise method is called before any methods are instrumented and
before the JDK classes are considered for deoptimization and
instrumentation.
Note that this means that some JDK classes may be loaded and compiled
without instrumentation as a side effect of being used by the handler’s
initialise method.
However, these will be recompiled and instrumented if required as part
of the JDK instrumentation phase.
Actual advice method invocations are not enabled until after the
VMAJavaRunScheme.initialize
returns in the RUNNING
phase.
The TERMINATING
phase is typically where the handler reports any
results, using whatever mechanism it chooses.
Note that the onLoad
method of a dynamically loaded handler is called
in the STARTING
phase, which precedes the RUNNING
phase.
Typically all the method should do is register an instance of the
handler using VMAJavaRunScheme.registerAdviceHandler
, so that it can
be invoked in the RUNNING
phase.
Properties to control VMA¶
VMA behavior can be controlled by setting some system properties in addition to the command line options. These are generally handler specific.
Boot Image Generation Properties¶
max.vma.vmlog
: This property must be set on a boot image build and controls whether the customVMLog
used byVMLogStoreVMAdviceHandler
is included. It is on by default but the code can be excluded by setting the value to false.max.vma.handler.class
: The fully qualified name of a handler class to be included in the boot image.max.vma.handler
: The short name of a standard handler class to be included in the boot image.
Handler Specific Properties¶
max.vma.handler.cbc.sort
: When set,CBCVMAdviceHandler
sorts the pan-thread advice counts by frequency.max.vma.store.bufsize
: The size of theStringBuilder
used to buffer store records. Default is 1 MB.max.vma.store.flush
: The size at which the store buffer is flushed to the file; defaults tomax.vma.store.bufsize
.max.vma.store.textkey
: Use a 3 character mnemonic key for stored records instead of a single digit code.
Performance¶
The performance overhead varies, evidently, with the set of bytecodes that are being advised and the set of classes that are subject to instrumentation. Performance is fundamentally limited by VMA currently being restricted to the T1X baseline compiler. The numbers presented below are for the SpecJVM98 benchmarks. The overhead of using T1X with no optimization for hot methods varies considerable depending on the application behavior, averaging 6.9% for SpecJVM98 with a range of 1.0% to 16.7%. The benchmarks that make use of the JDK classes show much less overhead since they are able exploit the optimized JDK methods compiled into the boot image.
The NullVMAdviceHandler
provides a measure of the basic overhead of a
handler.
The overhead is relative to Maxine using T1X with no optimization of hot
methods with every bytecode advised.
The average overhead is 3.5%, with a range of 1.8% to 7.3%, when only
the benchmark classes are instrumented.
If we restrict the advice to just those bytecodes needed by the
objectuse
configuration, the overhead averages 2.1% with a range of 1.3%
to 3.7%.
If the JDK classes are also instrumented, including those in the boot
image, the average overhead with all bytecodes advised increases to
5.6%, with a range of 1.8% to 12% and for the objectuse
configuration
averages 2.9% with a range of 1.4% to 6.8%.
Analysis Tools¶
QueryAnalysis¶
QueryAnalysis is a command line tool that was originally implemented in a project that was focused on analyzing objects for immutability. It reads the compact text form of the store file and builds a data structure suitable for analysis. The tool has no pre-defined analyses built in but supports dynamically loaded queries that are written to a standard API.
The basic data structure created by the tool is a list of the advice
records in the file.
Object instances and Maxine meta-objects, e.g. MethodActor
, are
replaced with types defined in the analysis tool, namely ObjectRecord
,
ClassRecord
, FieldRecord
and MethodRecord
, with the obvious
mappings.
The tools also builds some auxiliary data structures to facilitate analysis.
objects
: a map containing all the object instances in the store trace. The key is the id of the object and the value is theObjectRecord
. Note that since id’s might be reused by the VM as objects are garbage collected, the id is tagged with the allocation epoch to ensure uniqueness.classLoaders
: a map from classloader instances to a (sorted) map from classes loaded by that classloader. The key of the classLoaders map is the id of the classloader instance. The key of the class map is the name of the class and the value is theClassRecord
.missingConstructors
: Inevitably object instances occur in the trace for which no allocation event was seen, e.g. objects allocated in the boot image. These are given id’s that decrease from -1. ThemissingConstructors
map is keyed by the id and the value is the associatedObjectRecord
.allocationEpochs
: a list ofAllocationEpoch
objects that define when garbage collection events have occurred. Each instance specifies the period from one garbage collection to the next.objectCount
: the total number of object instances, that are not arrays, encountered in the trace.arrayCount
: the total number of array instances in the trace.
Usage:
[-f inpath] [-v] [-i queryfile] [-e query]
The default value of inpath
is vmastore
.
If the value is a directory (normal) it is expected to contain either a
vm file or a set of per-thread files.
If the value is a file, it is used directly.
Options:
-v
: Report on progress reading the store file, showing the time to read every 100000 records.-e query
: initial query to execute-i queryfile
: Execute the commands in queryfile before entering interactive mode.
After processing the store file the tool enters interactive mode
allowing queries to be executed against the data structures described
above.
The input prompt is %%
.
The following interactive commands are available:
e query
: The tool prependscom.oracle.max.vma.tools.qa.queries
and appendsQuery
to queryclass and then attempts to load that class, which must be a subclass ofQueryBase
, and then invokes its execute method. E.g., e Foo will attempt to invokecom.oracle.max.vma.tools.qa.queries.FooQuery.execute
. See below for details on the pre-defined queries.i infile
: Execute commands from infile.o outfile
: Redirect output to outfile or the standard output if outfile omitted.
A query is executed with the command:
%% e query
Standard Query Arguments¶
-v
: set verbose output mode.-class name | -c name
: restrict output to class name-thread name | -th name
: restrict output to thread name.-id id
: restrict output to object with id.-clid id
: restrict output to classloader id.-abs
: report time as absolute
Evidently these arguments have a query-specific interpretation, within the general definition given above.
Pre-defined Analysis Queries¶
The analysis tool is meant to be easily extensible, but a set of simple query classes are included with the tool. Many of these derive from the prior work on immutability so, for example, when displaying objects it is typical for information on immutability to be output.
AdviceRecords -from fromindex -to toindex -showindex -indent¶
Lists the advice records reconstructed from the store.
Note: Unless the range is constrained this generates even more
output that contained in the original (comopressed) store, and is best
redirected to a file with the o outfile command.
The -showIndex
option adds the index of the record as a prefix, and
the -indent
option indents on a method entry record.
BasicCounts¶
Displays the number of classes, classloaders, objects, arrays, the
number of missing constructors and also displays the result of the
ImmutableCount
query.
Classes¶
Displays the classes, showing the classloader and the number of instances of each class.
Additional arguments:
-sortbycount
: sort the output from largest number of instances to smallest.
ClassLoaders¶
Displays the classloader objects in the trace, i.e., those that inherit
from java.lang.ClassLoader
.
DataByClassLoader¶
For each classloader, display the data on objects of a given class loaded by that classloader.
Example output:
Objects organized by classloader
Classloader: (sun.misc.Launcher$AppClassLoader) -1:0
Objects organized by class
test.Simple, total objects 1
1:0, c 223.318617ms, la 253.762114ms, lm 238.633649ms, stable for 49.693585%
Classloader: (com.sun.max.vm.type.BootClassLoader) -2:0
Objects organized by class
java.io.PrintStream, total objects 1
-4:0, c 253.77319ms, la 253.777241ms, lm 253.77319ms, stable for 100%
etc.
The end of construction by c, the last access time by la, and the last modify time by lm. Note that in the current implementation objects whose construction was not observed are given ids that decrease from -1, and a creation time of the first time they are accessed.
Additional options:
-showthread
: show the thread that allocated the instance (defaultfalse
)-sort_lt
: Sort instances by lifetime (highest to lowest)-sort_mlt
: Sort instances by mutable lifetime (highest to lowest)-summary
: Suppress the individual instance output and replace with the percentage of objects immutable for more than a given percentile (default100
) (defaultfalse
).-pci percentile
: Set the percentile to use with -summary.-sort_summary mode
: The summary data can be sorted by classmode == class
, total number of instancesmode == total
or total number immutable for more than percentile,mode = imm_total
.
DataByClass¶
The same output as DataByClassLoader
except for all classes,
irrespective of classloader.
DataByObject¶
The data, in same format as DataByClass
on all the objects in the
objects map.
DataOnObject¶
The data on a specific object id.
DataByThreads¶
Similar output to DataByClass
except grouped by the allocating
thread.
Additional arguments:
-summary
: restrict output to the total number allocated and the total live number.-sort_lt
: as perDataByClass
.-sort_mlt
: as perDataByClass
.
GC¶
Displays the allocation epochs in the trace, that is, the periods
between garbage collections.
If -r
is set, also displays the objects that were collected at the end
of each epoch.
ImmutableClassBuckets¶
For each class: first computes the immutable lifetime as a percentage, then counts how many objects fall into buckets that are 1% in size. E.g.:
Class sun.reflect.NativeMethodAccessorImpl, Object count 4
4: 1 (25.00) 42: 1 (25.00) 75: 1 (25.00) 100: 1 (25.00)
This means that one object was immutable for 4%, one for 42%, one for 75% and 1 for 100% of respective lifetime. The number in brackets is the percent of the total for that bucket.
ImmutableCount¶
Displays the immutable object percentage and the immutable array percentage.
LiveObjects¶
Displays the total number and size of the live objects.
MissingConstructor¶
Displays the number of objects for which no trace was generated for
construction and, if -v
is set, the data on those objects.
MutableObjects¶
Display all the mutable objects of a given class and the list of modifications.
StaticFieldAccess¶
Displays the accesses to the static fields of classes.
ThreadLocal¶
Analyzes the data for thread locality, reporting on objects created by
one thread that are accessed by another thread.
Evidently, this analysis is dependent on the appropriate bytecodes being
traced.
The objectuse
configuration will report any use of an object, whereas
objectaccess
will report an actual access to the content of an object.
CallGraph¶
Assuming that the store file contains method entry and exit traces, this query constructs a call graph and displays it graphically using a standard Swing JTree.
ConvertLog¶
This tool can perform various conversion operations on the store file.
Usage:
[-f inpath] [-o outfile] [-readable | -unbatch | -batch | -merge] [-abstime]
The default value if inpath
is vmastore
.
If no output file is specified the output goes to the standard
output.
The options have the following effect:
-readable
: Generate a (more) readable form of the store file.-unbatch
: Convert the store file containing records batched by thread into a time ordered file-batch
: Reverse the process performed by-unbatch
. This is a debugging tool to check the-unbatch
command.-abstime
: By default store files denote time by the increment between successive records (in a batch). This option will convert the file to use absolute time for each record.-merge
: Merges all per-thread store files into a single output file.
Simple Tests¶
The com.oracle.max.vm.ext.vma.test
package contains some simple test
programs to exercise the system, of which we highlight a few here.
To simplify the exposition, assume that the current working directory
contains the Maxine projects and the following aliases have been
defined:
alias qa="java -classpath com.oracle.max.vma.tools/bin:com.oracle.max.vm.ext.vma/bin com.oracle.max.vma.tools.qa.QueryAnalysis"
alias maxvma="max vm -cp com.oracle.max.vm.ext.vma/bin"
Simple¶
This is an example of a class with a non-final field that is stable in the sense that it is written to once shortly after the constructor executes and is then immutable from that point on. To demonstrate this, execute:
$ maxvma '-XX:VMAMI=test.Simple.*' test.Simple
$ qa
%% e DataByClass -c test.Simple
Objects organized by class
test.Simple, total objects 1, cl: (sun.misc.Launcher$AppClassLoader) -1:0
1:0, c 223.318617ms, la 253.762114ms, lm 238.633649ms, stable for 49.693585%
GCTest¶
GCTest is a multi-threaded program where each thread iteratively builds
up a list of objects with a randomly generated lifetime, removing those
that have expired after each iteration, and then invoking
System.GC
. E.g.,
$ maxvma -XX:VMAMI='test.GCTest.*' test.GCTest
$ qa -v
processing trace file vmastore starting
processed 100000 traces in 1331 ms (1331)
processed 200000 traces in 1887 ms (556)
processed 300000 traces in 2399 ms (512)
processed 400000 traces in 2702 ms (303)
processed 500000 traces in 3024 ms (322)
processing trace file vmastore complete
%% e GC
Allocation epochs
Epoch 0, 0ms, 646.481ms
Epoch 1, 646.481ms, 772.329ms
Epoch 2, 772.329ms, 879.328ms
Epoch 3, 879.328ms, 985.426ms
Epoch 4, 985.426ms, 1117.057ms
Epoch 5, 1117.057ms, 1226.683ms
etc.
Since the store file is considerably larger for this example, we used
the -v
option to report processing speed.
ThreadLocal01¶
ThreadLocal01 is a multi-threaded program where several worker threads (default 2) build lists of objects that are private to the thread. Optionally the program can be configured so that they leak objects that are accessed by a leak observer thread. To run in private (thread local) mode, execute:
$ maxvma -XX:VMAMI='test.ThreadLocal.*' test.ThreadLocal01
running with 2 threads
Thread Generator-0 running
Thread Generator-1 running
Thread Generator-0 returning
Thread Generator-1 returning
global list size 22, LeakObserver accessCount 437
main thread terminating
$ qa
%% e ThreadLocal
Check objects allocated by thread Generator-1
Check objects allocated by thread Generator-0
Check objects allocated by thread main
object 5:0 is accessed by thread Generator-0
object 2:0 is accessed by thread Generator-1
object 2:0 is accessed by thread Generator-0
object 9:0 is accessed by thread Generator-1
object 8:0 is accessed by thread Generator-1
object 6:0 is accessed by thread Generator-0
The ThreadLocal query determines that objects allocated by the generator threads are not accessed by any other thread.
Now execute:
$ maxvma -XX:VMAMI='test.ThreadLocal.*' test.ThreadLocal01 -l
running with 2 threads
Thread LeakObserver running
Thread Generator-0 running
Thread Generator-1 running
Thread Generator-0 returning
Thread Generator-1 returning
main thread terminating
$ qa
%% e ThreadLocal
Check objects allocated by thread Generator-1
object 120:0 is accessed by thread LeakObserver
object 120:0 is accessed by thread Generator-0
object 161:0 is accessed by thread LeakObserver
object 283:0 is accessed by thread Generator-0
object 387:0 is accessed by thread LeakObserver
object 381:0 is accessed by thread LeakObserver
object 137:0 is accessed by thread Generator-0
object 147:0 is accessed by thread LeakObserver
object 30:0 is accessed by thread LeakObserver
object 30:0 is accessed by thread Generator-0
object 62:0 is accessed by thread LeakObserver
object 51:0 is accessed by thread LeakObserver
object 406:0 is accessed by thread LeakObserver
object 347:0 is accessed by thread LeakObserver
object 309:0 is accessed by thread Generator-0
object 208:0 is accessed by thread LeakObserver
object 208:0 is accessed by thread Generator-0
object 202:0 is accessed by thread LeakObserver
etc.
In this case the query detects that objects created by Generator-1
have leaked to both LeakObserver
and Generator-0
.
Note: since both generator threads are leaking objects to the same
global list, they also see each others leaks.
Note that a similar analysis is performed online by the ThreadLocalVMAdviceHandler.
Bugs and Limitations¶
The main limitation at present is that VMA is only available for the baseline (JIT) compiler, and that many bytecodes do not support both BEFORE and AFTER advice.