blob: c74fb0bacf29148e915c15eb5fcdb01a8fb27968 [file] [log] [blame]
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +00001<?xml version="1.0" encoding="ISO-8859-1" ?>
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=ISO-8859-1" />
6 <link rel="stylesheet" href="book.css" charset="ISO-8859-1" type="text/css" />
7 <title>JaCoCo - Implementation Design</title>
8</head>
9<body>
10
11<h1>JaCoCo - Implementation Design</h1>
12
13<p>
14 This is a unordered list of implementation design decisions. Each topic tries
15 to follow this structure:
16</p>
17
18<ul>
19 <li>Problem statement</li>
20 <li>Proposed Solution</li>
21 <li>Alternatives and Discussion</li>
22</ul>
23
24
25<h2>Coverage Analysis Mechanism</h2>
26
27<p class="Note">
28 Coverage information has to be collected at runtime. For this purpose JaCoCo
29 creates instrumented versions of the original class definitions. The
30 instrumentation process happens on-the-fly during class loading using so
31 called Java agents.
32</p>
33
34<p>
35 There are several different approaches to collect coverage information. For
36 each approach different implementation techniques are known. The following
37 diagram gives an overview with the techniques used by JaCoCo highlighted:
38</p>
39
40<ul>
41 <li>Runtime Profiling
42 <ul>
43 <li>Java Virtual Machine Profiler Interface (JVMPI), until Java 1.4</li>
44 <li>Java Virtual Machine Tool Interface (JVMTI), since Java 1.5</li>
45 </ul>
46 </li>
Marc R. Hoffmanne52a0ef2009-06-16 20:28:45 +000047 <li><span class="high">Instrumentation*</span>
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +000048 <ul>
49 <li>Java Source Instrumentation</li>
Marc R. Hoffmanne52a0ef2009-06-16 20:28:45 +000050 <li><span class="high">Byte Code Instrumentation'</span>
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +000051 <ul>
52 <li>Offline
53 <ul>
54 <li>Replace Original Classes In-Place</li>
55 <li>Inject Instrumented Classes into the Class Path</li>
56 </ul>
57 </li>
Marc R. Hoffmanne52a0ef2009-06-16 20:28:45 +000058 <li><span class="high">On-The-Fly*</span>
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +000059 <ul>
60 <li>Special Classloader Implementions or Framework Specific Hooks</li>
Marc R. Hoffmanne52a0ef2009-06-16 20:28:45 +000061 <li><span class="high">Java Agent*</span></li>
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +000062 </ul>
63 </li>
64 </ul>
65 </li>
66 </ul>
67 </li>
68</ul>
69
70<p>
71 Byte code instrumentation is very fast, can be implemented in pure Java and
72 works with every Java VM. On-the-fly instrumentation with the Java agent
73 hook can be added to the JVM without any modification of the target
74 application.
75</p>
76
77<p>
78 The Java agent hook requires at least 1.5 JVMs. For reporting class files
79 compiled with debug information (line numbers) allow a good mapping back to
80 source level. Although some Java language constructs are compiled in a way
81 that the the coverage highlighting leads to unexpected results, especially
82 in case of implicitly generated code like default constructors or control
83 structures for finally statements.
84</p>
85
Marc R. Hoffmann5267b6c2009-07-05 16:34:27 +000086
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +000087<h2>Instrumentation Approach</h2>
88
89<p class="Note">
90 Basic Block
91</p>
92
93<p>
Marc R. Hoffmann5267b6c2009-07-05 16:34:27 +000094 source language independent
95 more detailed than pure line coverage in case of multi condition expressions
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +000096 Problem: Exceptions
97</p>
98
Marc R. Hoffmann5267b6c2009-07-05 16:34:27 +000099<h2>Coverage Agent Isolation</h2>
100
101<p class="Note">
102 The Java agent is loaded by the application class loader. Therefore the
103 classes of the agent live in the same name space than the application classes
104 which can result in clashes especially with the third party library ASM. The
105 JoCoCo build therefore moves all agent classes into a unique package.
106</p>
107
108<p>
109 The JaCoCo build renames all classes contained in the
110 <code>jacocoagent.jar</code> into classes with a
Marc R. Hoffmann0948cb92009-07-06 09:15:28 +0000111 <code>org.jacoco.&lt;randomid&gt;</code> prefix, including the required ASM
112 library classes. The identifier is created from a random number. As the agent
113 does not provide any API, no one should be affected by this renaming. This
114 trick also allows that JaCoCo tests can be verified with JaCoCo.
Marc R. Hoffmann5267b6c2009-07-05 16:34:27 +0000115</p>
116
117
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +0000118<h2>Minimal Java Version</h2>
119
120<p class="Note">
Marc R. Hoffmanne52a0ef2009-06-16 20:28:45 +0000121 JaCoCo requires Java 1.5.
122</p>
123
124<p>
125 The Java agent mechanism used for on-the-fly instrumentation became available
126 with in Java 1.5 VMs. Coding and testing with Java 1.5 language level is more
127 efficient, less error-prone &ndash; and more fun. JaCoCo will still allow to
Marc R. Hoffmann5267b6c2009-07-05 16:34:27 +0000128 run against Java code compiled for older versions.
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +0000129</p>
130
131
132<h2>Byte Code Manipulation</h2>
133
134<p class="Note">
Marc R. Hoffmanne52a0ef2009-06-16 20:28:45 +0000135 Instrumentation requires mechanisms to modify and generate Java byte code.
136 JaCoCo uses the ASM library for this purpose.
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +0000137</p>
138
Marc R. Hoffmanne52a0ef2009-06-16 20:28:45 +0000139<p>
140 Implementing the Java byte code specification would be a extensive and
141 error-prone task. Therefore an existing library should be used. The
142 <a href="http://asm.objectweb.org/">ASM</a> library is lightweight, easy to
143 use and very efficient in terms of memory and CPU usage. It is actively
144 maintained and includes as huge regression test suite. Its simplified BSD
145 license is approved by the Eclipse Foundation for usage with EPL products.
146</p>
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +0000147
148<h2>Java Class Identity</h2>
149
150<p class="Note">
151 Each class loaded at runtime needs a unique identity to associate coverage data with.
152 JaCoCo creates such identities by a CRC64 hash code of the raw class definition.
153</p>
154
155<p>
156 In multi-classloader environments the plain name of a class does not
157 unambiguously identify a class. For example OSGi allows to use different
158 versions of the same class to be loaded within the same VM. In complex
159 deployment scenarios the actual version of the test target might be different
160 from current development version. A code coverage report should guarantee that
Marc R. Hoffmann5267b6c2009-07-05 16:34:27 +0000161 the presented figures are extracted from a valid test target. A hash code of
162 the class definitions allows a differentiate between classes and versions of a
163 class. The CRC64 hash computation is simple and fast resulting in a small 64
164 bit identifier.
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +0000165</p>
166
167<p>
168 The same class definition might be loaded by class loaders which will result
169 in different classes for the Java runtime system. For coverage analysis this
170 distinction should be irrelevant. Class definitions might be altered by other
171 instrumentation based technologies (e.g. AspectJ). In this case the hash code
172 will change and identity gets lost. On the other hand code coverage analysis
173 based on classes that have been somehow altered will produce unexpected
174 results. The CRC64 has code might produce so called <i>collisions</i>, i.e.
175 creating the same hash code for two different classes. Although CRC64 is not
176 cryptographically strong and collision examples can be easily computed, for
177 regular class files the collision probability is very low.
178</p>
179
180<h2>Coverage Runtime Dependency</h2>
181
182<p class="Note">
Marc R. Hoffmanne52a0ef2009-06-16 20:28:45 +0000183 Instrumented code typically gets a dependency to a coverage runtime which is
184 responsible for collecting and storing execution data. JaCoCo uses JRE types
185 and interfaces only in generated instrumentation code.
186</p>
187
188<p>
189 Making a runtime library available to all instrumented classes can be a
190 painful or impossible task in frameworks that use there own class loading
Marc R. Hoffmann5267b6c2009-07-05 16:34:27 +0000191 mechanisms. Therefore JaCoCo decouples the instrumented classes and the
Marc R. Hoffmanne52a0ef2009-06-16 20:28:45 +0000192 coverage runtime through official JRE API types.
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +0000193</p>
194
Marc R. Hoffmann5267b6c2009-07-05 16:34:27 +0000195<h2>Memory Usage</h2>
196
197<p class="Note">
198
199</p>
200
201<p>
202 Streaming, Deep first
203</p>
204
205<h2>Java Element Identifiers</h2>
206
207<p class="Note">
208 The Java language and the Java VM use different String representation formats
209 for Java elements. For example while a type reference in Java reads like
210 <code>java.lang.Object</code>, the VM references the same type as
211 <code>Ljava/lang/Object;</code>. The JaCoCo API is based on VM identifiers only.
212</p>
213
214<p>
215 Using VM identifiers directly does not cause any transformation overhead at
216 runtime. There are several programming languages based on the Java VM that
217 might use different notations. Specific transformations should therefore only
218 happen at the user interface level, for example while report generation.
219</p>
220
221<h2>Modularization of the JaCoCo implementation</h2>
222
223<p class="Note">
224 JaCoCo is implemented in several modules providing different functionality.
225 These modules are provided as OSGi bundles with proper manifest files. But
226 there is no dependencies on OSGi itself.
227</p>
228
229<p>
230 Using OSGi bundles allows well defines dependencies at development time and
231 at runtime in OSGi containers. As there are no dependencies on OSGi, the
232 bundles can also be used as regular JAR files.
233</p>
234
Marc R. Hoffmanna2af15d2009-06-07 21:15:05 +0000235
236<hr/>
237<div style="float:right">@VERSION@</div>
238<div>Copyright &copy; 2009 Mountainminds GmbH &amp; Co. KG, Marc R. Hoffmann</div>
239
240</body>
241</html>