英文:
How do I run Kotlin code using OkHttp from the command line?
问题
I tried running Kotlin code on macOS 13 from the command line, first I installed it with:
brew install kotlin
then I made a directory and downloaded the latest versions of some jar files that seemed relevant:
mkdir -p /tmp/kotlin
cd /tmp/kotlin
curl https://repo1.maven.org/maven2/com/squareup/okhttp3/okhttp/4.11.0/okhttp-4.11.0.jar > okhttp-4.11.0.jar
curl https://repo1.maven.org/maven2/com/squareup/okio/okio/3.3.0/okio-3.3.0.jar > okio-3.3.0.jar
curl https://repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.8.21/kotlin-stdlib-1.8.21.jar > kotlin-stdlib-1.8.21.jar
(ChatGPT told me to install kotlin-stdlib too, I'm not sure that makes sense...)
then I created a sample file called OkHttpExample.kt with these contents:
import java.io.IOException;
import okhttp3.OkHttpClient
import okhttp3.Request
fun main() {
val client = OkHttpClient()
val request = Request.Builder()
.url("https://example.com")
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
println(response.body!!.string())
}
}
and tried to compile and run it
kotlinc -classpath okhttp-4.11.0.jar:kotlin-stdlib-1.8.21.jar:okio-3.3.0.jar OkHttpExample.kt -include-runtime -d OkHttpExample.jar
java -classpath okhttp-4.11.0.jar:kotlin-stdlib-1.8.21.jar:okio-3.3.0.jar:OkHttpExample.jar OkHttpExampleKt
but the java
command fails with this error:
Exception in thread "main" java.lang.NoClassDefFoundError: okio/Buffer
at okhttp3.ResponseBody$Companion.create(ResponseBody.kt:248)
at okhttp3.ResponseBody$Companion.create$default(ResponseBody.kt:247)
at okhttp3.internal.Util.<clinit>(Util.kt:65)
at okhttp3.OkHttpClient.<clinit>(OkHttpClient.kt:1073)
at OkHttpExampleKt.main(OkHttpExample.kt:6)
at OkHttpExampleKt.main(OkHttpExample.kt)
Caused by: java.lang.ClassNotFoundException: okio.Buffer
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 6 more
英文:
I tried running Kotlin code on macOS 13 from the command line, first I installed it with
brew install kotlin
then I made a directory and downloaded the latest versions of some jar files that seemed relevant:
mkdir -p /tmp/kotlin
cd /tmp/kotlin
curl https://repo1.maven.org/maven2/com/squareup/okhttp3/okhttp/4.11.0/okhttp-4.11.0.jar > okhttp-4.11.0.jar
curl https://repo1.maven.org/maven2/com/squareup/okio/okio/3.3.0/okio-3.3.0.jar > okio-3.3.0.jar
curl https://repo1.maven.org/maven2/org/jetbrains/kotlin/kotlin-stdlib/1.8.21/kotlin-stdlib-1.8.21.jar > kotlin-stdlib-1.8.21.jar
(ChatGPT told me to install kotlin-stdlib too, I'm not sure that makes sense...)
then I created a sample file called OkHttpExample.kt with these contents:
import java.io.IOException;
import okhttp3.OkHttpClient
import okhttp3.Request
fun main() {
val client = OkHttpClient()
val request = Request.Builder()
.url("https://example.com")
.build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
println(response.body!!.string())
}
}
and tried to compile and run it
kotlinc -classpath okhttp-4.11.0.jar:kotlin-stdlib-1.8.21.jar:okio-3.3.0.jar OkHttpExample.kt -include-runtime -d OkHttpExample.jar
java -classpath okhttp-4.11.0.jar:kotlin-stdlib-1.8.21.jar:okio-3.3.0.jar:OkHttpExample.jar OkHttpExampleKt
but the java
command fails with this error:
Exception in thread "main" java.lang.NoClassDefFoundError: okio/Buffer
at okhttp3.ResponseBody$Companion.create(ResponseBody.kt:248)
at okhttp3.ResponseBody$Companion.create$default(ResponseBody.kt:247)
at okhttp3.internal.Util.<clinit>(Util.kt:65)
at okhttp3.OkHttpClient.<clinit>(OkHttpClient.kt:1073)
at OkHttpExampleKt.main(OkHttpExample.kt:6)
at OkHttpExampleKt.main(OkHttpExample.kt)
Caused by: java.lang.ClassNotFoundException: okio.Buffer
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:641)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:188)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:521)
... 6 more
答案1
得分: 1
解决您的具体问题
NoClassDefFoundError: okio/Buffer
表示某些代码尝试使用 okio.Buffer
类,但该类不在您放在类路径上的任何jar文件中。
这可能是因为您刚刚手动挑选了一些要下载的jar文件,并且忽略了传递性依赖关系。例如,您可能缺少了 okio
本身的依赖项 okio-jvm
。
一种解决方法是自行查找所有传递性依赖项(例如,查看Maven Central中的.pom
文件),然后手动下载更多jar文件,但这并不是非常实际的方法。
推荐方法
相反,我强烈建议在这里有两个选项:
-
创建一个“标准”的Kotlin项目,并使用构建工具如Gradle来管理依赖项和编译。这需要一些设置,但对大多数人来说会更加熟悉,而且您可以轻松找到在线示例。
-
如果您只是在玩耍,可以尝试使用Kotlin脚本,使用
.main.kts
脚本定义,这可能简化您的工作流程,但请注意它是实验性的并且不是很知名。
我将在这里详细介绍选项2,因为关于它的信息较难找到。
要使用main-kts定义,请确保您的文件以.main.kts
结尾。然后将您的代码直接放在文件的顶层,而不是将其包装在main()
函数中。
不需要手动下载jar文件,只需在文件顶部使用@file:DependsOn
添加依赖项,其中包含依赖项的Maven坐标(您无需添加传递性依赖项,只需添加您直接使用的依赖项):
script.main.kts
(扩展名很重要!)
@file:DependsOn("com.squareup.okhttp3:okhttp:4.11.0")
import java.io.IOException
import okhttp3.OkHttpClient
import okhttp3.Request
val client = OkHttpClient()
val request = Request.Builder().url("https://example.com").build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
println(response.body!!.string())
}
然后,您可以使用一个简单的命令来编译并运行它:
kotlin script.main.kts
这里有一个更“官方”的关于main.kts
使用的示例:
https://github.com/Kotlin/kotlin-script-examples/blob/master/jvm/main-kts/MainKts.md
英文:
Fixing your specific problem
NoClassDefFoundError: okio/Buffer
means that some code tries to use the okio.Buffer
class but the class is not in any jar that you put on the classpath.
This may happen because you just manually cherry-picked some jars to download, and you missed transitive dependencies. For instance, it's likely you're missing the okio-jvm
dependency, which is a dependency of okio
itself.
One solution is to find all transitive dependencies yourself (for instance by looking at .pom
files in Maven Central) and download more and more jars by hand, but it's not very practical.
Recommended approaches
Instead, I highly suggest 2 options here:
-
create a "standard" Kotlin project and use a build tool like Gradle to manage dependencies and compilation. It requires a bit of setup, but it will be more familiar to most people, and you may easily find examples online.
-
if you're just playing around, you can try to use Kotlin Scripting with the
.main.kts
script definition, which may simplify your workflow here, but note that it's experimental and not very well known.
I'll elaborate on option 2 here because it's harder to find information about it.
To use the main-kts definition, make sure your file ends with .main.kts
. Then put your code directly at the top level without wrapping it in a main()
function.
Instead of manually downloading jars, add dependencies to it using @file:DependsOn
at the top of the file, with the maven coordinates of the dependencies (you don't need to put transitive dependencies, just the ones you want to use directly):
script.main.kts
(the extension matters!)
@file:DependsOn("com.squareup.okhttp3:okhttp:4.11.0")
import java.io.IOException
import okhttp3.OkHttpClient
import okhttp3.Request
val client = OkHttpClient()
val request = Request.Builder().url("https://example.com").build()
client.newCall(request).execute().use { response ->
if (!response.isSuccessful) throw IOException("Unexpected code $response")
println(response.body!!.string())
}
Then you can compile and run it in one simple command:
kotlin script.main.kts
Here is a more "official" example about main.kts
usage:
https://github.com/Kotlin/kotlin-script-examples/blob/master/jvm/main-kts/MainKts.md
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论