Home | History | Annotate | Download | only in doc
      1 <?xml version="1.0" encoding="UTF-8" ?>
      2 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
      3 <html xmlns="http://www.w3.org/1999/xhtml" lang="en">
      4 <head>
      5   <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
      6   <link rel="stylesheet" href=".resources/doc.css" charset="UTF-8" type="text/css" />
      7   <link rel="shortcut icon" href=".resources/report.gif" type="image/gif" />
      8   <title>JaCoCo - Class Ids</title>
      9 </head>
     10 <body>
     11 
     12 <div class="breadcrumb">
     13   <a href="../index.html" class="el_report">JaCoCo</a> &gt;
     14   <a href="index.html" class="el_group">Documentation</a> &gt;
     15   <span class="el_source">Class Ids</span>
     16 </div>
     17 <div id="content"> 
     18 
     19 <h1>Class Ids</h1>
     20 
     21 <p>
     22   As JaCoCo's class identifiers are sometimes causing confusion this chapter
     23   answers the concepts and common issues with class ids in FAQ style format.
     24 </p>
     25 
     26 <h3>What are class ids and how are they created?</h3>
     27 <p>
     28   Class ids are 64-bit integer values, for example
     29   <code>0x638e104737889183</code> in hex notation. Their calculation is
     30   considered an implementation detail of JaCoCo. Currently ids are created with
     31   a CRC64 checksum of the raw class file.
     32 </p>
     33 
     34 <h3>What are class ids used for?</h3>
     35 <p>
     36   Class ids are used to unambiguously identify Java classes. At runtime execution
     37   data is sampled for every loaded class and typically stored to
     38   <code>*.exec</code> files. At analysis time &mdash; for example for report
     39   generation &mdash; the class ids are used to relate analyzed classes with the
     40   execution data.
     41 </p>
     42 
     43 <h3>What are the advantages of JaCoCo class ids?</h3>
     44 <p>
     45   The concept of class ids allows distinguishing different versions of classes,
     46   for example when multiple versions of an application are deployed to an
     47   application server or different versions of libraries are included.
     48 </p>
     49 <p>
     50   Also class ids are the prerequisite for JaCoCo's minimal runtime-overhead and
     51   small <code>*.exec</code> files even for very large applications under test.
     52 </p>
     53 
     54 <h3>What is the disadvantage of JaCoCo class ids?</h3>
     55 <p>
     56   The fact that class ids identify a specific version of a class causes problems
     57   in setups where different classes are used at runtime and at analysis time.
     58 </p>
     59 
     60 <h3>What happens if different classes are used at runtime and at analysis time?</h3>
     61 <p>
     62   In this case execution data cannot be related to the analyzed classes. As a
     63   consequence such classes are reported with 0% coverage.
     64 </p>
     65 
     66 <h3>How can I detect that I have a problem with class ids?</h3>
     67 <p>
     68   The typical symptom of class id mismatch is classes not shown as covered
     69   although they have been executed during the test. This situation can be easily
     70   detected e.g. in the HTML report: Open the <i>Sessions</i> page with the link
     71   on the top-right corner. You see a list of all classes where execution data
     72   has been collected for. Find the class in questions and check whether the
     73   entry has a link to the corresponding coverage report page. If the entry is
     74   not linked this means there is a class id mismatch between the class used at
     75   runtime and the class provided to create the report.
     76 </p>
     77 
     78 <h3>What can cause different class ids?</h3>
     79 <p>
     80   Class ids are identical for the exact same class file only (byte-by-byte).
     81   There is a couple of reasons why you might get different class files. First
     82   compiling Java source files will result in different class files if you use
     83   a different tool chain:
     84 </p>
     85 <ul>
     86   <li>Different compiler vendor (e.g. Eclipse vs. Oracle JDK)</li>
     87   <li>Different compiler versions</li>
     88   <li>Different compiler settings (e.g. debug vs. non-debug) </li>
     89 </ul>
     90 <p>
     91   Also post-processing class files (obfuscation, AspectJ, etc.) will typically
     92   change the class files. JaCoCo will work well if you simply use the same class
     93   files for runtime as well as for analysis. So the tool chain to create these
     94   class files does not matter.
     95 </p>
     96 <p>
     97   Even if the class files on the file system are the same there is possible that
     98   classes seen by the JaCoCo runtime agent are different anyways. This typically
     99   happens when another Java agent is configured <i>before</i> the JaCoCo agent
    100   or special class loaders pre-process the class files. Typical candidates are:
    101 </p>
    102 <ul>
    103   <li>Mocking frameworks</li>
    104   <li>Application servers</li>
    105   <li>Persistence frameworks</li>
    106 </ul>
    107 
    108 <h3>What workarounds exist to deal with runtime-modified classes?</h3>
    109 <p>
    110   If classes get modified at runtime in your setup there are some workarounds to
    111   make JaCoCo work anyways:
    112 </p>
    113 <ul>
    114   <li>If you use another Java agent make sure the <a href="agent.html">JaCoCo
    115       agent</a> is specified at first in the command line. This way the JaCoCo
    116       agent should see the original class files.</li>
    117   <li>Specify the <code>classdumpdir</code> option of the
    118       <a href="agent.html">JaCoCo agent</a> and use the dumped classes at report
    119       generation. Note that only loaded classes will be dumped, i.e. classes not
    120       executed at all will not show-up in your report as not covered.</li>
    121   <li>Use <a href="offline.html">offline instrumentation</a> before you run your
    122       tests. This way classes get instrumented by JaCoCo before any runtime
    123       modification can take place. Note that in this case the report has to be
    124       generated with the <i>original</i> classes, not with instrumented ones.</li>
    125 </ul>
    126 
    127 <h3>Why can't JaCoCo simply use the class name to identify classes?</h3>
    128 <p>
    129   To understand why JaCoCo can't rely on class names we need to have a look at
    130   the way how JaCoCo measures code coverage.
    131 </p>
    132 <p>
    133   JaCoCo tracks execution with so called <i>probes</i>. Probes are additional
    134   byte code instructions inserted in the original class file which will note
    135   when they are executed and report this to the JaCoCo runtime. This process is
    136   called <i>instrumentation</i>. To keep the runtime overhead minimal, only a
    137   few probes are inserted at "strategic" places. These probe positions are
    138   determined by <a href="flow.html">analyzing the control flow</a> of all
    139   methods of a class. As a result every instrumented class produces a list of
    140   <code>n</code> boolean flags indicating whether the probe has been executed or
    141   not. A JaCoCo <code>*.exec</code> file simply stores a boolean array per
    142   class id.
    143 </p>
    144 <p>
    145   At analysis time, for example for report generation, the <code>*.exec</code>
    146   file is used to get information about probe execution status. But as probes
    147   are stored in a plain boolean array there is no information like corresponding
    148   methods or lines. To retrieve this information we need the original class
    149   files and perform the exact same control flow analysis than at instrumentation
    150   time. Because this is a deterministic process we get the same probe positions.
    151   With this information we can now interfere the execution status of every
    152   single instruction and branch of a method. Using the debug information
    153   embedded in the class files we can also calculate line coverage.
    154 </p>
    155 <p>
    156   If we would use just slightly different classes at analysis time than at
    157   runtime &mdash; e.g. different method ordering or additional branches &mdash;
    158   we would end-up with different probes. For example the probe at index
    159   <code>i</code> would be in method <code>a()</code> and not in method
    160   <b>b()</b>. Obviously this will create random coverage results.
    161 </p>
    162 
    163 <h3>Why do I get an error when I try to analyze multiple versions of the same
    164     class with a group?</h3>
    165 <p>
    166   JaCoCo always analyzes a set of class as a group. The group is used to
    167   aggregate data for source files and packages (both can contain multiple
    168   classes). Within the reporting API classes are identified by their fully
    169   qualified name (e.g. to create stable file names in the HTML reports).
    170   Therefore it is not possible to include two different classes with the same
    171   name within a group. Anyhow it is possible to analyze different versions of
    172   class files in separate groups, for example the <a href="ant.html#report">Ant
    173   report task</a> can be configured with multiple groups.
    174 </p>
    175 
    176 </div>
    177 <div class="footer">
    178   <span class="right"><a href="@jacoco.home.url@">JaCoCo</a> @qualified.bundle.version@</span>
    179   <a href="license.html">Copyright</a> &copy; @copyright.years@ Mountainminds GmbH &amp; Co. KG and Contributors
    180 </div>
    181 
    182 </body>
    183 </html>
    184