| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
| Name | Name | Last commit date | ||
|---|---|---|---|---|
 |  | |||
 |  | |||
 |  | |||
 |  | |||
 |  | |||
 |  | |||
 |  | |||
 |  | |||
 |  | |||
 |  | |||
This repository contains the Java dynamic dedup coverage agent for Keploy Enterprise.
It collects per-testcase Java coverage during Keploy replay and sends that coverage back to Enterprise so duplicate testcases can be identified and removed.
The repository contains only the dedup-focused keploy-sdk module.
Supported runtimes in CI today are Java 8, 17, and 21.
Dynamic dedup works on applications compiled up to Java 26. See Supported Java versions for where that ceiling comes from and how to raise it.
Keploy Enterprise drives dynamic dedup per testcase.
Coverage is collected at per-testcase granularity, not process granularity.
Download the keploy-sdk jar and keep it outside your application dependencies. The jar is a Java agent and should be attached only when you run Keploy dynamic deduplication.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.6.1</version>
<executions>
<execution>
<id>copy-keploy-java-agent</id>
<phase>package</phase>
<goals>
<goal>copy</goal>
</goals>
<configuration>
<artifactItems>
<artifactItem>
<groupId>io.keploy</groupId>
<artifactId>keploy-sdk</artifactId>
<version>2.0.5</version>
<outputDirectory>${project.build.directory}</outputDirectory>
<destFileName>keploy-sdk.jar</destFileName>
</artifactItem>
</artifactItems>
</configuration>
</execution>
</executions>
</plugin>The SDK no longer has to be added to dependencies, and application code should not import io.keploy.* classes for dynamic deduplication.
The dedup agent reads coverage in-process via JaCoCo's runtime API (org.jacoco.agent.rt.RT.getAgent()), so attaching the JaCoCo Java agent is the only runtime requirement in the common cases below:
java \
-javaagent:/path/to/keploy-sdk.jar \
-javaagent:/path/to/jacocoagent.jar \
-jar your-app.jarIf the in-process API is unavailable (for example because the JaCoCo agent is loaded into an isolated classloader), the SDK transparently falls back to JaCoCo's TCP server mode. To use the fallback explicitly, start JaCoCo in tcpserver mode and set KEPLOY_JACOCO_HOST / KEPLOY_JACOCO_PORT:
java \
-javaagent:/path/to/keploy-sdk.jar \
-javaagent:/path/to/jacocoagent.jar=address=127.0.0.1,port=36320,output=tcpserver \
-jar your-app.jarRun replay with dynamic dedup enabled:
keploy test -c "java -javaagent:/path/to/keploy-sdk.jar -javaagent:/path/to/jacocoagent.jar -jar your-app.jar" \
--dedup \
--language javaWhen using the TCP fallback, also pass --pass-through-ports <jacoco-port> so Keploy does not try to mock the JaCoCo control connection.
After replay, run:
keploy dedupTo remove duplicates:
keploy dedup --rmJava dedup works in native, Docker, and restricted Docker environments as long as /tmp is shared and writable between Keploy Enterprise and the Java process. In Docker Compose flows, Enterprise can inject that shared /tmp mount when it rewrites the Compose file for replay.
Keploy Enterprise and the Java SDK communicate over these Unix sockets:
Without a shared /tmp, dedup will not work inside containers because Enterprise and the Java process will be writing to different socket paths.
Dynamic dedup can only handle bytecode that both of its jars can read, so the supported ceiling is the lower of two limits — not one:
| Component | Role | Reads up to |
|---|---|---|
| jacocoagent.jar (k8s-proxy init image) | analyzes coverage | Java 26 (JaCoCo 0.8.15) |
| keploy-sdk.jar (this repo) | instruments the app, via the ASM shaded in through org.jacoco:org.jacoco.core | Java 26 (jacoco.core 0.8.15) |
Both currently sit at Java 26, so that is the effective ceiling.
It is easy to assume the JaCoCo agent alone decides this. It does not. The dedup agent here does its own instrumentation through the ASM that jacoco.core brings in, and ASM refuses class files newer than the release it was built against. So the jacoco.core version in keploy-sdk/pom.xml is an independent limit, and for a long time it was the lower one: while it sat on 0.8.12 it capped dedup at Java 22 even though the agent could already read more.
Nothing crashes, which is what makes it worth documenting. The app is instrumented, the replay runs, and every test passes — coverage is simply never produced, so no duplicates are found. That is indistinguishable from "this app genuinely has no duplicates" unless something says otherwise, which is why k8s-proxy now detects the app's real class-file version from the classes this agent uploads and reports the reason instead of failing silently.
Take the Java number from JaCoCo's release notes — the officially supported version, not the "experimental support for Java N+1 class files" one. Each JaCoCo release ships an ASM that declares one version beyond what it accepts by default, so reading the highest declared Opcodes.V<n> over-states real support by one. k8s-proxy's image build checks the constant against the ASM actually inside the jar and fails the build if it over-promises.
A scheduled k8s-proxy pipeline also fails when a newer JaCoCo is published, so this ceiling does not quietly fall behind again.
For a working reference, see the Java dedup sample in keploy/samples-java:
That sample is used in CI to validate Java dynamic dedup for JDK 8, 17, and 21 across native, classpath, Docker, distroless, and restricted Docker runs. The CI matrix is narrower than the supported range: it pins the runtimes the sample is exercised on, not the ceiling — see Supported Java versions.
| Back | FazBrowse Home | New Git URL |