compile
方法已经被弃用,推荐使用implementation
方法。它能够加载通过compile
方法声明的依赖项。但是,由于其已经被弃用,不能再使用该方法(而且当该方法被移除时会回到之前的状态)。
我有一个Gradle任务:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'rpi-sense-hat-lib',
'Implementation-Version': version,
'Main-Class': 'io.github.lunarwatcher.pi.sensehat.Tests'
}
baseName = project.name
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
只有一个依赖项,不考虑测试依赖项:
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlin_version"
testImplementation group: 'junit', name: 'junit', version: '4.12'
}
在IDE中运行正常。但是,当我部署到我的树莓派上(或者使用本地的gradlew fatJar
结果),我会收到以下异常:
$ java -jar java-sense-hat-1.0a.jar
Exception in thread "main" java.lang.NoClassDefFoundError: kotlin/jvm/internal/Intrinsics
at io.github.lunarwatcher.pi.sensehat.UtilsKt.getSenseHat(Utils.kt:18)
at io.github.lunarwatcher.pi.sensehat.SenseHat.<init>(SenseHat.java:12)
at io.github.lunarwatcher.pi.sensehat.Tests.main(Tests.java:9)
Caused by: java.lang.ClassNotFoundException: kotlin.jvm.internal.Intrinsics
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(Unknown Source)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(Unknown Source)
at java.base/java.lang.ClassLoader.loadClass(Unknown Source)
... 3 more
这是由以下代码触发的:
return Optional.empty()
在返回一个
Optional<File>
的 Kotlin 方法中,相关问题的答案指出:
要么将 kotlin-runtime 加入 classpath 并使用 $ echo $CLASSPATH 进行验证。
或者将 kotlin-runtime 添加到 maven 中,然后使用 mvn compile assembly:single 将其汇编到 jar 文件中。
这意味着 kotlin-runtime 没有包含在 classpath 中。在回答“将 kotlin-runtime 添加到依赖项中”之前,请注意它是 stdlib 的一部分:
Kotlin Runtime(已弃用,改用 kotlin-stdlib)
我使用了 kotlin-stdlib-jdk8
,在 IDE 中可以正常工作。仅供测试目的,使用 kotlin-stdlib
不会改变任何内容。
此外,将 implementation
替换为 compile
可以解决问题。
在我链接到问题顶部的帖子中,建议在 fatJar 任务中使用 runtime
。因此:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'rpi-sense-hat-lib',
'Implementation-Version': version,
'Main-Class': 'io.github.lunarwatcher.pi.sensehat.Tests'
}
baseName = project.name
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
依赖项仍未包含在内,导致程序崩溃。
那么为什么不将实现添加为配置项以进行复制呢?
我尝试了,但最终得到了这个结果:
task fatJar(type: Jar) {
manifest {
attributes 'Implementation-Title': 'rpi-sense-hat-lib',
'Implementation-Version': version,
'Main-Class': 'io.github.lunarwatcher.pi.sensehat.Tests'
}
baseName = project.name
from {
configurations.compile.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.runtime.collect {
it.isDirectory() ? it : zipTree(it)
}
configurations.implementation.collect {
it.isDirectory() ? it : zipTree(it)
}
}
with jar
}
同时还有一个异常:
不允许直接解决配置“implementation”
考虑到:
compile
可以替换implementation
- 运行时异常是由于 Kotlin 不在类路径中导致的
- 在 IDE 中可以正常工作
- 将
implementation
语句添加到fatJar
任务会导致编译崩溃并出现单独的异常
当使用 implementation
关键字时,如何在 Gradle 4.4 中生成包含所有依赖项的 jar 包?