问题
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); \
}'
}
回答1:
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 package kotlin
: 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 class kotlin.String
exactly in the same way as the Kotlin compiler sees those members (despite the fact that there's no kotlin/String.class
file and it's erased to java.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.
回答2:
You can optimize/omit these from yours JARs/APKs:
packagingOptions {
exclude "/META-INF/*.kotlin_module"
exclude "**/kotlin/**"
}
Even better:
packagingOptions {
exclude "/META-INF/*.kotlin_module"
exclude "**/kotlin/**"
exclude "**/*.txt"
exclude "**/*.xml"
exclude "**/*.properties"
}
Source: https://github.com/jaredsburrows/android-gif-example/blob/master/build.gradle.kts#L127
来源:https://stackoverflow.com/questions/41052868/what-are-kotlin-builtins-files-and-can-i-omit-them-from-my-uberjars