我只是想了解底层架构,我认为我错了。
以教程here为例。
当我这样做时:
kotlinc-jvm hello.kt -include-runtime -d hello.jar
如果编译器已经将代码转换为Java字节码,为什么需要将Kotlin运行时捆绑到jar中?
答案 0 :(得分:34)
当您使用Java编写应用程序时,您将依赖所有标准类库。每个JRE都附带java.
个类(例如java.lang.*
,java.util.*
...),因此您无需自行打包它们。
Kotlin包含自己的标准类库( Kotlin运行时),与Java类库分开。要分发任何可以使用普通旧JRE运行的jar文件,您还需要捆绑Kotlin运行时。
如果您没有捆绑Kotlin运行时,那么您的用户必须确保在执行应用程序时Kotlin运行时在类路径上。您链接的页面提供了此方案的示例:
编译库
如果您正在开发一个供其他Kotlin应用程序使用的库,您可以生成.jar文件,而不包括Kotlin运行时。
$ kotlinc-jvm hello.kt -d hello.jar
如果您要定位其他Kotlin用户,那么可以合理地假设他们已经可以使用Kotlin运行时。但是,如果您正在尝试为最终用户部署应用程序,那么您希望包含Kotlin运行时,以便您的应用程序是自包含的。
答案 1 :(得分:24)
Greg Kopff's accepted answer解释了需要捆绑某些内容的一般情况,但我觉得这个问题的主要内容是错过的:为什么要编译成Java字节代码的东西(和因此不再是Kotlin)需要Kotlin“运行时”?
我的期望(以及提问者的期望,我怀疑)是,一旦编译,就不再有Kotlin的痕迹,因此不需要Kotlin运行时。
我的期望是“运行时”是某种原生二进制文件,如JRE,直接负责执行字节代码。
来自Kotlin language reference上的packages,但是:
默认情况下,许多软件包都会导入到每个Kotlin文件中:
- 科特林。*
- kotlin.annotation。*
- kotlin.collections。*
- kotlin.comparisons。*(自1.1起)
- kotlin.io。*
- kotlin.ranges。*
- kotlin.sequences。*
- kotlin.text。*
因此,似乎:
“Kotlin运行时”实际上只是一个“Kotlin类库”(而不是像JRE那样严格的单独“运行时”);
当Kotlin代码编译成Java字节代码时,Kotlin已经消失,但替换它的字节代码需要访问Kotlin类库;所以
Kotlin运行时必须可用于任何最初为Kotlin代码的Java字节代码,这可以通过将Kotlin运行时与这些代码捆绑在一起来完成。
对我而言,Kotlin团队使用“运行时”这个词引发了如此多的混乱。我更希望他们称之为“Kotlin支持类”,而不是使用具有非常不同内涵的Java术语。
这并不能解释为什么需要kotlin
包命名空间下的这么多东西,或者是否可以编写Kotlin文件实际上根本不依赖于Kotlin运行时,但也许这些是另一个问题的问题。
答案 2 :(得分:1)
Kotlin运行时不过是一组在运行时期间引用的库(捆绑在jar中),就像在classpath中的任何其他jar一样。
答案 3 :(得分:0)
也许.jar与Java兼容。
kotlin可以单独运行.class。
这也是工作
kotlinc hello.kt
kotlin HelloKt
答案 4 :(得分:0)
JRE不仅是本地二进制文件,而且还由JVM,Java标准库(Java SE API)和其他工具(如Rmiregisty)(Java 8及更低版本)组成。
JVM是本机应用程序,它直接负责执行字节码。如果编写仅依赖Java SE API的Java应用程序,则无需将任何库添加到类路径,因为Bootstrap类加载器和委托模型正在执行其工作。如果您编写Kotlin应用程序,则kotlinc编译器将添加一些“运行时代码”,并且您的应用程序将依赖于Kotlin库(似乎您的源代码不依赖于Kotlin库,而二进制代码则取决于)。因此,我认为,JetBrains的人员将其称为运行时库。顺便说一句,根据Central Maven存储库的说法,运行时库已重命名为kotlin-stdlib(Kotlin运行时(不建议使用,而是使用kotlin-stdlib工件)。