为什么 Kotlin 编译后需要打包它的运行时?
Why Kotlin needs to bundle its runtime after compiled?
我只是想了解底层架构,但我认为我弄错了。
以教程here为例
当我这样做时:
kotlinc-jvm hello.kt -include-runtime -d hello.jar
如果编译器已经将代码转换为 Java 字节码,为什么需要将 Kotlin 运行时捆绑到 jar 中?
当您在 Java 中编写应用程序时,您将依赖所有标准 class 库。每个 JRE 都包含 java.
classes(例如 java.lang.*
、java.util.*
...),因此您不需要自己打包它们。
Kotlin 包含自己的标准 class 库(Kotlin 运行time),独立于 Java class图书馆。要分发任何使用普通旧 JRE 的人都可以 运行 的 jar 文件,您还需要捆绑 Kotlin 运行 时间。
如果您没有捆绑 Kotlin 运行time,那么您的用户在执行您的应用程序时必须确保 Kotlin 运行time 在 classpath 上。您链接的页面给出了这种情况的示例:
Compiling a library
If you’re developing a library to be used by other Kotlin applications, you can produce the .jar file without including the Kotlin runtime into it.
$ kotlinc-jvm hello.kt -d hello.jar
如果您的目标是其他 Kotlin 用户,那么可以合理地假设他们已经可以使用 Kotlin 运行时间。但是,如果您尝试为最终用户部署应用程序,那么您希望包括 Kotlin 运行时间,以便您的应用程序是独立的。
解释了需要捆绑某些东西的一般情况,但我觉得问题的要点被遗漏了:为什么编译成 Java 字节的东西应该-code(因此不再是 Kotlin)需要 Kotlin“运行时”?
我的期望(以及提问者的期望,我怀疑)是一旦编译,就再也没有 Kotlin 的踪迹,因此应该不需要 Kotlin 运行时。
我还期望“运行时”是某种本机二进制文件,如 JRE,直接负责执行字节码。
来自 Kotlin language reference on packages,但是:
A number of packages are imported into every Kotlin file by default:
- kotlin.*
- kotlin.annotation.*
- kotlin.collections.*
- kotlin.comparisons.* (since 1.1)
- kotlin.io.*
- kotlin.ranges.*
- kotlin.sequences.*
- kotlin.text.*
因此,似乎是:
“Kotlin 运行时”实际上只是一个“Kotlin class 库”(并不是像 JRE 那样严格意义上的独立“运行时”) ;
当 Kotlin 代码被编译成 Java 字节码时,Kotlin 消失了,但是替换它的字节码需要访问 Kotlin class图书馆;所以
Kotlin 运行时必须可用于任何最初是 Kotlin 代码的 Java 字节码,这可以通过捆绑 Kotlin使用这样的代码运行时。
对我来说,Kotlin 团队对“运行时”一词的使用引发了如此多的困惑。我宁愿他们称之为“Kotlin 支持 classes”,而不是使用具有非常不同内涵的 Java 术语。
这并不能解释为什么需要 kotlin
包命名空间下的这么多东西,或者是否可以编写实际上根本不依赖 Kotlin 运行时的 Kotlin 文件,但也许这些是另一个问题的问题。
也许 .jar 与 java.
兼容
kotlin 可以 运行 .class 本身。
这也是工作
kotlinc hello.kt
kotlin HelloKt
Kotlin 运行时只不过是一组在运行时引用的库(捆绑在一个 jar 中),就像类路径中的任何其他 jar 一样。
JRE 不仅是本机二进制文件,JRE 由 JVM、java 标准库 (Java SE API) 和其他工具如 Rmiregisty (Java 8 和降低)。
JVM 是本机应用程序,它直接负责执行字节码。如果你编写 java 只依赖于 Java SE API 的应用程序,它不需要将任何库添加到类路径,因为 Bootstrap 类加载器和委托模型正在完成它们的工作.如果您编写 Kotlin 应用程序,kotlinc 编译器会添加一些 "runtime code" 并且您的应用程序变得依赖于 Kotlin 库(看起来您的源代码不依赖于 kotlin 库,但二进制代码依赖)。因此,我认为 JetBrains 的人将其称为运行时库。顺便说一句,根据 Central Maven 存储库,runtime-library 被重命名为 kotlin-stdlib(Kotlin Runtime(已弃用,改用 kotlin-stdlib 工件)。
使用 kotlin
命令行可以轻松解决所有 kotlin 特定的依赖项。
AFAIK 所有其他参数都类似于 java
我只是想了解底层架构,但我认为我弄错了。
以教程here为例
当我这样做时:
kotlinc-jvm hello.kt -include-runtime -d hello.jar
如果编译器已经将代码转换为 Java 字节码,为什么需要将 Kotlin 运行时捆绑到 jar 中?
当您在 Java 中编写应用程序时,您将依赖所有标准 class 库。每个 JRE 都包含 java.
classes(例如 java.lang.*
、java.util.*
...),因此您不需要自己打包它们。
Kotlin 包含自己的标准 class 库(Kotlin 运行time),独立于 Java class图书馆。要分发任何使用普通旧 JRE 的人都可以 运行 的 jar 文件,您还需要捆绑 Kotlin 运行 时间。
如果您没有捆绑 Kotlin 运行time,那么您的用户在执行您的应用程序时必须确保 Kotlin 运行time 在 classpath 上。您链接的页面给出了这种情况的示例:
Compiling a library
If you’re developing a library to be used by other Kotlin applications, you can produce the .jar file without including the Kotlin runtime into it.
$ kotlinc-jvm hello.kt -d hello.jar
如果您的目标是其他 Kotlin 用户,那么可以合理地假设他们已经可以使用 Kotlin 运行时间。但是,如果您尝试为最终用户部署应用程序,那么您希望包括 Kotlin 运行时间,以便您的应用程序是独立的。
我的期望(以及提问者的期望,我怀疑)是一旦编译,就再也没有 Kotlin 的踪迹,因此应该不需要 Kotlin 运行时。
我还期望“运行时”是某种本机二进制文件,如 JRE,直接负责执行字节码。
来自 Kotlin language reference on packages,但是:
A number of packages are imported into every Kotlin file by default:
- kotlin.*
- kotlin.annotation.*
- kotlin.collections.*
- kotlin.comparisons.* (since 1.1)
- kotlin.io.*
- kotlin.ranges.*
- kotlin.sequences.*
- kotlin.text.*
因此,似乎是:
“Kotlin 运行时”实际上只是一个“Kotlin class 库”(并不是像 JRE 那样严格意义上的独立“运行时”) ;
当 Kotlin 代码被编译成 Java 字节码时,Kotlin 消失了,但是替换它的字节码需要访问 Kotlin class图书馆;所以
Kotlin 运行时必须可用于任何最初是 Kotlin 代码的 Java 字节码,这可以通过捆绑 Kotlin使用这样的代码运行时。
对我来说,Kotlin 团队对“运行时”一词的使用引发了如此多的困惑。我宁愿他们称之为“Kotlin 支持 classes”,而不是使用具有非常不同内涵的 Java 术语。
这并不能解释为什么需要 kotlin
包命名空间下的这么多东西,或者是否可以编写实际上根本不依赖 Kotlin 运行时的 Kotlin 文件,但也许这些是另一个问题的问题。
也许 .jar 与 java.
兼容
kotlin 可以 运行 .class 本身。
这也是工作
kotlinc hello.kt
kotlin HelloKt
Kotlin 运行时只不过是一组在运行时引用的库(捆绑在一个 jar 中),就像类路径中的任何其他 jar 一样。
JRE 不仅是本机二进制文件,JRE 由 JVM、java 标准库 (Java SE API) 和其他工具如 Rmiregisty (Java 8 和降低)。
JVM 是本机应用程序,它直接负责执行字节码。如果你编写 java 只依赖于 Java SE API 的应用程序,它不需要将任何库添加到类路径,因为 Bootstrap 类加载器和委托模型正在完成它们的工作.如果您编写 Kotlin 应用程序,kotlinc 编译器会添加一些 "runtime code" 并且您的应用程序变得依赖于 Kotlin 库(看起来您的源代码不依赖于 kotlin 库,但二进制代码依赖)。因此,我认为 JetBrains 的人将其称为运行时库。顺便说一句,根据 Central Maven 存储库,runtime-library 被重命名为 kotlin-stdlib(Kotlin Runtime(已弃用,改用 kotlin-stdlib 工件)。
使用 kotlin
命令行可以轻松解决所有 kotlin 特定的依赖项。
AFAIK 所有其他参数都类似于 java