Introduction
Since Groovy 2.0, support was added for the JVM invokedynamic instruction. This instruction is supported since Java 7 and is a bytecode instruction in the JVM that allows easier implementation of dynamic languages. This instruction is also used internally, by the JVM, for lambda support in Java 8+.
This feature is not visible to the developer or the end user. It is a compilation and runtime feature only. It affects how Groovy compiles dynamic method calls, property access, and other dynamic operations into bytecode.
Groovy 4.0+ (current)
From Groovy 4.0 onwards, invokedynamic bytecode generation is enabled by default. There is a single set of jars, compiled with invokedynamic enabled. The separate "-indy" jars and Maven classifiers from earlier versions are no longer needed.
It is still possible to disable invokedynamic for user-compiled code, which causes the compiler to fall back to classic call-site caching bytecode. This can be useful in cases where call-site caching is faster for specific workloads. To disable:
- System property:
groovy.target.indy=false - Compiler configuration: set the
indyoptimization option tofalse
Note that disabling invokedynamic only affects the bytecode generated for your code. The Groovy runtime jars themselves are compiled with invokedynamic enabled.
There are also internal thresholds that can be tuned for performance
(search the codebase for groovy.indy.optimize.threshold
and groovy.indy.fallback.threshold).
Groovy 2.0 to 3.x
Two JARs
The Groovy distribution came with two jars:
groovy-x.y.z.jar: compiled with classic call-site cachinggroovy-x-y-z-indy.jar: compiled with invokedynamic
Both jars contained a fully working Groovy implementation capable of compiling user code using either invokedynamic or call-site caching. The sets of jars were mutually exclusive (don't put both on classpath) and the key difference was how the Groovy source files that make up Groovy itself were compiled.
When accessing a Groovy jar from a Maven repository, you could select the indy version using the 'indy' classifier.
The compilation flag
Independently of the jar version used, invokedynamic support required a specific compilation flag (indy). If you wanted to compile your classes with invokedynamic support, this flag had to be set at compile time.
For user compiled classes:
| indy flag | off | on |
|---|---|---|
| normal jar | call site caching | invokedynamic |
| indy jar | call site caching | invokedynamic |
For core Groovy classes:
| indy flag | off | on |
|---|---|---|
| normal jar | call site caching | call site caching |
| indy jar | invokedynamic | invokedynamic |
So even if you used the indy jar, if you didn't use the invokedynamic flag at compile time, then the compiled classes would use the "old" format with call-site caching.