I'm working on integrating proguard to my gradle build for an application written in Kotlin. I'm finding that proguard is stripping out the Kotlin standard library (as it should in my simple Hello World program) but it's leaving a bunch of files in my jar that have the file extension .kotlin_builtins
. When I configure my gradle task to exclude those files, the program still appears to work fine. What are those files and must they ship with my executable uberjar?
Here's my build.gradle
file's contents for reference:
buildscript {
ext.kotlin_version = '1.0.5'
ext.shadow_version = '1.2.4'
repositories {
mavenCentral()
maven {
url "https://plugins.gradle.org/m2/"
}
flatDir dirs: "gradle/proguard"
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "com.github.jengelman.gradle.plugins:shadow:$shadow_version"
classpath ":proguard:"
}
}
apply plugin: 'kotlin'
apply plugin: 'application'
apply plugin: 'com.github.johnrengelman.shadow'
mainClassName = 'namespace.MainKt'
defaultTasks 'run'
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
testCompile "junit:junit:4.12"
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
}
shadowJar {
exclude 'kotlin/**/*.kotlin_builtins'
exclude '.keep'
}
task minify(type: proguard.gradle.ProGuardTask, dependsOn: 'shadowJar') {
libraryjars "${System.getProperty('java.home')}/lib/rt.jar"
injars 'build/libs/artful-all.jar'
outjars 'build/libs/artful-all.out.jar'
printmapping 'build/libs/out.map'
keepclasseswithmembers 'public class * { \
public static void main(java.lang.String[]); \
}'
assumenosideeffects 'class kotlin.jvm.internal.Intrinsics { \
static void checkParameterIsNotNull(java.lang.Object, java.lang.String); \
}'
}
You can optimize/omit these from yours JARs/APKs:
Even better:
Source: https://github.com/jaredsburrows/android-gif-example/blob/master/build.gradle.kts#L127
These files contain data for declarations of standard ("built-in") Kotlin classes which are not compiled to
.class
files, but rather are mapped to the existing types on the platform (in this case, JVM). For example,kotlin/kotlin.kotlin_builtins
contains the information for non-physical classes in packagekotlin
:Int
,String
,Enum
,Annotation
,Collection
, etc.There are two main scenarios when these files are used:
1) The compiler looks them up from
kotlin-runtime
on the classpath to determine which built-in declarations are available.2) The reflection library (
kotlin-reflect
) loads these files as resources to provide reflection capabilities for built-in declarations. For example,String::class.members
returns all members of the classkotlin.String
exactly in the same way as the Kotlin compiler sees those members (despite the fact that there's nokotlin/String.class
file and it's erased tojava.lang.String
in bytecode).The first point is clearly not applicable in your case. And if you don't use reflection on built-in classes, I think it's safe to exclude
.kotlin_builtins
files completely from the resulting jar.