xref: /aosp_15_r20/external/jacoco/org.jacoco.doc/docroot/doc/flow.html (revision 7e63c1270baf9bfa84f5b6aecf17bd0c1a75af94)
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> &gt;
16*7e63c127SSorin Basca  <a href="index.html" class="el_group">Documentation</a> &gt;
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 &ndash; 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> &copy; ${copyright.years} Mountainminds GmbH &amp; Co. KG and Contributors
427*7e63c127SSorin Basca</div>
428*7e63c127SSorin Basca
429*7e63c127SSorin Basca</body>
430*7e63c127SSorin Basca</html>
431