异常只能抛一个,捕捉到再抛一个,也只是一个异常
看下面的代码,如果你认为执行不到(如果 if 条件满足)执行不到第2个 throwException 就错了 (Jeallybean code)
libcore/luni/src/main/native/libcore_io_Posix.cpp#throwException
146 static void throwGaiException(JNIEnv* env, const char* functionName, int error) {
147 if (errno != 0) {
148 // EAI_SYSTEM should mean "look at errno instead", but both glibc and bionic seem to
149 // mess this up. In particular, if you don't have INTERNET permission, errno will be EACCES
150 // but you'll get EAI_NONAME or EAI_NODATA. So we want our GaiException to have a
151 // potentially-relevant ErrnoException as its cause even if error != EAI_SYSTEM.
152 // http://code.google.com/p/android/issues/detail?id=15722
153 throwErrnoException(env, functionName);
154 // Deliberately fall through to throw another exception...
155 }
156 static jmethodID ctor3 = env->GetMethodID(JniConstants::gaiExceptionClass,
157 "<init>", "(Ljava/lang/String;ILjava/lang/Throwable;)V");
158 static jmethodID ctor2 = env->GetMethodID(JniConstants::gaiExceptionClass,
159 "<init>", "(Ljava/lang/String;I)V");
160 throwException(env, JniConstants::gaiExceptionClass, ctor3, ctor2, functionName, error);
161 }
因为这不是 native C++ 自己的exception,而是 native 送给 java 层的 exception
再看下面的函数,如果在有 Pending Exception 的情况下(env->ExceptionOccurred), Pending Exception 将成为当前Exception 的 cause
113 static void throwException(JNIEnv* env, jclass exceptionClass, jmethodID ctor3, jmethodID ctor2,
114 const char* functionName, int error) {
115 jthrowable cause = NULL;
116 if (env->ExceptionCheck()) {
117 cause = env->ExceptionOccurred();
118 env->ExceptionClear();
119 }
120
121 ScopedLocalRef<jstring> detailMessage(env, env->NewStringUTF(functionName));
122 if (detailMessage.get() == NULL) {
123 // Not really much we can do here. We're probably dead in the water,
124 // but let's try to stumble on...
125 env->ExceptionClear();
126 }
127
128 jobject exception;
129 if (cause != NULL) {
130 exception = env->NewObject(exceptionClass, ctor3, detailMessage.get(), error, cause);
131 } else {
132 exception = env->NewObject(exceptionClass, ctor2, detailMessage.get(), error);
133 }
134 env->Throw(reinterpret_cast<jthrowable>(exception));
135 }
再看下面
libcore/luni/src/main/java/java/net/InetAddress.java#getAllByNameImpl
417 } catch (GaiException gaiException) {
418 // If the failure appears to have been a lack of INTERNET permission, throw a clear
419 // SecurityException to aid in debugging this common mistake.
420 // http://code.google.com/p/android/issues/detail?id=15722
421 if (gaiException.getCause() instanceof ErrnoException) {
422 if (((ErrnoException) gaiException.getCause()).errno == EACCES) {
423 throw new SecurityException("Permission denied (missing INTERNET permission?)", gaiException);
424 }
425 }
426 // Otherwise, throw an UnknownHostException.
427 String detailMessage = "Unable to resolve host \"" + host + "\": " + Libcore.os.gai_strerror(gaiException.error);
428 addressCache.putUnknownHost(host, detailMessage);
429 throw gaiException.rethrowAsUnknownHostException(detailMessage);
430 }
检测到GaiException的时候,正好检查 Cause 是否是 ErrnoException