2. <emmajava>/emmarun

<emmajava>/emmarun — instrumented application runner (on-the-fly instrumentation mode).

2.1. Description

<emmajava>/emmarun pairs an advanced custom classloader with a combination of core internal components of <instr>/instr and <report>/report to form a unique convenience tool in EMMA kit: an application runner that instruments classes on the fly and generates coverage reports without any need for a separate build or any intermediate work files alltogether.

<emmajava>/emmarun convenience is especially apparent in command line mode, because its option names intentionally mimick the familiar java options: a Java application launch command line could be made coverage-enabled by inserting a single new word (emmarun) into the command line. Similarly, the ANT version of this tool is an extension of ANT's standard <java> task. <emmajava>/emmarun can execute as little as a single Java class or as much as a complex Swing application made up of hundreds of classes, all with equally small instrumentation overhead.

Thinking of <emmajava>/emmarun as a combination of EMMA class instrumentor and report generator is a good way to remember its ANT attributes and command line options: in the reference sections that follow most of them are documented as identical to their namesakes in <instr>/instr and <report>/report.

What gets instrumented. The default <emmajava>/emmarun behavior is to instrument only the classes that are loaded by the JVM for the running application. The resulting report will not even mention classes that were never loaded and which potentially decrease your coverage percentages. If your objective is to get a complete coverage report (as you would from an offline combination of <instr>/instr and <report>/report) you should use the option for a full classpath scan, possibly in combination with some coverage filters.

Compatibility. At runtime, <emmajava>/emmarun's instrumenting classloader installs itself as the application classloader, bypassing the standard system classloader. It uses a smart class delegation strategy, whereby it automatically detects JRE core and extension classes without having to filter by class names (the frequently used, but inadequate, delegation strategy). Coupled with full support for Class-Path manifest entries and -jar option, the resulting EMMA runtime will correctly run most standalone Java programs. However, certain cases are exceptions:

  • Java code referencing java.lang.ClassLoader.getSystemClassLoader() (either directly or via ClassLoader.findSystemClass() and related methods) instead of using the current or thread context loaders will bypass <emmajava>/emmarun classloader, causing subsequent classes to be loaded at the wrong node of the classloader hierarchy. Such coding patterns should really be considered bugs and are not supported. Such code could be patched up on the fly during instrumentation, but a reliable solution is expensive in terms of processing. Switching to offline instrumentation is an easy workaround.
  • Java applications designed around their own custom classloaders and classpaths most likely will not work with <emmajava>/emmarun (at best, they will run fine but coverage instrumention will not occur). Application containers (Apache tomcat, BEA Weblogic, IBM Websphere, etc) are the common case here. Again, switching to offline instrumentation is an easy alternative.

<emmajava> is always forked. ANT's in-process classloading model is not sufficiently JRE-compatible. ANT's class delegation in the standard <java> task in fork='false' (in-process) mode is based on name matching (with a hardcoded set of name filters) and inevitably fails for applications that depend on non-standard JRE extensions. To support EMMA deployment as a JRE extension <emmajava> always forces fork='true' to ensure correct execution (unless its enabled attribute makes it a pass-through).

Internal EMMA properties that affect classloading and class instrumentation. Several EMMA property settings affect instrumentation and classloading behavior done by <emmajava>/emmarun:

Changing the default classloading behavior should be done by experienced Java users only. Most of instrumentation-related properties should normally be left with their default values. instr.do_suid.compensation can be set to false to gain extra instrumentation processing speed when runtime execution does not involve class de-serialization from existing files or serialization across JVMs.