
Compiler plugin reducing APK size by optimizing data class methods like `toString`, `equals`, and `hashCode`. Configurable modes control method generation while retaining compatibility with bytecode optimizers.
or simply DCG
DataClassGenerate is a Kotlin compiler plugin that addresses APK size overhead.
DCG brings data class’ app size contribution on-par with semantically identical Plain Java Objects.
Kotlin positions data class as an easy-to-use and low friction utility for representing plain-old data.
Despite appearing compact in source code, the compiler generates multiple utility methods for each data class, which impact APK size e.g.: hashCode, equals, toString, copy, componentN.
Before an optimizer (like Redex or R8) can strip these methods, it must prove that they are never used.
Since methods like toString, equals, and hashCode are so fundamental (defined on Object/Any), calls to them will exist all over the app, and the optimizer must prove that a data class would not flow into any of those call sites, which is often not possible.
Apply the gradle plugin.
plugins {
id("com.facebook.kotlin.compilerplugins.dataclassgenerate") version <version>
}And that's it! The default configuration will add the artifact which contains @DataClassGenerate automatically.
If needed, you can configure the DataClassGenerate plugin using dataClassGenerate block:
import com.facebook.kotlin.compilerplugins.dataclassgenerate.gradle.DataClassGenerateMode
dataClassGenerate {
enabled.set(true/false) // defaults to true
mode.set(DataClassGenerateMode.EXPLICIT/STRICT/IMPLICIT) // defaults to EXPLICIT
generateSuperClass.set(true/false) // defaults to false
}DataClassGenerate Kotlin Compiler Plugin processes @DataClassGenerate annotation.
NOTE: DCG is applicable to Kotlin data classes only.
NOTE: DCG configures an intent to generate (KEEP) or skip (OMIT) toString, equals, and hashCode methods generation.
NOTE: DCG does not configure copy, componentN, and other methods, but Redex or R8 will take care of them.
@DataClassGenerate annotation configures Kotlin data class code generation and bytecode optimizations.
@DataClassGenerate is applicable only to Kotlin data classes, and will not make any change if applied to a regular class (Unfortunately, Kotlin does not have a data class as an annotation target).
@DataClassGenerate annotation, together with applied DataClassGenerate compiler plugin, does 3 things:
toString method.
@DataClassGenerate(toString = Mode.KEEP) will generate toString as in a usual data class.@DataClassGenerate(toString = Mode.OMIT) will NOT generate toString for an annotated data class.equals and hashCode methods.
@DataClassGenerate(equalsHashCode = Mode.KEEP) will generate equals and hashCode as in usual data class.@DataClassGenerate(equalsHashCode = Mode.OMIT) will NOT generate equals and hashCode for an annotated data class.DataClassSuper for suitable Data Classes to make them available for Redex Class Merging Optimization.
DataClassSuper. There is no guarantee a concrete data class will get a marker super class.How we can set @DataClassGenerate (toString = ???, equalsHashCode = ???) arguments?
| Mode | Explanation |
|---|---|
KEEP |
Express an intent to keep/generate a method(s) |
OMIT |
Express an intent to omit method(s) generation. |
@DataClassGenerate is declared with the following defaults:
annotation class DataClassGenerate(
val toString: Mode = Mode.OMIT,
val equalsHashCode: Mode = Mode.KEEP
)Kotlin allows annotation parameter name ommission. The table below explains @DataClassGenerate shortcuts:
| Declaration | Explicit Equivalent |
|---|---|
@DataClassGenerate |
@DataClassGenerate(toString = Mode.OMIT, equalsHashCode = Mode.KEEP) |
@DataClassGenerate() |
@DataClassGenerate(toString = Mode.OMIT, equalsHashCode = Mode.KEEP) |
@DataClassGenerate(Mode.KEEP) |
@DataClassGenerate(toString = Mode.KEEP, equalsHashCode = Mode.KEEP) |
@DataClassGenerate(Mode.KEEP, Mode.OMIT) |
@DataClassGenerate(toString = Mode.KEEP, equalsHashCode = Mode.OMIT) |
@DataClassGenerate(equalsHashCode = Mode.OMIT) |
@DataClassGenerate(toString = Mode.OMIT, equalsHashCode = Mode.OMIT) |
DataClassGenerate Kotlin compiler plugin works in multiple modes, but the most important is a STRICT mode.
In STRICT mode:
Plugin applies only to data classes annotated with @DataClassGenerate(...).
Plugin reports a compilation error whenever it sees a data class without @DataClassGenerate(...) annotation.
Example:
// Plugin will generate:
// -`toString`
// -`equals`, and `hashCode`
@DataClassGenerate(toString = Mode.KEEP, equalsHashCode = Mode.KEEP)
data class A(val i:Int)
// Plugin will report a compilation error
data class B(val l:Long)
In EXPLICIT mode:
@DataClassGenerate, DCG will act according to the annotation instructions for method generation.Example:
// Plugin will generate:
// -`toString`
// -`equals`, and `hashCode`
@DataClassGenerate(toString = Mode.KEEP, equalsHashCode = Mode.KEEP)
data class A(val i:Int)
// Plugin will only create a marker super class
data class B(val l:Long)
// Plugin will do nothing
data class C(val l:Long): SomeSuperClass()
Coming soon
| K1 | K2 |
|---|---|
| 1.5x | N/A |
| 1.6x | N/A |
| 1.7x-1.9x | 1.7.21 + -Xuse-k2
|
| N/A | 2.0+ |
DCG was created by the Kotlin Foundation team @ Meta:
DataClassGenerate is MIT-licensed.
or simply DCG
DataClassGenerate is a Kotlin compiler plugin that addresses APK size overhead.
DCG brings data class’ app size contribution on-par with semantically identical Plain Java Objects.
Kotlin positions data class as an easy-to-use and low friction utility for representing plain-old data.
Despite appearing compact in source code, the compiler generates multiple utility methods for each data class, which impact APK size e.g.: hashCode, equals, toString, copy, componentN.
Before an optimizer (like Redex or R8) can strip these methods, it must prove that they are never used.
Since methods like toString, equals, and hashCode are so fundamental (defined on Object/Any), calls to them will exist all over the app, and the optimizer must prove that a data class would not flow into any of those call sites, which is often not possible.
Apply the gradle plugin.
plugins {
id("com.facebook.kotlin.compilerplugins.dataclassgenerate") version <version>
}And that's it! The default configuration will add the artifact which contains @DataClassGenerate automatically.
If needed, you can configure the DataClassGenerate plugin using dataClassGenerate block:
import com.facebook.kotlin.compilerplugins.dataclassgenerate.gradle.DataClassGenerateMode
dataClassGenerate {
enabled.set(true/false) // defaults to true
mode.set(DataClassGenerateMode.EXPLICIT/STRICT/IMPLICIT) // defaults to EXPLICIT
generateSuperClass.set(true/false) // defaults to false
}DataClassGenerate Kotlin Compiler Plugin processes @DataClassGenerate annotation.
NOTE: DCG is applicable to Kotlin data classes only.
NOTE: DCG configures an intent to generate (KEEP) or skip (OMIT) toString, equals, and hashCode methods generation.
NOTE: DCG does not configure copy, componentN, and other methods, but Redex or R8 will take care of them.
@DataClassGenerate annotation configures Kotlin data class code generation and bytecode optimizations.
@DataClassGenerate is applicable only to Kotlin data classes, and will not make any change if applied to a regular class (Unfortunately, Kotlin does not have a data class as an annotation target).
@DataClassGenerate annotation, together with applied DataClassGenerate compiler plugin, does 3 things:
toString method.
@DataClassGenerate(toString = Mode.KEEP) will generate toString as in a usual data class.@DataClassGenerate(toString = Mode.OMIT) will NOT generate toString for an annotated data class.equals and hashCode methods.
@DataClassGenerate(equalsHashCode = Mode.KEEP) will generate equals and hashCode as in usual data class.@DataClassGenerate(equalsHashCode = Mode.OMIT) will NOT generate equals and hashCode for an annotated data class.DataClassSuper for suitable Data Classes to make them available for Redex Class Merging Optimization.
DataClassSuper. There is no guarantee a concrete data class will get a marker super class.How we can set @DataClassGenerate (toString = ???, equalsHashCode = ???) arguments?
| Mode | Explanation |
|---|---|
KEEP |
Express an intent to keep/generate a method(s) |
OMIT |
Express an intent to omit method(s) generation. |
@DataClassGenerate is declared with the following defaults:
annotation class DataClassGenerate(
val toString: Mode = Mode.OMIT,
val equalsHashCode: Mode = Mode.KEEP
)Kotlin allows annotation parameter name ommission. The table below explains @DataClassGenerate shortcuts:
| Declaration | Explicit Equivalent |
|---|---|
@DataClassGenerate |
@DataClassGenerate(toString = Mode.OMIT, equalsHashCode = Mode.KEEP) |
@DataClassGenerate() |
@DataClassGenerate(toString = Mode.OMIT, equalsHashCode = Mode.KEEP) |
@DataClassGenerate(Mode.KEEP) |
@DataClassGenerate(toString = Mode.KEEP, equalsHashCode = Mode.KEEP) |
@DataClassGenerate(Mode.KEEP, Mode.OMIT) |
@DataClassGenerate(toString = Mode.KEEP, equalsHashCode = Mode.OMIT) |
@DataClassGenerate(equalsHashCode = Mode.OMIT) |
@DataClassGenerate(toString = Mode.OMIT, equalsHashCode = Mode.OMIT) |
DataClassGenerate Kotlin compiler plugin works in multiple modes, but the most important is a STRICT mode.
In STRICT mode:
Plugin applies only to data classes annotated with @DataClassGenerate(...).
Plugin reports a compilation error whenever it sees a data class without @DataClassGenerate(...) annotation.
Example:
// Plugin will generate:
// -`toString`
// -`equals`, and `hashCode`
@DataClassGenerate(toString = Mode.KEEP, equalsHashCode = Mode.KEEP)
data class A(val i:Int)
// Plugin will report a compilation error
data class B(val l:Long)
In EXPLICIT mode:
@DataClassGenerate, DCG will act according to the annotation instructions for method generation.Example:
// Plugin will generate:
// -`toString`
// -`equals`, and `hashCode`
@DataClassGenerate(toString = Mode.KEEP, equalsHashCode = Mode.KEEP)
data class A(val i:Int)
// Plugin will only create a marker super class
data class B(val l:Long)
// Plugin will do nothing
data class C(val l:Long): SomeSuperClass()
Coming soon
| K1 | K2 |
|---|---|
| 1.5x | N/A |
| 1.6x | N/A |
| 1.7x-1.9x | 1.7.21 + -Xuse-k2
|
| N/A | 2.0+ |
DCG was created by the Kotlin Foundation team @ Meta:
DataClassGenerate is MIT-licensed.