1

我想编译一个带有依赖项/导入的 kotlin 文件

package_a.kt

// file: package_a.kt
package package_a

fun function_from_package_a(){
    println(" hurray function_from_package_a was called ! ")
}

主文件

// file: main.kt

import package_a.*

fun main() {
    
    function_from_package_a();

    println("main function  was executed")
}

编译正在使用

$ kotlinc package_a.kt -d package_a.jar               
$ kotlinc main.kt -classpath package_a.jar -d main.jar

但是当我用java运行main.jar时,我会得到一个错误:

$ java -jar main.jar
Exception in thread "main" java.lang.NoClassDefFoundError: package_a/Package_aKt
        at MainKt.main(main.kt:8)
        at MainKt.main(main.kt)
Caused by: java.lang.ClassNotFoundException: package_a.Package_aKt
        at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:602)
        at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:178)
        at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:522)
        ... 2 more

有人知道为什么吗?

4

2 回答 2

0

我找到了问题的解决方案

我将 main.kt 更改为

// file: main.kt
package test

import package_a.*

fun main() {
    
    function_from_package_a();

    println("main function  was executed")
}

然后我可以运行它

java -cp main.jar:package_a.jar test.MainKt
于 2022-01-16T02:40:05.187 回答
0

使用命令编译主类时:

kotlinc main.kt -classpath package_a.jar -d main.jar

结果main.jar只包含主类对象。它不包含package_a包中的对象。仅允许在编译期间解析符号的-classpath选项。kotlinc它不会导致结果main.jar文件中包含任何其他内容。

因此,当您执行时:

java -jar main.jar

Java 不知道从哪里获取package_a包的内容。

然后你可能会认为这会起作用:

java -classpath package_a.jar -jar main.jar

但这也不起作用,因为当您指定 Java 执行 jar 文件时,所有用于查找依赖对象的指令,无论是在 jar 文件中还是在其他地方,都必须来自 jar 文件本身。使用该-classpath选项时忽略该-jar选项。

更新:我只在发布我自己的答案后才看到 OP 发布了答案。运行代码的另一种方式是有效的,因为-jar没有使用该选项,因此该-classpath选项不会被忽略,因此指示的命令告诉 Java 要执行什么,还告诉它在哪里可以找到所有必要的类文件。

注意:不需要对原始源文件进行任何更改。主类不需要在命名包中就可以在命令行上引用它。此命令将以原始形式执行代码:

java -cp main.jar:package_a.jar MainKt

另一种选择是在main.jar文件中包含依赖包。我试过这个,它工作正常。这有点复杂,因为您必须正确获取清单,以便 Java 知道要执行哪个类。因为OP已经找到了另一种方式,这里不再赘述。

于 2022-01-16T02:45:16.350 回答