1 /* 2 * Copyright (C) 2008 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 /* 18 * Exception handling. 19 */ 20 #ifndef DALVIK_EXCEPTION_H_ 21 #define DALVIK_EXCEPTION_H_ 22 23 /* 24 * Create a Throwable and throw an exception in the current thread (where 25 * "throwing" just means "set the thread's exception pointer"). 26 * 27 * "msg" and/or "cause" may be NULL. 28 * 29 * If we have a bad exception hierarchy -- something in Throwable.<init> 30 * is missing -- then every attempt to throw an exception will result 31 * in another exception. Exceptions are generally allowed to "chain" 32 * to other exceptions, so it's hard to auto-detect this problem. It can 33 * only happen if the system classes are broken, so it's probably not 34 * worth spending cycles to detect it. 35 * 36 * We do have one case to worry about: if the classpath is completely 37 * wrong, we'll go into a death spin during startup because we can't find 38 * the initial class and then we can't find NoClassDefFoundError. We have 39 * to handle this case. 40 */ 41 void dvmThrowChainedException(ClassObject* exceptionClass, 42 const char* msg, Object* cause); 43 INLINE void dvmThrowException(ClassObject* exceptionClass, 44 const char* msg) 45 { 46 dvmThrowChainedException(exceptionClass, msg, NULL); 47 } 48 49 /* 50 * Like dvmThrowException, but takes printf-style args for the message. 51 */ 52 void dvmThrowExceptionFmtV(ClassObject* exceptionClass, 53 const char* fmt, va_list args); 54 void dvmThrowExceptionFmt(ClassObject* exceptionClass, 55 const char* fmt, ...) 56 #if defined(__GNUC__) 57 __attribute__ ((format(printf, 2, 3))) 58 #endif 59 ; 60 INLINE void dvmThrowExceptionFmt(ClassObject* exceptionClass, 61 const char* fmt, ...) 62 { 63 va_list args; 64 va_start(args, fmt); 65 dvmThrowExceptionFmtV(exceptionClass, fmt, args); 66 va_end(args); 67 } 68 69 /* 70 * Like dvmThrowChainedException, but take a class object 71 * instead of a name and turn the given message into the 72 * human-readable form for a descriptor. 73 */ 74 void dvmThrowChainedExceptionWithClassMessage( 75 ClassObject* exceptionClass, const char* messageDescriptor, 76 Object* cause); 77 78 /* 79 * Like dvmThrowException, but take a class object instead of a name 80 * and turn the given message into the human-readable form for a descriptor. 81 */ 82 INLINE void dvmThrowExceptionWithClassMessage( 83 ClassObject* exceptionClass, const char* messageDescriptor) 84 { 85 dvmThrowChainedExceptionWithClassMessage(exceptionClass, 86 messageDescriptor, NULL); 87 } 88 89 /* 90 * Return the exception being thrown in the current thread, or NULL if 91 * no exception is pending. 92 */ 93 INLINE Object* dvmGetException(Thread* self) { 94 return self->exception; 95 } 96 97 /* 98 * Set the exception being thrown in the current thread. 99 */ 100 INLINE void dvmSetException(Thread* self, Object* exception) 101 { 102 assert(exception != NULL); 103 self->exception = exception; 104 } 105 106 /* 107 * Clear the pending exception. 108 * 109 * (We use this rather than "set(null)" because we may need to have special 110 * fixups here for StackOverflowError stuff. Calling "clear" in the code 111 * makes it obvious.) 112 */ 113 INLINE void dvmClearException(Thread* self) { 114 self->exception = NULL; 115 } 116 117 /* 118 * Clear the pending exception. Used by the optimization and verification 119 * code, which has to run with "initializing" set to avoid going into a 120 * death-spin if the "class not found" exception can't be found. 121 */ 122 void dvmClearOptException(Thread* self); 123 124 /* 125 * Returns "true" if an exception is pending. Use this if you have a 126 * "self" pointer. 127 */ 128 INLINE bool dvmCheckException(Thread* self) { 129 return (self->exception != NULL); 130 } 131 132 /* 133 * Returns "true" if this is a "checked" exception, i.e. it's a subclass 134 * of Throwable (assumed) but not a subclass of RuntimeException or Error. 135 */ 136 bool dvmIsCheckedException(const Object* exception); 137 138 /* 139 * Wrap the now-pending exception in a different exception. 140 * 141 * If something fails, an (unchecked) exception related to that failure 142 * will be pending instead. 143 */ 144 void dvmWrapException(const char* newExcepStr); 145 146 /* 147 * Get the "cause" field from an exception. 148 * 149 * Returns NULL if the field is null or uninitialized. 150 */ 151 Object* dvmGetExceptionCause(const Object* exception); 152 153 /* 154 * Print the exception stack trace on stderr. Calls the exception's 155 * print function. 156 */ 157 void dvmPrintExceptionStackTrace(void); 158 159 /* 160 * Print the exception stack trace to the log file. The exception stack 161 * trace is computed within the VM. 162 */ 163 void dvmLogExceptionStackTrace(void); 164 165 /* 166 * Search for a catch block that matches "exception". 167 * 168 * "*newFrame" gets a copy of the new frame pointer. 169 * 170 * If "doUnroll" is set, we unroll "thread"s stack as we go (and update 171 * self->interpSave.curFrame with the same value as in *newFrame). 172 * 173 * Returns the offset to the catch code on success, or -1 if we couldn't 174 * find a catcher. 175 */ 176 extern "C" int dvmFindCatchBlock(Thread* self, int relPc, Object* exception, 177 bool doUnroll, void** newFrame); 178 179 /* 180 * Support for saving exception stack traces and converting them to 181 * usable form. Use the "FillIn" function to generate a compact array 182 * that represents the stack frames, then "GetStackTrace" to convert it 183 * to an array of StackTraceElement objects. 184 * 185 * Don't call the "Internal" form of the function directly. 186 */ 187 void* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, size_t* pCount); 188 /* return an [I for use by interpreted code */ 189 INLINE Object* dvmFillInStackTrace(Thread* thread) { 190 return (Object*) dvmFillInStackTraceInternal(thread, true, NULL); 191 } 192 ArrayObject* dvmGetStackTrace(const Object* stackState); 193 /* return an int* and array count; caller must free() the return value */ 194 INLINE int* dvmFillInStackTraceRaw(Thread* thread, size_t* pCount) { 195 return (int*) dvmFillInStackTraceInternal(thread, false, pCount); 196 } 197 ArrayObject* dvmGetStackTraceRaw(const int* intVals, size_t stackDepth); 198 void dvmFillStackTraceElements(const int* intVals, size_t stackDepth, ArrayObject* steArray); 199 200 /* 201 * Print a formatted version of a raw stack trace to the log file. 202 */ 203 void dvmLogRawStackTrace(const int* intVals, int stackDepth); 204 205 /** 206 * Throw an AbstractMethodError in the current thread, with the given detail 207 * message. 208 */ 209 void dvmThrowAbstractMethodError(const char* msg); 210 211 /** 212 * Throw an ArithmeticException in the current thread, with the given detail 213 * message. 214 */ 215 extern "C" void dvmThrowArithmeticException(const char* msg); 216 217 /* 218 * Throw an ArrayIndexOutOfBoundsException in the current thread, 219 * using the given array length and index in the detail message. 220 */ 221 extern "C" void dvmThrowArrayIndexOutOfBoundsException(int length, int index); 222 223 /* 224 * Throw an ArrayStoreException in the current thread, using the given classes' 225 * names in the detail message, indicating that an object of the given type 226 * can't be stored into an array of the given type. 227 */ 228 extern "C" void dvmThrowArrayStoreExceptionIncompatibleElement(ClassObject* objectType, ClassObject* arrayType); 229 230 /* 231 * Throw an ArrayStoreException in the current thread, using the given 232 * class name and argument label in the detail message, indicating 233 * that it is not an array. 234 */ 235 void dvmThrowArrayStoreExceptionNotArray(ClassObject* actual, const char* label); 236 237 /* 238 * Throw an ArrayStoreException in the current thread, using the given 239 * classes' names in the detail message, indicating that the arrays 240 * aren't compatible (for copying contents). 241 */ 242 void dvmThrowArrayStoreExceptionIncompatibleArrays(ClassObject* source, ClassObject* destination); 243 244 /* 245 * Throw an ArrayStoreException in the current thread, using the given 246 * index and classes' names in the detail message, indicating that the 247 * object at the given index and of the given type cannot be stored 248 * into an array of the given type. 249 */ 250 void dvmThrowArrayStoreExceptionIncompatibleArrayElement(s4 index, ClassObject* objectType, 251 ClassObject* arrayType); 252 253 /** 254 * Throw a ClassCastException in the current thread, using the given classes' 255 * names in the detail message. 256 */ 257 extern "C" void dvmThrowClassCastException(ClassObject* actual, ClassObject* desired); 258 259 /** 260 * Throw a ClassCircularityError in the current thread, with the 261 * human-readable form of the given descriptor as the detail message. 262 */ 263 void dvmThrowClassCircularityError(const char* descriptor); 264 265 /** 266 * Throw a ClassFormatError in the current thread, with the given 267 * detail message. 268 */ 269 void dvmThrowClassFormatError(const char* msg); 270 271 /** 272 * Throw a ClassNotFoundException in the current thread, with the given 273 * class name as the detail message. 274 */ 275 void dvmThrowClassNotFoundException(const char* name); 276 277 /** 278 * Throw a ClassNotFoundException in the current thread, with the given 279 * cause, and the given class name as the detail message. 280 */ 281 void dvmThrowChainedClassNotFoundException(const char* name, Object* cause); 282 283 /* 284 * Throw the VM-spec-mandated error when an exception is thrown during 285 * class initialization. Unlike other helper functions, this automatically 286 * wraps the current thread's pending exception. 287 */ 288 void dvmThrowExceptionInInitializerError(void); 289 290 /** 291 * Throw a FileNotFoundException in the current thread, with the given 292 * detail message. 293 */ 294 void dvmThrowFileNotFoundException(const char* msg); 295 296 /** 297 * Throw an IOException in the current thread, with the given 298 * detail message. 299 */ 300 void dvmThrowIOException(const char* msg); 301 302 /** 303 * Throw an IllegalAccessError in the current thread, with the 304 * given detail message. 305 */ 306 void dvmThrowIllegalAccessError(const char* msg); 307 308 /** 309 * Throw an IllegalAccessException in the current thread, with the 310 * given detail message. 311 */ 312 void dvmThrowIllegalAccessException(const char* msg); 313 314 /** 315 * Throw an IllegalArgumentException in the current thread, with the 316 * given detail message. 317 */ 318 void dvmThrowIllegalArgumentException(const char* msg); 319 320 /** 321 * Throw an IllegalMonitorStateException in the current thread, with 322 * the given detail message. 323 */ 324 void dvmThrowIllegalMonitorStateException(const char* msg); 325 326 /** 327 * Throw an IllegalStateException in the current thread, with 328 * the given detail message. 329 */ 330 void dvmThrowIllegalStateException(const char* msg); 331 332 /** 333 * Throw an IllegalThreadStateException in the current thread, with 334 * the given detail message. 335 */ 336 void dvmThrowIllegalThreadStateException(const char* msg); 337 338 /** 339 * Throw an IncompatibleClassChangeError in the current thread, 340 * the given detail message. 341 */ 342 void dvmThrowIncompatibleClassChangeError(const char* msg); 343 344 /** 345 * Throw an IncompatibleClassChangeError in the current thread, with the 346 * human-readable form of the given descriptor as the detail message. 347 */ 348 void dvmThrowIncompatibleClassChangeErrorWithClassMessage( 349 const char* descriptor); 350 351 /** 352 * Throw an InstantiationException in the current thread, with 353 * the human-readable form of the given class as the detail message, 354 * with optional extra detail appended to the message. 355 */ 356 void dvmThrowInstantiationException(ClassObject* clazz, 357 const char* extraDetail); 358 359 /** 360 * Throw an InternalError in the current thread, with the given 361 * detail message. 362 */ 363 extern "C" void dvmThrowInternalError(const char* msg); 364 365 /** 366 * Throw an InterruptedException in the current thread, with the given 367 * detail message. 368 */ 369 void dvmThrowInterruptedException(const char* msg); 370 371 /** 372 * Throw a LinkageError in the current thread, with the 373 * given detail message. 374 */ 375 void dvmThrowLinkageError(const char* msg); 376 377 /** 378 * Throw a NegativeArraySizeException in the current thread, with the 379 * given number as the detail message. 380 */ 381 extern "C" void dvmThrowNegativeArraySizeException(s4 size); 382 383 /** 384 * Throw a NoClassDefFoundError in the current thread, with the 385 * human-readable form of the given descriptor as the detail message. 386 */ 387 extern "C" void dvmThrowNoClassDefFoundError(const char* descriptor); 388 389 /** 390 * Throw a NoClassDefFoundError in the current thread, with the given 391 * cause, and the human-readable form of the given descriptor as the 392 * detail message. 393 */ 394 void dvmThrowChainedNoClassDefFoundError(const char* descriptor, 395 Object* cause); 396 397 /** 398 * Throw a NoSuchFieldError in the current thread, with the given 399 * detail message. 400 */ 401 extern "C" void dvmThrowNoSuchFieldError(const char* msg); 402 403 /** 404 * Throw a NoSuchFieldException in the current thread, with the given 405 * detail message. 406 */ 407 void dvmThrowNoSuchFieldException(const char* msg); 408 409 /** 410 * Throw a NoSuchMethodError in the current thread, with the given 411 * detail message. 412 */ 413 extern "C" void dvmThrowNoSuchMethodError(const char* msg); 414 415 /** 416 * Throw a NullPointerException in the current thread, with the given 417 * detail message. 418 */ 419 extern "C" void dvmThrowNullPointerException(const char* msg); 420 421 /** 422 * Throw an OutOfMemoryError in the current thread, with the given 423 * detail message. 424 */ 425 void dvmThrowOutOfMemoryError(const char* msg); 426 427 /** 428 * Throw a RuntimeException in the current thread, with the given detail 429 * message. 430 */ 431 void dvmThrowRuntimeException(const char* msg); 432 433 /** 434 * Throw a StaleDexCacheError in the current thread, with 435 * the given detail message. 436 */ 437 void dvmThrowStaleDexCacheError(const char* msg); 438 439 /** 440 * Throw a StringIndexOutOfBoundsException in the current thread, with 441 * a detail message specifying an actual length as well as a requested 442 * index. 443 */ 444 void dvmThrowStringIndexOutOfBoundsExceptionWithIndex(jsize stringLength, 445 jsize requestIndex); 446 447 /** 448 * Throw a StringIndexOutOfBoundsException in the current thread, with 449 * a detail message specifying an actual length as well as a requested 450 * region. 451 */ 452 void dvmThrowStringIndexOutOfBoundsExceptionWithRegion(jsize stringLength, 453 jsize requestStart, jsize requestLength); 454 455 /** 456 * Throw a TypeNotPresentException in the current thread, with the 457 * human-readable form of the given descriptor as the detail message. 458 */ 459 void dvmThrowTypeNotPresentException(const char* descriptor); 460 461 /** 462 * Throw an UnsatisfiedLinkError in the current thread, with 463 * the given detail message. 464 */ 465 void dvmThrowUnsatisfiedLinkError(const char* msg); 466 void dvmThrowUnsatisfiedLinkError(const char* msg, const Method* method); 467 468 /** 469 * Throw an UnsupportedOperationException in the current thread, with 470 * the given detail message. 471 */ 472 void dvmThrowUnsupportedOperationException(const char* msg); 473 474 /** 475 * Throw a VerifyError in the current thread, with the 476 * human-readable form of the given descriptor as the detail message. 477 */ 478 void dvmThrowVerifyError(const char* descriptor); 479 480 /** 481 * Throw a VirtualMachineError in the current thread, with 482 * the given detail message. 483 */ 484 void dvmThrowVirtualMachineError(const char* msg); 485 486 #endif // DALVIK_EXCEPTION_H_ 487