11

我正在为用 Kotlin 编写的应用程序将 proguard 集成到我的 gradle 构建中。我发现 proguard 正在剥离 Kotlin 标准库(在我的简单 Hello World 程序中应该如此),但它在我的 jar 中留下了一堆文件扩展名为.kotlin_builtins. 当我配置我的 gradle 任务以排除这些文件时,该程序似乎仍然可以正常工作。这些文件是什么,它们必须与我的可执行 uberjar 一起提供吗?

这是我的build.gradle文件内容供参考:

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); \
    }'
}
4

2 回答 2

14

这些文件包含声明标准(“内置”)Kotlin 类的数据,这些类未编译为.class文件,而是映射到平台上的现有类型(在本例中为 JVM)。例如,kotlin/kotlin.kotlin_builtins包含包中非物理类的信息kotlinIntStringEnumAnnotationCollection等。

使用这些文件时主要有两种情况:

  1. 编译器从类路径中查找它们kotlin-stdlib以确定哪些内置声明可用。

  2. 反射库 ( kotlin-reflect) 将这些文件作为资源加载,以为内置声明提供反射功能。例如,以与 Kotlin 编译器看到这些成员的方式完全相同的方式String::class.members返回类的所有成员(尽管事实上没有文件并且它在字节码中被擦除)。kotlin.Stringkotlin/String.classjava.lang.String

第一点显然不适用于您的情况。而且,如果您不对内置类使用反射,我认为.kotlin_builtins从生成的 jar 中完全排除文件是安全的。

于 2016-12-10T08:53:38.097 回答
3

您可以从您的 JAR/APK 中优化/省略这些:

packagingOptions {
  exclude "/META-INF/*.kotlin_module"
  exclude "**/kotlin/**"
}

更好的是:

packagingOptions {
  exclude "/META-INF/*.kotlin_module"
  exclude "**/kotlin/**"
  exclude "**/*.txt"
  exclude "**/*.xml"
  exclude "**/*.properties"
}

来源:https ://github.com/jaredsburrows/android-gif-example/blob/master/build.gradle.kts#L127

于 2017-07-04T16:33:47.880 回答