我们编写了一个 Kotlin 库来处理一些网络逻辑。该库本身包含一个 AsyncTask
,它使用 java.net.*
中的 HttpURLConnection
设施。
private inner class ClickstreamTask(
headers: HashMap<String, String>,
params: Request,
success: (() -> Unit)? = null,
failure: ((statusCode: Int?, json:
HashMap<String, String>?) -> Unit)? = null) : AsyncTask<Void, Unit, Unit>() {
private var headers: HashMap<String, String> = headers
private var paramaters: Request = params
private var success: (() -> Unit)? = success
private var failure: ((statusCode: Int?, json: HashMap<String, String>?) -> Unit)? = failure
override fun doInBackground(vararg params: Void){
val url = try {
URL(getURLString() + path)
} catch (e: Exception) {
failure?.invoke(null, hashMapOf("error" to "Invalid URL."))
return Unit
}
var request = try{
url.openConnection() as HttpURLConnection
} catch (e: Exception){
failure?.invoke(null, hashMapOf("error" to "Unable to establish connection"))
return Unit
}
request.doInput = false
request.doOutput = true
val mapper = jacksonObjectMapper()
request.requestMethod = "POST"
val httpBody = try {
mapper.writeValueAsBytes(paramaters)
} catch (e: Exception) {
failure?.invoke(null, hashMapOf("error" to "Invalid params."))
return Unit
}
for ((key, value) in headers) {
request.setRequestProperty(key, value)
}
try{
request.outputStream.write(httpBody)
}catch (e: Throwable){
request.outputStream.close()
failure?.invoke(null, hashMapOf("error" to "Issue writing to URL"))
return Unit
}
request.outputStream.close()
if (request.responseCode != 200){
failure?.invoke(request.responseCode, hashMapOf("Failed request" to request.responseMessage))
return Unit
}
success?.invoke()
return Unit
}
}
当我们使用在飞行模式下运行该库的 Android 应用程序时,该应用程序会因未捕获的异常“UnknownHostException”而崩溃:
Caused by: java.net.UnknownHostException: Unable to resolve host "ste03lbclkapp00.iteclientsys.local": No address associated with hostname at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:141) at java.net.Inet6AddressImpl.lookupAllHostAddr(Inet6AddressImpl.java:90) at java.net.InetAddress.getAllByName(InetAddress.java:787) at com.android.okhttp.Dns$1.lookup(Dns.java:39) at com.android.okhttp.internal.http.RouteSelector.resetNextInetSocketAddress(RouteSelector.java:175) at com.android.okhttp.internal.http.RouteSelector.nextProxy(RouteSelector.java:141) at com.android.okhttp.internal.http.RouteSelector.next(RouteSelector.java:83) at com.android.okhttp.internal.http.StreamAllocation.findConnection(StreamAllocation.java:174) at com.android.okhttp.internal.http.StreamAllocation.findHealthyConnection(StreamAllocation.java:126) at com.android.okhttp.internal.http.StreamAllocation.newStream(StreamAllocation.java:95) at com.android.okhttp.internal.http.HttpEngine.connect(HttpEngine.java:281) at com.android.okhttp.internal.http.HttpEngine.sendRequest(HttpEngine.java:224) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:461) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:127) at com.android.okhttp.internal.huc.HttpURLConnectionImpl.getOutputStream(HttpURLConnectionImpl.java:258) at com.android.okhttp.internal.huc.DelegatingHttpsURLConnection.getOutputStream(DelegatingHttpsURLConnection.java:218) at com.android.okhttp.internal.huc.HttpsURLConnectionImpl.getOutputStream(Unknown Source:0) at com.tdameritrade.amerivest.clickstreamshared.Network.NetworkManager$ClickstreamTask.doInBackground(NetworkManager.kt:87) at com.tdameritrade.amerivest.clickstreamshared.Network.NetworkManager$ClickstreamTask.doInBackground(NetworkManager.kt:43) at android.os.AsyncTask$2.call(AsyncTask.java:333) at java.util.concurrent.FutureTask.run(FutureTask.java:266) ... 4 more Caused by: android.system.GaiException: android_getaddrinfo failed: EAI_NODATA (No address associated with hostname) at libcore.io.Linux.android_getaddrinfo(Native Method) at libcore.io.ForwardingOs.android_getaddrinfo(ForwardingOs.java:59) at java.net.Inet6AddressImpl.lookupHostByName(Inet6AddressImpl.java:122) ... 24 more
引发异常的行是request.outputStream.write(httpBody)
。但是,我们将该行包装在处理 Throwable
的 try/catch
中。
当 doOnBackground()
第 87 行包含在 catch 中时,它如何抛出异常?
最佳答案
这段代码:
try{
request.outputStream.write(httpBody)
}catch (e: Throwable){
request.outputStream.close()
failure?.invoke(null, hashMapOf("error" to "Issue writing to URL"))
return Unit
}
将尝试在 catch block 中执行操作,这也可能生成异常:
request.outputStream.close()
这是未被捕获的 - 但考虑到您在访问输出流时正在处理一些错误,这似乎也是不明智的。
异常跟踪表明了更多的原因,我猜进一步挖掘你会发现这个问题。
关于java - Android 库在捕获所有 Throwable 的 try block 内抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49984636/