As convenient as the on-the-fly mode is, in many cases it is not sufficient. For example, running a commercial J2EE container in a custom instrumenting classloader is practically impossible. Certain (bad) coding practices also fail for code executing in a custom classloader. Finally, in large scale development there is a common need to collect and merge coverage data from multiple execution runs and multiple JVM processes.
This is where separate instrument/execute/report phases are a necessity. This section repeats the previous exercise using emma command line tool, which provides several subcommands for managing EMMA's offline code coverage analysis: instr, merge, and report (there is also a run equivalent of emmarun for scripting convenience).
If you skipped the previous exercise, you need to compile the sample source code at this time:
>cd ...samples >mkdir out >javac -d out -g src/*.java src/search/*.java
Now, you are going to instrument classes produced by javac (it's kind of a second compilation phase). EMMA can do "in place" instrumentation (overwrite mode), whereby the classes and jar files are overwritten with their instrumented versions. However, this is easy to abuse, so for now we are going to be careful and create a separate directory for coverage-instrumented output:
>mkdir outinstr >java emma instr -d outinstr -ip out EMMA: processing instrumentation path ... EMMA: instrumentation path processed in 116 ms EMMA: [3 class(es) instrumented, 0 resource(s) copied] EMMA: metadata merged into [...coverage.em] {in 31 ms}
Several instrumented classes have been added to
outinstr
directory and class
metadata has been dumped into a
coverage.em
file. Note that instr
accepts a regular classpath string (containing archives and class
directories) as input: this is very convenient for makefile integration
because existing makefiles tend to already have macros for various
classpaths in a project.
Unlike some other tools, EMMA's design is based around filtering for the right set of classes at instrumentation time. Doing so allows EMMA to scale to enterprise size projects and ensures the best performance throughout all three offline stages: instrumentation, execution, and reporting. To select a subset of classes to be processed, you could give instr several -ix options, each containing a comma-separated list of inclusion/exlusion patterns. See Section6.2, Coverage filters in the reference manual for full details.
Now the instrumented application can be run. In a real-world project you might be packaging the instrumented classes in an archive to be deployed in an application server, but in this tutorial we just load the classes from disk:
>java -cp outinstr;out Main EMMA: collecting runtime coverage data ... main(): running doSearch()... main(): done EMMA: runtime coverage data merged into [...coverage.ec] {in 32 ms}
When the JVM exits, EMMA runtime dumps the runtime
coverage profile into a coverage.ec
file
(the precise names and locations of all files created by EMMA are
configurable, the above is just EMMA's default behavior).
And finally, we combine the class metadata and runtime coverage profile to produce a plain text and an HTML reports:
>java emma report -r txt,html -in coverage.em -in coverage.ec EMMA: 2 file(s) read and merged in 43 ms EMMA: writing [txt] report to [...coverage.txt] ... EMMA: writing [html] report to [...coverage/index.html] ...
Note that there could be several instrumentation and execution stages and report will happily merge all of the results in memory before generating the reports. To merge all files on disk (for maintenance and disk storage reasons) you can use merge:
>java emma merge -in coverage.em -in coverage.ec -out coverage.es EMMA: processing input files ... EMMA: 2 file(s) read and merged in 42 ms EMMA: merged/compacted data written to [...coverage.es] {in 58 ms}
In EMMA's offline mode, you are in complete control of mixing and
matching metadata and coverage data from different application runs. You can
instruct all tools to merge all types of data in the same file or keep everything in
separate file repositories. EMMA tools default to
merge=true
output file mode for metadata and runtime
coverage data, but properties exist to alter this behavior. See Chapter3, EMMA Property Reference in the reference manual for further details.
Further reading. This has been a quick intro to EMMA's offline instrumentation tools for command line. For further details read the reference manual starting with Section3, <instr>/instr.