If you have ever written a custom Gradle task to analyze or process compiled bytecode (like custom linters, schema validators, or metadata generators), you have probably encountered a hidden, silent performance killer: the aggressive compiler erasure.
In this first article of our Gradle Under the Hood series, we’ll explore how we re-engineered the incremental tracking of JPersist (a zero-boilerplate JPA build automation suite) to achieve bulletproof UP-TO-DATE execution states, even when the Java compiler tries to destroy your task's cache.
The Naive Approach to Bytecode Tasks
When building a task that processes compiled .class files, the most intuitive setup is to declare the compiler's output directory as your task's @InputDirectory :
abstract class MyBytecodeTask extends DefaultTask { @InputDirectory abstract DirectoryProperty getCompiledClassesDir ()
@TaskAction void execute ( InputChanges inputChanges ) { // Process altered files...…