为何Kotlin/Retrofit脚本执行完毕后无法正常退出?
为什么这段Kotlin/Retrofit脚本无法正常退出?
这段改编自Retrofit官方示例的Kotlin脚本,在执行完打印操作后会挂起,必须手动调用exitProcess(0)才能退出,核心原因和OkHttp的后台线程机制有关:
问题代码
#!/usr/bin/env kotlin @file:Repository("https://repo.maven.apache.org/maven2/") @file:DependsOn("com.squareup.retrofit2:retrofit:2.9.0") @file:DependsOn("com.squareup.retrofit2:converter-gson:2.9.0") import retrofit2.Call import retrofit2.Retrofit import retrofit2.converter.gson.GsonConverterFactory import retrofit2.http.GET import retrofit2.http.Path import java.lang.RuntimeException import kotlin.system.exitProcess data class Repo( val id: Int, val name: String ) interface GitHubService { @GET("users/{user}/repos") fun listRepos(@Path("user") user: String?): Call<List<Repo>?>? } var retrofit: Retrofit = Retrofit.Builder() .baseUrl("https://api.github.com/") .addConverterFactory(GsonConverterFactory.create()) .build() var service: GitHubService = retrofit.create(GitHubService::class.java) ?: throw RuntimeException() val repoList = service.listRepos("octocat")?.execute()?.body() ?: throw RuntimeException() println("The repos' names: ${repoList.joinToString(", ") { it.name }} ") // The program just hangs unless I uncomment the next line //exitProcess(0)
挂起原因
Retrofit默认依赖OkHttp作为底层HTTP客户端,OkHttp内部的Dispatcher(请求调度器)会维护一个非守护线程池,用来处理请求执行和连接池的后台维护(比如清理空闲连接)。
当主线程执行完所有业务代码后,这些后台线程仍然处于活跃状态(等待接收新请求或执行定时任务)。JVM的退出规则是:只有当所有非守护线程都终止时,JVM才会停止运行。因此这些未终止的后台线程会阻止JVM正常退出,导致脚本挂起。
解决方法
方法1:手动强制退出JVM
直接调用exitProcess(0),这是最直接的方式,会立即终止整个JVM进程,不受后台线程状态影响。
方法2:显式关闭OkHttp客户端
通过手动创建并持有OkHttpClient实例,使用完毕后关闭它,让后台线程池终止:
// 新增OkHttpClient实例创建 val okHttpClient = OkHttpClient.Builder().build() // Retrofit构建时指定自定义的OkHttpClient var retrofit: Retrofit = Retrofit.Builder() .baseUrl("https://api.github.com/") .client(okHttpClient) // 添加这一行 .addConverterFactory(GsonConverterFactory.create()) .build() // ... 原有业务代码 ... println("The repos' names: ${repoList.joinToString(", ") { it.name }} ") // 关闭OkHttpClient,终止后台线程 okHttpClient.close()
调用close()会自动关闭Dispatcher的线程池和连接池,让所有后台线程终止,JVM就能正常退出了。
内容的提问来源于stack exchange,提问作者lowellk
相关产品推荐
相关产品推荐

