Этот вопрос относится к этому .
Я получил задание 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 работает нормально. Однако при развертывании на Raspberry Pi (или использовании локальных результатов jar 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 должна находиться в пути к классам и проверяться с помощью $ echo $ CLASSPATH.
Или вам нужно добавить kotlin-runtime в maven, а затем собрать внутри самого фляги с помощью компиляции mvn: single,
Это означает, что среда выполнения kotlin не включена в путь к классам. Прежде чем вы ответите «добавьте kotlin-runtime к вашим зависимостям», это часть stdlib :
Kotlin Runtime (устарело, используйте вместо этого артефакт kotlin-stdlib)
Я использую kotlin-stdlib-jdk8
, и он работает в IDE. Просто для тестирования использование kotlin-stdlib
вместо этого ничего не меняет.
Кроме того, замена implementation
на compile
исправляет это.
В посте, на который я ссылался вверху вопроса, есть предложение использовать runtime
в задании fatJar. Итак:
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
}
И исключение:
Непосредственное разрешение конфигурации 'реализация' не разрешено
Итак, учитывая:
compile
вместо implementation
работает
- Исключением времени выполнения является то, что Kotlin не находится в пути к классам
- Работает в IDE
- При добавлении предложения
implementation
к задаче fatJar
компиляция завершается с отдельным исключением
Как создать банку со всеми зависимостями в Gradle 4.4 при использовании ключевого слова implementation
?
Обработка предложенного дубликата: он работает только с ключевым словом compile, а не implementation
. Кроме того, compile
устарела в пользу implementation
и api
, поэтому использование compile
вместо implementation
при объявлении зависимости не вариант.