How to use Jacoco Java API to read Jacoco execution dump file

129 views
Skip to first unread message

Abhishek Khandelwal

unread,
Dec 2, 2019, 12:15:47 PM12/2/19
to JaCoCo and EclEmma Users
Hello team,


Note: I am using Jacoco version - 0.8.6-SNAPSHOT. 

There is a requirement where I need to read Jacoco execution dump file and get meaningful data out of it using Jacoco Java API.  

For that, I did try to follow below steps but not able to read exec file. It will be really helpful if you can provide any pointer to achieve this task.
  1. Run Jacoco as an agent and attached to the jvm.  I used below command for that-  [Working]
    • java -javaagent:C:/jacocoagent.jar=port=36320,includes=com.*,output=tcpserver -jar demoapp.jar
  2. Use Jacoco Java api to connect to this tcpserver and get the dump [Working]  - pls refer attached 'Jacoco_execution_dump.png' screenshot 
    • Here I am getting data from tcp server and dumping into jacoco.exec file. [Eventually, I just want to read the data from tcp server and directly convert that byte data into meaningful information rather than dumping into jacoco.exec file and then read that file]
  3. Now I am trying to use Jacoco Java api (CoverageBuilder) to read the jacoco.exec file [created in step-2] and convert this data to get class/method coverage. Code which I am using to read jacoco.exec file is put down below. While running that piece of code, I am getting below error - 

Exception in thread "main" java.lang.IncompatibleClassChangeError: class org.jacoco.core.internal.flow.ClassProbesVisitor has interface org.objectweb.asm.ClassVisitor as super class
at java.lang.ClassLoader.defineClass1(Native Method)
at java.lang.ClassLoader.defineClass(Unknown Source)
at java.security.SecureClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.defineClass(Unknown Source)
at java.net.URLClassLoader.access$100(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.net.URLClassLoader$1.run(Unknown Source)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at sun.misc.Launcher$AppClassLoader.loadClass(Unknown Source)
at java.lang.ClassLoader.loadClass(Unknown Source)
at org.helmetsrequired.jacocotogo.JacocoClient.readJacocoFile(JacocoClient.java:142)
at org.helmetsrequired.jacocotogo.JacocoClient.main(JacocoClient.java:38)



Code to read Jacoco.exec file -      private void readJacocoFile() throws Exception { File execFile = new File("jacoco.exec");                ExecFileLoader loader = new ExecFileLoader();                loader.load(execFile);
               final CoverageBuilder coverageBuilder = new CoverageBuilder();        final Analyzer analyzer = new Analyzer(loader.getExecutionDataStore(), coverageBuilder); File classesDirectory = new File("C:\\classes"); analyzer.analyzeAll(classesDirectory); IBundleCoverage coverage = coverageBuilder.getBundle("jacoco"); System.out.println(coverage.getName()); for (IPackageCoverage p : coverage.getPackages()) { System.out.println("in the firsr for loop: " + p.getName()); String packageName = p.getName(); for (IClassCoverage c : p.getClasses()) { System.out.println(coverage.getName() + " : " + packageName + " : " +  c); }

Jacoco_execution_dump.png

Abhishek Khandelwal

unread,
Dec 2, 2019, 12:32:44 PM12/2/19
to JaCoCo and EclEmma Users
Here is a complete code to read exec file including import statements too.


import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;

import org.jacoco.core.analysis.Analyzer;
import org.jacoco.core.analysis.CoverageBuilder;
import org.jacoco.core.analysis.IBundleCoverage;

import org.jacoco.core.analysis.IClassCoverage;
import org.jacoco.core.analysis.IPackageCoverage;
import org.jacoco.core.data.ExecutionDataReader;
import org.jacoco.core.data.ExecutionDataStore;
import org.jacoco.core.data.ExecutionDataWriter;
import org.jacoco.core.data.SessionInfoStore;
import org.jacoco.core.runtime.RemoteControlReader;
import org.jacoco.core.runtime.RemoteControlWriter;
import org.jacoco.core.tools.ExecFileLoader;

public class JacocoClient {

private final SessionInfoStore sessionInfos = new SessionInfoStore();
private final ExecutionDataStore executionData = new ExecutionDataStore();
  
public static void main(String[] args) {
// TODO Auto-generated method stub
try {
new JacocoClient().readJacocoFile();
} catch (Exception e) {
e.printStackTrace();

Evgeny Mandrikov

unread,
Dec 2, 2019, 3:20:22 PM12/2/19
to JaCoCo and EclEmma Users

 
On Monday, December 2, 2019 at 5:15:47 PM UTC, Abhishek Khandelwal wrote:
Exception in thread "main" java.lang.IncompatibleClassChangeError: class org.jacoco.core.internal.flow.ClassProbesVisitor has interface org.objectweb.asm.ClassVisitor as super class

According to the exception message looks like that you use wrong version of ASM library.


Note: I am using Jacoco version - 0.8.6-SNAPSHOT. 

Since JaCoCo 0.8.5 up to as of today's 0.8.6-SNAPSHOT ( https://www.jacoco.org/jacoco/trunk/doc/changes.html ) required ASM version is 7.2

Abhishek Khandelwal

unread,
Dec 2, 2019, 5:37:06 PM12/2/19
to JaCoCo and EclEmma Users
Thank you, Evgeny for reply. It worked perfectly after removing one of the asm lib. 

One que where need your expertise pls- 

My intention is to capture the code coverage at test level. With single user in single vm, my approach will work where after finishing my test case execution, I can just call my custom api to fetch the data from jacoco agent and retrieve the class/method level info and then flush the exec data. 

But in case of multi user or multi node environment (docker/kube) - how to uniquely identify and get the mapping between test case and code coverage? Is there anyway where we can set any request/session header at request api call and Jacoco agent can look for that header value and capture into its exec file?  Or any other suggestion.. 

Just to illustrate my requirement -  Lets say, I have Java based microService consists two apis ('hello'  and 'hello1'). Both apis hit several other service/dao methods under the hood. If 2 users simultaneously hitting both apis (via postman/soapui/browser) then how to capture the code coverage at each user api hit level?

please let me know if you need any other specific details from my side regards to it. But it will be really helpful if you can provide any pointer to handle such scenarios. 
jacoco_exec_reader.txt

Evgeny Mandrikov

unread,
Dec 3, 2019, 6:12:59 AM12/3/19
to JaCoCo and EclEmma Users


On Monday, December 2, 2019 at 11:37:06 PM UTC+1, Abhishek Khandelwal wrote:
If 2 users simultaneously hitting both apis (via postman/soapui/browser) then how to capture the code coverage at each user api hit level?

It is impossible to obtain separate execution data for simultaneous/parallel execution,
separate execution data can be obtained only for sequential executions.


Regards,
Evgeny

Abhishek Khandelwal

unread,
Dec 3, 2019, 9:53:23 AM12/3/19
to JaCoCo and EclEmma Users
Thanks Evgeny. Do you know any other instrumentation tool that can suffice my purpose? 


Regards
Abhishek 
Reply all
Reply to author
Forward
This conversation is locked
You cannot reply and perform actions on locked conversations.
0 new messages