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
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
However, it should be considered experimental.
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
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
Running a VMA-enabled image¶
A VMA-enabled image can be run in the usual way with the
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
However, this can be controlled more precisely with the
Both options take values that are regular expressions in the format
-XX:VMAMI option specifies methods to include and
specifies methods to exclude.
-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
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 entry
entryexit: advises after method entry and before return, including return by thrown exception
monitor: 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.
VMAConfig options accepts a list of these configurations and
aggregates them into a single set of the appropriate bytecodes to be
The specific bytecode advice controls are
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
Note that while all the bytecodes in the standard set defined by the JVM
can be individually controlled, the
aggregates the advice for collections of similar bytecodes into a single
For example, one can advice just the
bytecodes, but the advice for both will be directed to the
The aggregating methods do not provide a way to distinguish which
bytecode generated the advice.
Certain handlers can optionally gather timing information, notably
VMATime option provides a standard way to specify how time is
If the option value is none, time is not recorded.
If the value starts with
wallns, then wall clock time is gathered
If the value starts with
wallms, then wall clock time is gathered
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
This variant has considerably less overhead that gathering wall clock
time, yet tracks wall clock time quite closely.
TimeTestVMAdviceHandler can be used to compare the two values over
By default all application threads are enabled for advice.
However a subset can be enabled by using the
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 is
pis a regular expression pattern specifying methods to include for instrumentation.
VMAMX=p: regular expression pattern specifying methods to exclude for instrumentation. Overrides
VMAXJDK: boolean valued option that excludes all JDK classes from instrumentation.
pis a regular expression pattern of bytecodes to include for instrumentation.
pis a regular expression pattern of bytecodes to exclude for instrumentation. Overrides
cis a comma spearated list of configuration names that instrument for specific analyses.
pis a regular expression pattern of threads to have advising enabled.
pis 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 is
VMASample=initialperiod,interval,period: run in sampling mode. Defaults to
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
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
Output goes to the shared store file named vm in the store directory.
VMLogStoreVMAdviceHandler uses a custom instance of the
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
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
representations when the records are flushed.
The maximum latency occurs when the store buffer is flushed to the
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
ThreadLocalVMAdviceHandler analyses object use for thread
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
CBCVMAdviceHandler can be used to estimate the size of the
persistent store that would be created by
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.
One of the issues for analysis tools, either online or offline, is
associating analysis-specific state with an object, for example a unique
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
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
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
Support for unique identifiers is provided through the
interface and support for marking bits through the
SimpleObjectState implements both of these
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
ObjectBitSet and one for use by the handler.
Access to the additional words is through the
SimpleObjectState to implement
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
Objects passed as arguments to the other methods are checked for a uuid
having been assigned and, if not, the abstract method
which must be implemented the handler, is called.
The adapter also handles unique id generation for
since these may be user defined.
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
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:
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
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,
VMAJavaRunScheme, to interpose on the VM startup to perform VMA
VMAdviceHandler defines an
initialise(MaxineVM.Phase phase) method
that normally should be overridden in a handler, and this method is
The only phases that are of interest are
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
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
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
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
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
STARTING phase, which precedes the
Typically all the method should do is register an instance of the
VMAJavaRunScheme.registerAdviceHandler, so that it can
be invoked in the
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 custom
VMLogStoreVMAdviceHandleris 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,
CBCVMAdviceHandlersorts the pan-thread advice counts by frequency.
max.vma.store.bufsize: The size of the
StringBuilderused 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 to
max.vma.store.textkey: Use a 3 character mnemonic key for stored records instead of a single digit code.
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.
NullVMAdviceHandler provides a measure of the basic overhead of a
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%
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
averages 2.9% with a range of 1.4% to 6.8%.
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.
replaced with types defined in the analysis tool, namely
MethodRecord, with the obvious
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 the
ObjectRecord. 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 the
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. The
missingConstructorsmap is keyed by the id and the value is the associated
allocationEpochs: a list of
AllocationEpochobjects 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.
[-f inpath] [-v] [-i queryfile] [-e query]
The default value of
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.
-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
The input prompt is
The following interactive commands are available:
e query: The tool prepends
Queryto queryclass and then attempts to load that class, which must be a subclass of
QueryBase, and then invokes its execute method. E.g., e Foo will attempt to invoke
com.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.
-showIndex option adds the index of the record as a prefix, and
-indent option indents on a method entry record.
Displays the number of classes, classloaders, objects, arrays, the
number of missing constructors and also displays the result of the
Displays the classes, showing the classloader and the number of instances of each class.
-sortbycount: sort the output from largest number of instances to smallest.
Displays the classloader objects in the trace, i.e., those that inherit
For each classloader, display the data on objects of a given class loaded by that classloader.
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.
-showthread: show the thread that allocated the instance (default
-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 (default
-pci percentile: Set the percentile to use with -summary.
-sort_summary mode: The summary data can be sorted by class
mode == class, total number of instances
mode == totalor total number immutable for more than percentile,
mode = imm_total.
The same output as
DataByClassLoader except for all classes,
irrespective of classloader.
The data, in same format as
DataByClass on all the objects in the
The data on a specific object id.
Similar output to
DataByClass except grouped by the allocating
-summary: restrict output to the total number allocated and the total live number.
-sort_lt: as per
-sort_mlt: as per
Displays the allocation epochs in the trace, that is, the periods
between garbage collections.
-r is set, also displays the objects that were collected at the end
of each epoch.
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.
Displays the immutable object percentage and the immutable array percentage.
Displays the total number and size of the live objects.
Displays the number of objects for which no trace was generated for
construction and, if
-v is set, the data on those objects.
Display all the mutable objects of a given class and the list of modifications.
Displays the accesses to the static fields of classes.
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
objectuse configuration will report any use of an object, whereas
objectaccess will report an actual access to the content of an object.
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.
This tool can perform various conversion operations on the store file.
[-f inpath] [-o outfile] [-readable | -unbatch | -batch | -merge] [-abstime]
The default value if
If no output file is specified the output goes to the standard
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
-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.
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
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"
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 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
$ 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
-v option to report processing speed.
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.
$ 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
have leaked to both
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.