Android OS如何识别主线程上的网络调用并引发NetworkOnMainThreadException

时间:2018-07-11 09:27:29

标签: android android-source networkonmainthread

我正在尝试查找AOSP源代码中负责保护在主线程上进行网络调用并因此抛出NetworkOnMainThreadException的部分,但是到目前为止,我失败了。

那么Android如何识别主线程上的网络调用?它是否检查操作系统的某些网络组件(可能发生在硬件层?)?

感谢 Michael Dodd 的答案,我发现了引发异常的地方(您可以通过this search找到异常)。现在的问题是谁和何时调用android.os.StrictMode.onNetwork()方法。

2 个答案:

答案 0 :(得分:2)

感谢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.app.ActivityThread.java中的PENALTY_DEATH_ON_NETWORK设置android.os.StrictMode.enableDeathOnNetwork()

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

答案 1 :(得分:0)

感谢Anton A.作为初始指针,负责抛出NetworkOnMainThreadException的代码段位于StrictMode.java内的frameworks/base/core/java/android/os

这是有问题的功能。据我所知,至少从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);
}