Android OS 如何识别主线程上的网络调用并抛出 NetworkOnMainThreadException
How Android OS recognizes network calls on main thread and throws NetworkOnMainThreadException
我试图找到 AOSP 的源代码中负责保护在主线程上进行网络调用并因此抛出 NetworkOnMainThreadException
的部分,但到目前为止我失败了.
那么Android如何识别主线程上的网络调用?它是否检查[=26]的某些网络组件(可能发生在硬件层?) =]被感动了?
感谢Michael Dodd的回答我找到了抛出异常的地方(你可以通过this search找到它)。现在的问题是谁以及何时调用 android.os.StrictMode.onNetwork()
方法。
由于 Anton A. 作为初始指针,负责抛出 NetworkOnMainThreadException
的代码部分是 StrictMode.java
,位于 frameworks/base/core/java/android/os
.[=15= 中]
这是有问题的函数。据我所知,这至少从 Android 4.3.
开始就保持不变
// Part of BlockGuard.Policy interface:
public void onNetwork() {
if ((mPolicyMask & DETECT_NETWORK) == 0) {
return;
}
if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
throw new NetworkOnMainThreadException();
}
if (tooManyViolationsThisLoop()) {
return;
}
BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
e.fillInStackTrace();
startHandlingViolationException(e);
}
感谢 Michael Dodd 的回答,我找到了它的工作原理,例如for Android 8 有:
/**
* Resolves a hostname to its IP addresses using a cache.
*
* @param host the hostname to resolve.
* @param netId the network to perform resolution upon.
* @return the IP addresses of the host.
*/
private static InetAddress[] lookupHostByName(String host, int netId)
throws UnknownHostException {
BlockGuard.getThreadPolicy().onNetwork();
// ...
}
并且(感谢 Michael Dodd)在 android.os.StrictMode 中您可以找到:
// Part of BlockGuard.Policy interface:
public void onNetwork() {
if ((mPolicyMask & DETECT_NETWORK) == 0) {
return;
}
if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
throw new NetworkOnMainThreadException();
}
if (tooManyViolationsThisLoop()) {
return;
}
BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
e.fillInStackTrace();
startHandlingViolationException(e);
}
mPolicyMask
通过 android.os.StrictMode.enableDeathOnNetwork()
从 android.app.ActivityThread.java 设置 PENALTY_DEATH_ON_NETWORK
:
/**
* For apps targetting Honeycomb or later, we don't allow network usage
* on the main event loop / UI thread. This is what ultimately throws
* {@link NetworkOnMainThreadException}.
*/
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
StrictMode.enableDeathOnNetwork();
}
我试图找到 AOSP 的源代码中负责保护在主线程上进行网络调用并因此抛出 NetworkOnMainThreadException
的部分,但到目前为止我失败了.
那么Android如何识别主线程上的网络调用?它是否检查[=26]的某些网络组件(可能发生在硬件层?) =]被感动了?
感谢Michael Dodd的回答我找到了抛出异常的地方(你可以通过this search找到它)。现在的问题是谁以及何时调用 android.os.StrictMode.onNetwork()
方法。
由于 Anton A. 作为初始指针,负责抛出 NetworkOnMainThreadException
的代码部分是 StrictMode.java
,位于 frameworks/base/core/java/android/os
.[=15= 中]
这是有问题的函数。据我所知,这至少从 Android 4.3.
开始就保持不变// Part of BlockGuard.Policy interface:
public void onNetwork() {
if ((mPolicyMask & DETECT_NETWORK) == 0) {
return;
}
if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
throw new NetworkOnMainThreadException();
}
if (tooManyViolationsThisLoop()) {
return;
}
BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
e.fillInStackTrace();
startHandlingViolationException(e);
}
感谢 Michael Dodd 的回答,我找到了它的工作原理,例如for Android 8 有:
/**
* Resolves a hostname to its IP addresses using a cache.
*
* @param host the hostname to resolve.
* @param netId the network to perform resolution upon.
* @return the IP addresses of the host.
*/
private static InetAddress[] lookupHostByName(String host, int netId)
throws UnknownHostException {
BlockGuard.getThreadPolicy().onNetwork();
// ...
}
并且(感谢 Michael Dodd)在 android.os.StrictMode 中您可以找到:
// Part of BlockGuard.Policy interface:
public void onNetwork() {
if ((mPolicyMask & DETECT_NETWORK) == 0) {
return;
}
if ((mPolicyMask & PENALTY_DEATH_ON_NETWORK) != 0) {
throw new NetworkOnMainThreadException();
}
if (tooManyViolationsThisLoop()) {
return;
}
BlockGuard.BlockGuardPolicyException e = new StrictModeNetworkViolation(mPolicyMask);
e.fillInStackTrace();
startHandlingViolationException(e);
}
mPolicyMask
通过 android.os.StrictMode.enableDeathOnNetwork()
从 android.app.ActivityThread.java 设置 PENALTY_DEATH_ON_NETWORK
:
/**
* For apps targetting Honeycomb or later, we don't allow network usage
* on the main event loop / UI thread. This is what ultimately throws
* {@link NetworkOnMainThreadException}.
*/
if (data.appInfo.targetSdkVersion >= Build.VERSION_CODES.HONEYCOMB) {
StrictMode.enableDeathOnNetwork();
}