1*7e63c127SSorin Basca<?xml version="1.0" encoding="UTF-8" ?> 2*7e63c127SSorin Basca<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> 3*7e63c127SSorin Basca<html xmlns="http://www.w3.org/1999/xhtml" lang="en"> 4*7e63c127SSorin Basca<head> 5*7e63c127SSorin Basca <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" /> 6*7e63c127SSorin Basca <link rel="stylesheet" href="resources/doc.css" charset="UTF-8" type="text/css" /> 7*7e63c127SSorin Basca <link rel="stylesheet" href="../coverage/jacoco-resources/prettify.css" charset="UTF-8" type="text/css" /> 8*7e63c127SSorin Basca <link rel="shortcut icon" href="resources/report.gif" type="image/gif" /> 9*7e63c127SSorin Basca <script type="text/javascript" src="../coverage/jacoco-resources/prettify.js"></script> 10*7e63c127SSorin Basca <title>JaCoCo - Control Flow Analysis</title> 11*7e63c127SSorin Basca</head> 12*7e63c127SSorin Basca<body onload="prettyPrint()"> 13*7e63c127SSorin Basca 14*7e63c127SSorin Basca<div class="breadcrumb"> 15*7e63c127SSorin Basca <a href="../index.html" class="el_report">JaCoCo</a> > 16*7e63c127SSorin Basca <a href="index.html" class="el_group">Documentation</a> > 17*7e63c127SSorin Basca <span class="el_source">Control Flow Analysis</span> 18*7e63c127SSorin Basca</div> 19*7e63c127SSorin Basca<div id="content"> 20*7e63c127SSorin Basca 21*7e63c127SSorin Basca<h1>Control Flow Analysis for Java Methods</h1> 22*7e63c127SSorin Basca 23*7e63c127SSorin Basca<p class="hint"> 24*7e63c127SSorin Basca Implementing a coverage tool that supports statement (C0) as well as branch 25*7e63c127SSorin Basca coverage coverage (C1) requires detailed analysis of the internal control flow 26*7e63c127SSorin Basca of Java methods. Due to the architecture of JaCoCo this analysis happens on 27*7e63c127SSorin Basca the bytecode of compiled class files. This document describes JaCoCo's 28*7e63c127SSorin Basca strategies for inserting probes into the control flow at runtime and analyzing 29*7e63c127SSorin Basca the actual code coverage. Marc R. Hoffmann, November 2011 30*7e63c127SSorin Basca</p> 31*7e63c127SSorin Basca 32*7e63c127SSorin Basca<h2>Control Flow Graphs for Java Bytecode</h2> 33*7e63c127SSorin Basca 34*7e63c127SSorin Basca<p> 35*7e63c127SSorin Basca As an starting point we take the following example method that contains a 36*7e63c127SSorin Basca single branching point: 37*7e63c127SSorin Basca</p> 38*7e63c127SSorin Basca 39*7e63c127SSorin Basca<pre class="source lang-java linenums"> 40*7e63c127SSorin Bascapublic static void example() { 41*7e63c127SSorin Basca a(); 42*7e63c127SSorin Basca if (cond()) { 43*7e63c127SSorin Basca b(); 44*7e63c127SSorin Basca } else { 45*7e63c127SSorin Basca c(); 46*7e63c127SSorin Basca } 47*7e63c127SSorin Basca d(); 48*7e63c127SSorin Basca} 49*7e63c127SSorin Basca</pre> 50*7e63c127SSorin Basca 51*7e63c127SSorin Basca<p> 52*7e63c127SSorin Basca A Java compiler will create the following bytecode from this example method. 53*7e63c127SSorin Basca Java bytecode is a linear sequence of instructions. Control flow is 54*7e63c127SSorin Basca implemented with <i>jump</i> instructions like the conditional 55*7e63c127SSorin Basca <code>IFEQ</code> or the unconditional <code>GOTO</code> opcode. The jump 56*7e63c127SSorin Basca targets are technically relative offsets to the target instruction. For better 57*7e63c127SSorin Basca readability we use symbolic labels (<code>L1</code>, <code>L2</code>) instead 58*7e63c127SSorin Basca (also the ASM API uses such symbolic labels): 59*7e63c127SSorin Basca</p> 60*7e63c127SSorin Basca 61*7e63c127SSorin Basca<pre class="source linenums"> 62*7e63c127SSorin Bascapublic static example()V 63*7e63c127SSorin Basca INVOKESTATIC a()V 64*7e63c127SSorin Basca INVOKESTATIC cond()Z 65*7e63c127SSorin Basca IFEQ L1 66*7e63c127SSorin Basca INVOKESTATIC b()V 67*7e63c127SSorin Basca GOTO L2 68*7e63c127SSorin Basca L1: INVOKESTATIC c()V 69*7e63c127SSorin Basca L2: INVOKESTATIC d()V 70*7e63c127SSorin Basca RETURN 71*7e63c127SSorin Basca</pre> 72*7e63c127SSorin Basca 73*7e63c127SSorin Basca<p> 74*7e63c127SSorin Basca The possible control flow in the bytecode above can be represented by a graph. 75*7e63c127SSorin Basca The nodes are byte code instruction, the edged of the graph represent the 76*7e63c127SSorin Basca possible control flow between the instructions. The control flow of the 77*7e63c127SSorin Basca example is shown in the left box of this diagram: 78*7e63c127SSorin Basca</p> 79*7e63c127SSorin Basca 80*7e63c127SSorin Basca<img src="resources/flow-example.png" alt="Bytecode Control Flow"/> 81*7e63c127SSorin Basca 82*7e63c127SSorin Basca 83*7e63c127SSorin Basca<h3>Flow Edges</h3> 84*7e63c127SSorin Basca 85*7e63c127SSorin Basca<p> 86*7e63c127SSorin Basca The control flow graph of a Java method defined by Java byte code may have 87*7e63c127SSorin Basca the following Edges. Each edge connects a source instruction with a target 88*7e63c127SSorin Basca instruction. In some cases the source instruction or the target instruction 89*7e63c127SSorin Basca does not exist (virtual edges for method entry and exit) or cannot be 90*7e63c127SSorin Basca exactly specified (exception handlers). 91*7e63c127SSorin Basca</p> 92*7e63c127SSorin Basca 93*7e63c127SSorin Basca<table class="coverage"> 94*7e63c127SSorin Basca <thead> 95*7e63c127SSorin Basca <tr> 96*7e63c127SSorin Basca <td>Type</td> 97*7e63c127SSorin Basca <td>Source</td> 98*7e63c127SSorin Basca <td>Target</td> 99*7e63c127SSorin Basca <td>Remarks</td> 100*7e63c127SSorin Basca </tr> 101*7e63c127SSorin Basca </thead> 102*7e63c127SSorin Basca <tbody> 103*7e63c127SSorin Basca <tr> 104*7e63c127SSorin Basca <td>ENTRY</td> 105*7e63c127SSorin Basca <td>-</td> 106*7e63c127SSorin Basca <td>First instruction in method</td> 107*7e63c127SSorin Basca <td></td> 108*7e63c127SSorin Basca </tr> 109*7e63c127SSorin Basca <tr> 110*7e63c127SSorin Basca <td>SEQUENCE</td> 111*7e63c127SSorin Basca <td>Instruction, except <code>GOTO</code>, <code>xRETURN</code>, 112*7e63c127SSorin Basca <code>THROW</code>, <code>TABLESWITCH</code> and <code>LOOKUPSWITCH</code></td> 113*7e63c127SSorin Basca <td>Subsequent instruction</td> 114*7e63c127SSorin Basca <td></td> 115*7e63c127SSorin Basca </tr> 116*7e63c127SSorin Basca <tr> 117*7e63c127SSorin Basca <td>JUMP</td> 118*7e63c127SSorin Basca <td><code>GOTO</code>, <code>IFx</code>, <code>TABLESWITCH</code> or 119*7e63c127SSorin Basca <code>LOOKUPSWITCH</code> instruction</td> 120*7e63c127SSorin Basca <td>Target instruction</td> 121*7e63c127SSorin Basca <td><code>TABLESWITCH</code> and <code>LOOKUPSWITCH</code> will define 122*7e63c127SSorin Basca multiple edges.</td> 123*7e63c127SSorin Basca </tr> 124*7e63c127SSorin Basca <tr> 125*7e63c127SSorin Basca <td>EXHANDLER</td> 126*7e63c127SSorin Basca <td>Any instruction in handler scope</td> 127*7e63c127SSorin Basca <td>Target instruction</td> 128*7e63c127SSorin Basca <td></td> 129*7e63c127SSorin Basca </tr> 130*7e63c127SSorin Basca <tr> 131*7e63c127SSorin Basca <td>EXIT</td> 132*7e63c127SSorin Basca <td><code>xRETURN</code> or <code>THROW</code> instruction</td> 133*7e63c127SSorin Basca <td>-</td> 134*7e63c127SSorin Basca <td></td> 135*7e63c127SSorin Basca </tr> 136*7e63c127SSorin Basca <tr> 137*7e63c127SSorin Basca <td>EXEXIT</td> 138*7e63c127SSorin Basca <td>Any instruction</td> 139*7e63c127SSorin Basca <td>-</td> 140*7e63c127SSorin Basca <td>Unhandled exception.</td> 141*7e63c127SSorin Basca </tr> 142*7e63c127SSorin Basca </tbody> 143*7e63c127SSorin Basca</table> 144*7e63c127SSorin Basca 145*7e63c127SSorin Basca<p> 146*7e63c127SSorin Basca The current JaCoCo implementation ignores edges caused by implicit exceptions 147*7e63c127SSorin Basca and the the method entry. This means we consider SEQUENCE, JUMP, EXIT. 148*7e63c127SSorin Basca</p> 149*7e63c127SSorin Basca 150*7e63c127SSorin Basca 151*7e63c127SSorin Basca<h2>Probe Insertion Strategy</h2> 152*7e63c127SSorin Basca 153*7e63c127SSorin Basca<p> 154*7e63c127SSorin Basca Probes are additional instructions that can be inserted between existing 155*7e63c127SSorin Basca instructions. They do not change the behavior of the method but record the 156*7e63c127SSorin Basca fact that they have been executed. One can think probes are placed on edges of 157*7e63c127SSorin Basca the control flow graph. Theoretically we could insert a probe at every edge of 158*7e63c127SSorin Basca the control flow graph. As a probe implementation itself requires multiple 159*7e63c127SSorin Basca bytecode instructions this would increase the size of the class files several 160*7e63c127SSorin Basca times and significantly slow down execution speed of the instrumented classes. 161*7e63c127SSorin Basca Fortunately this is not required, in fact we only need a few probes per method 162*7e63c127SSorin Basca depending on the control flow of the method. For example a method without any 163*7e63c127SSorin Basca branches requires a single probe only. The reason for this is that starting 164*7e63c127SSorin Basca from a certain probe we can back-trace the execution path and typically get 165*7e63c127SSorin Basca coverage information for multiple instructions. 166*7e63c127SSorin Basca</p> 167*7e63c127SSorin Basca 168*7e63c127SSorin Basca<p> 169*7e63c127SSorin Basca If a probe has been executed we know that the corresponding edge has been 170*7e63c127SSorin Basca visited. From this edge we can conclude to other preceding nodes and edges: 171*7e63c127SSorin Basca</p> 172*7e63c127SSorin Basca 173*7e63c127SSorin Basca<ul> 174*7e63c127SSorin Basca <li>If a edge has been visited, we know that the source node of the this edge 175*7e63c127SSorin Basca has been executed.</li> 176*7e63c127SSorin Basca <li>If a node has been executed and the node is the target of only one edge 177*7e63c127SSorin Basca we know that this edge has been visited.</li> 178*7e63c127SSorin Basca</ul> 179*7e63c127SSorin Basca 180*7e63c127SSorin Basca<p> 181*7e63c127SSorin Basca Recursively applying these rules allows to determine the execution status of 182*7e63c127SSorin Basca all instructions of a method – given that we have probes at the right 183*7e63c127SSorin Basca positions. Therefore JaCoCo inserts probes 184*7e63c127SSorin Basca</p> 185*7e63c127SSorin Basca 186*7e63c127SSorin Basca<ul> 187*7e63c127SSorin Basca <li>at every method exit (return or throws) and</li> 188*7e63c127SSorin Basca <li>at every edge where the target instruction is the target of more than one 189*7e63c127SSorin Basca edge.</li> 190*7e63c127SSorin Basca</ul> 191*7e63c127SSorin Basca 192*7e63c127SSorin Basca<p> 193*7e63c127SSorin Basca We recall that a probe is simply a small sequence of additional instructions 194*7e63c127SSorin Basca that needs to be inserted at a control flow edge. The following table 195*7e63c127SSorin Basca illustrates how this extra instructions are added in case of different edge 196*7e63c127SSorin Basca types. 197*7e63c127SSorin Basca</p> 198*7e63c127SSorin Basca 199*7e63c127SSorin Basca<table class="coverage"> 200*7e63c127SSorin Basca <thead> 201*7e63c127SSorin Basca <tr> 202*7e63c127SSorin Basca <td>Type</td> 203*7e63c127SSorin Basca <td>Before</td> 204*7e63c127SSorin Basca <td>After</td> 205*7e63c127SSorin Basca <td>Remarks</td> 206*7e63c127SSorin Basca </tr> 207*7e63c127SSorin Basca </thead> 208*7e63c127SSorin Basca <tbody> 209*7e63c127SSorin Basca <tr> 210*7e63c127SSorin Basca <td>SEQUENCE</td> 211*7e63c127SSorin Basca <td><img src="resources/flow-sequence.png" alt="Sequence"/></td> 212*7e63c127SSorin Basca <td><img src="resources/flow-sequence-probe.png" alt="Sequence with Probe"/></td> 213*7e63c127SSorin Basca <td> 214*7e63c127SSorin Basca In case of a simple sequence the probe is simply inserted between the 215*7e63c127SSorin Basca two instructions. 216*7e63c127SSorin Basca </td> 217*7e63c127SSorin Basca </tr> 218*7e63c127SSorin Basca <tr> 219*7e63c127SSorin Basca <td>JUMP (unconditional)</td> 220*7e63c127SSorin Basca <td><img src="resources/flow-goto.png" alt="Unconditional Jump"/></td> 221*7e63c127SSorin Basca <td><img src="resources/flow-goto-probe.png" alt="Unconditional Jump with Probe"/></td> 222*7e63c127SSorin Basca <td> 223*7e63c127SSorin Basca As an unconditional jump is executed in any case, we can also insert the 224*7e63c127SSorin Basca probe just before the GOTO instruction. 225*7e63c127SSorin Basca </td> 226*7e63c127SSorin Basca </tr> 227*7e63c127SSorin Basca <tr> 228*7e63c127SSorin Basca <td>JUMP (conditional)</td> 229*7e63c127SSorin Basca <td><img src="resources/flow-cond.png" alt="Conditional Jump"/></td> 230*7e63c127SSorin Basca <td><img src="resources/flow-cond-probe.png" alt="Conditional Jump with Probe"/></td> 231*7e63c127SSorin Basca <td> 232*7e63c127SSorin Basca Adding a probe to an conditional jump is little bit more tricky. We 233*7e63c127SSorin Basca invert the semantic of the opcode and add the probe right after the 234*7e63c127SSorin Basca conditional jump. With a subsequent <code>GOTO</code> instruction we 235*7e63c127SSorin Basca jump to the original target. Note that this approach will not introduce 236*7e63c127SSorin Basca a backward jump, which would cause trouble with the Java verifier if we 237*7e63c127SSorin Basca have an uninitialized object on the stack. 238*7e63c127SSorin Basca </td> 239*7e63c127SSorin Basca </tr> 240*7e63c127SSorin Basca <tr> 241*7e63c127SSorin Basca <td>EXIT</td> 242*7e63c127SSorin Basca <td><img src="resources/flow-exit.png" alt="Exit"/></td> 243*7e63c127SSorin Basca <td><img src="resources/flow-exit-probe.png" alt="Exit with Probe"/></td> 244*7e63c127SSorin Basca <td> 245*7e63c127SSorin Basca As is is the nature of RETURN and THROW statements to actually leave the 246*7e63c127SSorin Basca method we add the probe right before these statements. 247*7e63c127SSorin Basca </td> 248*7e63c127SSorin Basca </tr> 249*7e63c127SSorin Basca </tbody> 250*7e63c127SSorin Basca</table> 251*7e63c127SSorin Basca 252*7e63c127SSorin Basca<p> 253*7e63c127SSorin Basca Now let's see how this rules apply to the example snippet above. We see that 254*7e63c127SSorin Basca <code>INVOKE d()</code> instruction is the only node with more than one 255*7e63c127SSorin Basca incoming edge. So we need to place probes on those edges and another probe on 256*7e63c127SSorin Basca the only exit node. The result is shown the the right box of the diagram 257*7e63c127SSorin Basca above. 258*7e63c127SSorin Basca</p> 259*7e63c127SSorin Basca 260*7e63c127SSorin Basca<h2>Additional Probes Between Lines</h2> 261*7e63c127SSorin Basca 262*7e63c127SSorin Basca<p> 263*7e63c127SSorin Basca The probe insertion strategy described so far does not consider implicit 264*7e63c127SSorin Basca exceptions thrown for example from invoked methods. If the control flow 265*7e63c127SSorin Basca between two probes is interrupted by a exception not explicitly created with 266*7e63c127SSorin Basca a <code>throw</code> statement all instruction in between are considered as 267*7e63c127SSorin Basca not covered. This leads to unexpected results especially when the the block of 268*7e63c127SSorin Basca instructions spans multiple lines of source code. 269*7e63c127SSorin Basca</p> 270*7e63c127SSorin Basca 271*7e63c127SSorin Basca<p> 272*7e63c127SSorin Basca Therefore JaCoCo adds an additional probe between the instructions of two 273*7e63c127SSorin Basca lines whenever the subsequent line contains at least one method invocation. 274*7e63c127SSorin Basca This limits the effect of implicit exceptions from method invocations to 275*7e63c127SSorin Basca single lines of source. The approach only works for class files compiled with 276*7e63c127SSorin Basca debug information (line numbers) and does not consider implicit exceptions 277*7e63c127SSorin Basca from other instructions than method invocations (e.g. 278*7e63c127SSorin Basca <code>NullPointerException</code> or <code>ArrayIndexOutOfBoundsException</code>). 279*7e63c127SSorin Basca</p> 280*7e63c127SSorin Basca 281*7e63c127SSorin Basca<h2>Probe Implementation</h2> 282*7e63c127SSorin Basca 283*7e63c127SSorin Basca<p> 284*7e63c127SSorin Basca Code coverage analysis is a runtime metric that provides execution details 285*7e63c127SSorin Basca of the software under test. This requires detailed recording about the 286*7e63c127SSorin Basca instructions (instruction coverage) that have been executed. For branch 287*7e63c127SSorin Basca coverage also the outcome of decisions has to be recorded. In any case 288*7e63c127SSorin Basca execution data is collected by so called probes: 289*7e63c127SSorin Basca</p> 290*7e63c127SSorin Basca 291*7e63c127SSorin Basca<p class="hint"> 292*7e63c127SSorin Basca A <b>probe</b> is a sequence of bytecode instructions that can be inserted 293*7e63c127SSorin Basca into a Java method. When the probe is executed, this fact is recorded and can 294*7e63c127SSorin Basca be reported by the coverage runtime. The probe must not change the behavior 295*7e63c127SSorin Basca of the original code. 296*7e63c127SSorin Basca</p> 297*7e63c127SSorin Basca 298*7e63c127SSorin Basca<p> 299*7e63c127SSorin Basca The only purpose of the probe is to record that it has been executed at least 300*7e63c127SSorin Basca once. The probe does not record the number of times it has been called or 301*7e63c127SSorin Basca collect any timing information. The latter is out of scope for code coverage 302*7e63c127SSorin Basca analysis and more in the objective of a performance analysis tool. Typically 303*7e63c127SSorin Basca multiple probes needs to be inserted into each method, therefore probes needs 304*7e63c127SSorin Basca to be identified. Also the probe implementation and the storage mechanism it 305*7e63c127SSorin Basca depends on needs to be thread safe as multi-threaded execution is a common 306*7e63c127SSorin Basca scenario for java applications (albeit not for plain unit tests). Probes must 307*7e63c127SSorin Basca not have any side effects on the original code of the method. Also they should 308*7e63c127SSorin Basca add minimal overhead. 309*7e63c127SSorin Basca</p> 310*7e63c127SSorin Basca 311*7e63c127SSorin Basca<p> 312*7e63c127SSorin Basca So to summarize the requirements for execution probes: 313*7e63c127SSorin Basca</p> 314*7e63c127SSorin Basca 315*7e63c127SSorin Basca<ul> 316*7e63c127SSorin Basca <li>Record execution</li> 317*7e63c127SSorin Basca <li>Identification for different probes</li> 318*7e63c127SSorin Basca <li>Thread safe</li> 319*7e63c127SSorin Basca <li>No side effects on application code</li> 320*7e63c127SSorin Basca <li>Minimal runtime overhead</li> 321*7e63c127SSorin Basca</ul> 322*7e63c127SSorin Basca 323*7e63c127SSorin Basca<p> 324*7e63c127SSorin Basca JaCoCo implements probes with a <code>boolean[]</code> array instance per 325*7e63c127SSorin Basca class. Each probe corresponds to a entry in this array. Whenever the probe is 326*7e63c127SSorin Basca executed the entry is set to <code>true</code> with the following four 327*7e63c127SSorin Basca bytecode instructions: 328*7e63c127SSorin Basca</p> 329*7e63c127SSorin Basca 330*7e63c127SSorin Basca<pre class="source"> 331*7e63c127SSorin BascaALOAD probearray 332*7e63c127SSorin BascaxPUSH probeid 333*7e63c127SSorin BascaICONST_1 334*7e63c127SSorin BascaBASTORE 335*7e63c127SSorin Basca</pre> 336*7e63c127SSorin Basca 337*7e63c127SSorin Basca<p> 338*7e63c127SSorin Basca Note that this probe code is thread safe and does not modify the operand stack 339*7e63c127SSorin Basca or modify local variables. It does also not leave the 340*7e63c127SSorin Basca method through an external call. The only prerequisite is that the probe array 341*7e63c127SSorin Basca is available as a local variable. For this at the beginning of each method 342*7e63c127SSorin Basca additional instrumentation code needs to be added to obtain the array instance 343*7e63c127SSorin Basca associated with the belonging class. To avoid code duplication the 344*7e63c127SSorin Basca initialization is delegated to a static private method 345*7e63c127SSorin Basca <code>$jacocoinit()</code> which is added to every non-interface class. 346*7e63c127SSorin Basca</p> 347*7e63c127SSorin Basca 348*7e63c127SSorin Basca<p> 349*7e63c127SSorin Basca The size of the probe code above depends on the position of the probe array 350*7e63c127SSorin Basca variable and the value of the probe identifier as different opcodes can be 351*7e63c127SSorin Basca used. As calculated in the table below the overhead per probe ranges between 4 352*7e63c127SSorin Basca and 7 bytes of additional bytecode: 353*7e63c127SSorin Basca</p> 354*7e63c127SSorin Basca 355*7e63c127SSorin Basca<table class="coverage"> 356*7e63c127SSorin Basca <thead> 357*7e63c127SSorin Basca <tr> 358*7e63c127SSorin Basca <td>Possible Opcodes</td> 359*7e63c127SSorin Basca <td>Min. Size [bytes]</td> 360*7e63c127SSorin Basca <td>Max. Size [bytes]</td> 361*7e63c127SSorin Basca </tr> 362*7e63c127SSorin Basca </thead> 363*7e63c127SSorin Basca <tfoot> 364*7e63c127SSorin Basca <tr> 365*7e63c127SSorin Basca <td>Total:</td> 366*7e63c127SSorin Basca <td>4</td> 367*7e63c127SSorin Basca <td>7</td> 368*7e63c127SSorin Basca </tr> 369*7e63c127SSorin Basca </tfoot> 370*7e63c127SSorin Basca <tbody> 371*7e63c127SSorin Basca <tr> 372*7e63c127SSorin Basca <td><code>ALOAD_x</code>, <code>ALOAD</code> <sup>1</sup></td> 373*7e63c127SSorin Basca <td>1</td> 374*7e63c127SSorin Basca <td>2</td> 375*7e63c127SSorin Basca </tr> 376*7e63c127SSorin Basca <tr> 377*7e63c127SSorin Basca <td><code>ICONST_x</code>, <code>BIPUSH</code>, <code>SIPUSH</code>, <code>LDC</code>, <code>LDC_W</code> <sup>2</sup></td> 378*7e63c127SSorin Basca <td>1</td> 379*7e63c127SSorin Basca <td>3</td> 380*7e63c127SSorin Basca </tr> 381*7e63c127SSorin Basca <tr> 382*7e63c127SSorin Basca <td><code>ICONST_1</code></td> 383*7e63c127SSorin Basca <td>1</td> 384*7e63c127SSorin Basca <td>1</td> 385*7e63c127SSorin Basca </tr> 386*7e63c127SSorin Basca <tr> 387*7e63c127SSorin Basca <td><code>BASTORE</code></td> 388*7e63c127SSorin Basca <td>1</td> 389*7e63c127SSorin Basca <td>1</td> 390*7e63c127SSorin Basca </tr> 391*7e63c127SSorin Basca </tbody> 392*7e63c127SSorin Basca</table> 393*7e63c127SSorin Basca 394*7e63c127SSorin Basca<p> 395*7e63c127SSorin Basca <sup>1</sup> The probe array is the first variable after the arguments. 396*7e63c127SSorin Basca If the method arguments do not consume more that 3 slots the 1-byte opcode can 397*7e63c127SSorin Basca be used.<br/> 398*7e63c127SSorin Basca <sup>2</sup> 1-byte opcodes for ids 0 to 5, 2-byte opcode for ids up to 127, 399*7e63c127SSorin Basca 3-byte opcode for ids up to 32767. Ids values of 32768 or more require an 400*7e63c127SSorin Basca additional constant pool entry. For normal class files it is very unlikely to 401*7e63c127SSorin Basca require more than 32,000 probes. 402*7e63c127SSorin Basca</p> 403*7e63c127SSorin Basca 404*7e63c127SSorin Basca<h2>Performance</h2> 405*7e63c127SSorin Basca 406*7e63c127SSorin Basca<p> 407*7e63c127SSorin Basca The control flow analysis and probe insertion strategy described in this 408*7e63c127SSorin Basca document allows to efficiently record instruction and branch coverage. In 409*7e63c127SSorin Basca total classes instrumented with JaCoCo increase their size by about 30%. Due 410*7e63c127SSorin Basca to the fact that probe execution does not require any method calls, only local 411*7e63c127SSorin Basca instructions, the observed execution time overhead for instrumented 412*7e63c127SSorin Basca applications typically is less than 10%. 413*7e63c127SSorin Basca</p> 414*7e63c127SSorin Basca 415*7e63c127SSorin Basca<h2>References</h2> 416*7e63c127SSorin Basca 417*7e63c127SSorin Basca<ul> 418*7e63c127SSorin Basca <li><a href="http://asm.objectweb.org/">ASM byte code library</a> by Eric Bruneton at al.</li> 419*7e63c127SSorin Basca <li><a href="http://andrei.gmxhome.de/bytecode/index.html">Bytecode Outline Plug-In</a> by Andrei Loskutov</li> 420*7e63c127SSorin Basca <li><a href="http://en.wikipedia.org/wiki/Glossary_of_graph_theory">Wikipedia: Glossary of Graph Theory</a></li> 421*7e63c127SSorin Basca</ul> 422*7e63c127SSorin Basca 423*7e63c127SSorin Basca</div> 424*7e63c127SSorin Basca<div class="footer"> 425*7e63c127SSorin Basca <div class="right"><a href="${jacoco.home.url}">JaCoCo</a> ${qualified.bundle.version}</div> 426*7e63c127SSorin Basca <a href="license.html">Copyright</a> © ${copyright.years} Mountainminds GmbH & Co. KG and Contributors 427*7e63c127SSorin Basca</div> 428*7e63c127SSorin Basca 429*7e63c127SSorin Basca</body> 430*7e63c127SSorin Basca</html> 431