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 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. 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 is ``true``. - ``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. Overrides ``VMAMI``. - ``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. Overrides ``VMABI``. - ``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 is ``wallns``. - ``VMASample=initialperiod,interval,period``: run in sampling mode. Defaults to ``50,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 custom ``VMLog`` used by ``VMLogStoreVMAdviceHandler`` 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 the ``StringBuilder`` 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 to ``max.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 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 ``ClassRecord``. - ``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 ``missingConstructors`` map is keyed by the id and the value is the associated ``ObjectRecord``. - ``allocationEpochs``: a list of ``AllocationEpoch`` 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 prepends ``com.oracle.max.vma.tools.qa.queries`` and appends ``Query`` to 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. 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 (default ``false``) - ``-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 ``100``) (default ``false``). - ``-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 == 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 per ``DataByClass``. - ``-sort_mlt``: as per ``DataByClass``. 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.