Рассмотрим следующий пример.
Версия 1 состоит из следующих исходных файлов:
src/Example.java
class Example {
public static void main(String[] args) {
C.print(A.getPrefix() + B.getSuffix());
}
}
src/A.java
class A {
static String getPrefix() {
return "Hello, ";
}
}
src/B.java
class B {
static String getSuffix() {
return "World";
}
}
src/C.java
class C {
static void print(String msg) {
if ("Hello, World".equals(msg)) {
System.out.println(msg + "!");
} else {
System.out.println(msg);
}
}
}
Давайте скомпилируем и выполним версию 1:
# javac src/A.java src/B.java src/C.java src/Example.java -d v1
# java \
-javaagent:jacoco-0.8.4/lib/jacocoagent.jar=destfile=1.exec,sessionid=v1 \
-cp v1 \
Example
Hello, World!
Версия 2:
src/Example.java
изменено
class Example {
public static void main(String[] args) {
C.print("Hello");
}
}
src/A.java
изменено
class A {
static String getPrefix() {
return "";
}
}
src/B.java
и src/C.java
не изменено
Давайте скомпилируем и выполним версию 2:
# javac src/A.java src/B.java src/C.java src/Example.java -d v2
# java \
-javaagent:jacoco-0.8.4/lib/jacocoagent.jar=destfile=2.exec,sessionid=v2 \
-cp v2 \
Example
Hello
Обратите внимание, что Example.class
и A.class
различны, тогда как B.class
и C.class
одинаковы в обеих версиях:
# diff --report-identical-files v1/Example.class v2/Example.class
Binary files v1/Example.class and v2/Example.class differ
# diff --report-identical-files v1/A.class v2/A.class
Binary files v1/A.class and v2/A.class differ
# diff --report-identical-files v1/B.class v2/B.class
Files v1/B.class and v2/B.class are identical
# diff --report-identical-files v1/C.class v2/C.class
Files v1/C.class and v2/C.class are identical
И поэтому идентификаторы, вычисленные для этих классовфайлы:
# java -jar jacoco-0.8.4/lib/jacococli.jar classinfo v1
INST BRAN LINE METH CXTY ELEMENT
8 0 3 2 2 class 0xa170badd641f5a31 Example
5 0 2 2 2 class 0x45b9146c94e31f23 B
5 0 2 2 2 class 0xb8f01b5012761c26 A
16 2 5 2 3 class 0xaf857eca353b9073 C
# java -jar jacoco-0.8.4/lib/jacococli.jar classinfo v2
INST BRAN LINE METH CXTY ELEMENT
6 0 3 2 2 class 0x5915f0accdd77c81 Example
5 0 2 2 2 class 0x45b9146c94e31f23 B
5 0 2 2 2 class 0xa529ea9ab9745b77 A
16 2 5 2 3 class 0xaf857eca353b9073 C
И так, идентификаторы, записанные в данных выполнения:
# java -jar jacoco-0.8.4/lib/jacococli.jar execinfo 1.exec
[INFO] Loading exec file 1.exec.
CLASS ID HITS/PROBES CLASS NAME
Session "v1": Fri Jul 05 20:39:50 CEST 2019 - Fri Jul 05 20:39:50 CEST 2019
b8f01b5012761c26 1 of 2 A
a170badd641f5a31 1 of 2 Example
45b9146c94e31f23 1 of 2 B
af857eca353b9073 3 of 5 C
# java -jar jacoco-0.8.4/lib/jacococli.jar execinfo 2.exec
[INFO] Loading exec file 2.exec.
CLASS ID HITS/PROBES CLASS NAME
Session "v2": Fri Jul 05 20:39:50 CEST 2019 - Fri Jul 05 20:39:50 CEST 2019
af857eca353b9073 2 of 5 C
5915f0accdd77c81 1 of 2 Example
Давайте объединим, что объединяет данные выполнения для классов с одинаковым именем и идентификатором:
# java -jar jacoco-0.8.4/lib/jacococli.jar merge 1.exec 2.exec --destfile merged.exec
[INFO] Loading execution data file /private/tmp/j/1.exec.
[INFO] Loading execution data file /private/tmp/j/2.exec.
[INFO] Writing execution data to /private/tmp/j/merged.exec.
# java -jar jacoco-0.8.4/lib/jacococli.jar execinfo merged.exec
[INFO] Loading exec file merged.exec.
CLASS ID HITS/PROBES CLASS NAME
Session "v1": Fri Jul 05 20:39:50 CEST 2019 - Fri Jul 05 20:39:50 CEST 2019
Session "v2": Fri Jul 05 20:39:50 CEST 2019 - Fri Jul 05 20:39:50 CEST 2019
b8f01b5012761c26 1 of 2 A
a170badd641f5a31 1 of 2 Example
45b9146c94e31f23 1 of 2 B
af857eca353b9073 4 of 5 C
5915f0accdd77c81 1 of 2 Example
Давайте сгенерируем отчет, используя объединенные данные выполнения и файлы классов версии 2:
# java \
-jar jacoco-0.8.4/lib/jacococli.jar \
report merged.exec \
--classfiles v2 \
--sourcefiles src \
--html report
[INFO] Loading execution data file /private/tmp/j/merged.exec.
[WARN] Some classes do not match with execution data.
[WARN] For report generation the same class files must be used as at runtime.
[WARN] Execution data for class A does not match.
[INFO] Analyzing 4 classes.
Для src/Example.java
отчет покажет данные о выполнении версии 2, потому что идентификатор для v2/Example.class
равен 5915f0accdd77c81
:
Для src/A.java
отчет ничего не показывает, потому что в merged.exec
нет данных, которые соответствуют идентификатору v2/A.class
, то есть a529ea9ab9745b77
:
С сообщением, похожим на предупреждение при генерации отчета
Для src/B.java
отчет покажет данные о выполнении версии 1, поскольку в merged.exec
есть данные из 1.exec
, которые соответствуют идентификатору v2/B.class
- 45b9146c94e31f23
:
Для src/C.java
отчет покажет объединенные данные о выполнении обеих версий, потому что в merged.exec
есть данные как из 1.exec
, так и 2.exec
, которые соответствуют идентификатору v2/C.class
- af857eca353b9073
:
Приведенный выше отчет является правильным в том смысле, что он абсолютно правильно представляет слияние двух исполнений в отношении отдельного классафайлы, которые были предоставлены для генерации отчета:
v2/Example.class
было выполнено v2/A.class
не было выполнено B.class
быловыполненные в версии 1 - были выполнены обе ветви в
C.class
- одна в версии 1, другая в версии 2
Без использования идентификаторов классов отчет будет абсолютно некорректным без возможностиобнаружить это
v2/A.class
будет считаться выполненным, тогда как этого никогда не было - третья строка в
A.java
будет отображаться как выполненная, тогда как этого никогда не происходило
Однако в отношении всех вместе взятых классов отчет не представляет окончательную версию, потому что в окончательной версии
B.class
никогда не будет выполняться - только одна ветвь в
C.class
будет исполнено