JaCoCo provides two ways of performing instrumentation:
The difference is that in first case instrumentation happens in memory during execution and so no class or jar files will be changed on disk - quoting the second link:
One of the main benefits of JaCoCo is the Java agent, which instruments classes on-the-fly. This simplifies code coverage analysis a lot as no pre-instrumentation and classpath tweaking is required.
So one of the simplifications that Java agent brings - is exactly that you don't need to worry about packaging or multiple builds. This is IMO one of the advantages of JaCoCo over other coverage tools for Java such as Cobertura and Clover.
And this is one of the reasons why it is highly recommended to use on-the-fly instrumentation - quoting http://www.jacoco.org/jacoco/trunk/doc/cli.html :
the preferred way for code coverage analysis with JaCoCo is on-the-fly instrumentation with the JaCoCo agent. Offline instrumentation has several drawbacks and should only be used if a specific scenario explicitly requires this mode.
One of such specific scenarios - is execution of tests on Android, because there is no way to use Java agent on it. So AFAIK Android Plugin for Gradle, when instructed to measure coverage using JaCoCo, uses offline instrumentation and therefore requires two types of build - with coverage and without for release.
On the other hand JaCoCo Gradle Plugin, which integrates JaCoCo into Gradle for Java projects, AFAIK as of today provides ability to perform only on-the-fly instrumentation and not offline.