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();
}