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 */ 41void dvmThrowChainedException(ClassObject* exceptionClass, 42 const char* msg, Object* cause); 43INLINE 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 */ 52void dvmThrowExceptionFmtV(ClassObject* exceptionClass, 53 const char* fmt, va_list args); 54void dvmThrowExceptionFmt(ClassObject* exceptionClass, 55 const char* fmt, ...) 56#if defined(__GNUC__) 57 __attribute__ ((format(printf, 2, 3))) 58#endif 59 ; 60INLINE 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 */ 74void 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 */ 82INLINE 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 */ 93INLINE Object* dvmGetException(Thread* self) { 94 return self->exception; 95} 96 97/* 98 * Set the exception being thrown in the current thread. 99 */ 100INLINE 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 */ 113INLINE 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 */ 122void dvmClearOptException(Thread* self); 123 124/* 125 * Returns "true" if an exception is pending. Use this if you have a 126 * "self" pointer. 127 */ 128INLINE 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 */ 136bool 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 */ 144void 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 */ 151Object* dvmGetExceptionCause(const Object* exception); 152 153/* 154 * Print the exception stack trace on stderr. Calls the exception's 155 * print function. 156 */ 157void 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 */ 163void 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 */ 176extern "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 */ 187void* dvmFillInStackTraceInternal(Thread* thread, bool wantObject, size_t* pCount); 188/* return an [I for use by interpreted code */ 189INLINE Object* dvmFillInStackTrace(Thread* thread) { 190 return (Object*) dvmFillInStackTraceInternal(thread, true, NULL); 191} 192ArrayObject* dvmGetStackTrace(const Object* stackState); 193/* return an int* and array count; caller must free() the return value */ 194INLINE int* dvmFillInStackTraceRaw(Thread* thread, size_t* pCount) { 195 return (int*) dvmFillInStackTraceInternal(thread, false, pCount); 196} 197ArrayObject* dvmGetStackTraceRaw(const int* intVals, size_t stackDepth); 198void 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 */ 203void dvmLogRawStackTrace(const int* intVals, int stackDepth); 204 205/** 206 * Throw an AbstractMethodError in the current thread, with the given detail 207 * message. 208 */ 209void dvmThrowAbstractMethodError(const char* msg); 210 211/** 212 * Throw an ArithmeticException in the current thread, with the given detail 213 * message. 214 */ 215extern "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 */ 221extern "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 */ 228extern "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 */ 235void 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 */ 242void 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 */ 250void 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 */ 257extern "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 */ 263void dvmThrowClassCircularityError(const char* descriptor); 264 265/** 266 * Throw a ClassFormatError in the current thread, with the given 267 * detail message. 268 */ 269void 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 */ 275void 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 */ 281void 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 */ 288void dvmThrowExceptionInInitializerError(void); 289 290/** 291 * Throw a FileNotFoundException in the current thread, with the given 292 * detail message. 293 */ 294void dvmThrowFileNotFoundException(const char* msg); 295 296/** 297 * Throw an IOException in the current thread, with the given 298 * detail message. 299 */ 300void dvmThrowIOException(const char* msg); 301 302/** 303 * Throw an IllegalAccessError in the current thread, with the 304 * given detail message. 305 */ 306void dvmThrowIllegalAccessError(const char* msg); 307 308/** 309 * Throw an IllegalAccessException in the current thread, with the 310 * given detail message. 311 */ 312void dvmThrowIllegalAccessException(const char* msg); 313 314/** 315 * Throw an IllegalArgumentException in the current thread, with the 316 * given detail message. 317 */ 318void dvmThrowIllegalArgumentException(const char* msg); 319 320/** 321 * Throw an IllegalMonitorStateException in the current thread, with 322 * the given detail message. 323 */ 324void dvmThrowIllegalMonitorStateException(const char* msg); 325 326/** 327 * Throw an IllegalStateException in the current thread, with 328 * the given detail message. 329 */ 330void dvmThrowIllegalStateException(const char* msg); 331 332/** 333 * Throw an IllegalThreadStateException in the current thread, with 334 * the given detail message. 335 */ 336void dvmThrowIllegalThreadStateException(const char* msg); 337 338/** 339 * Throw an IncompatibleClassChangeError in the current thread, 340 * the given detail message. 341 */ 342void 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 */ 348void 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 */ 356void dvmThrowInstantiationException(ClassObject* clazz, 357 const char* extraDetail); 358 359/** 360 * Throw an InternalError in the current thread, with the given 361 * detail message. 362 */ 363extern "C" void dvmThrowInternalError(const char* msg); 364 365/** 366 * Throw an InterruptedException in the current thread, with the given 367 * detail message. 368 */ 369void dvmThrowInterruptedException(const char* msg); 370 371/** 372 * Throw a LinkageError in the current thread, with the 373 * given detail message. 374 */ 375void dvmThrowLinkageError(const char* msg); 376 377/** 378 * Throw a NegativeArraySizeException in the current thread, with the 379 * given number as the detail message. 380 */ 381extern "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 */ 387extern "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 */ 394void dvmThrowChainedNoClassDefFoundError(const char* descriptor, 395 Object* cause); 396 397/** 398 * Throw a NoSuchFieldError in the current thread, with the given 399 * detail message. 400 */ 401extern "C" void dvmThrowNoSuchFieldError(const char* msg); 402 403/** 404 * Throw a NoSuchFieldException in the current thread, with the given 405 * detail message. 406 */ 407void dvmThrowNoSuchFieldException(const char* msg); 408 409/** 410 * Throw a NoSuchMethodError in the current thread, with the given 411 * detail message. 412 */ 413extern "C" void dvmThrowNoSuchMethodError(const char* msg); 414 415/** 416 * Throw a NullPointerException in the current thread, with the given 417 * detail message. 418 */ 419extern "C" void dvmThrowNullPointerException(const char* msg); 420 421/** 422 * Throw an OutOfMemoryError in the current thread, with the given 423 * detail message. 424 */ 425void dvmThrowOutOfMemoryError(const char* msg); 426 427/** 428 * Throw a RuntimeException in the current thread, with the given detail 429 * message. 430 */ 431void dvmThrowRuntimeException(const char* msg); 432 433/** 434 * Throw a StaleDexCacheError in the current thread, with 435 * the given detail message. 436 */ 437void 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 */ 444void 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 */ 452void 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 */ 459void dvmThrowTypeNotPresentException(const char* descriptor); 460 461/** 462 * Throw an UnsatisfiedLinkError in the current thread, with 463 * the given detail message. 464 */ 465void dvmThrowUnsatisfiedLinkError(const char* msg); 466void dvmThrowUnsatisfiedLinkError(const char* msg, const Method* method); 467 468/** 469 * Throw an UnsupportedOperationException in the current thread, with 470 * the given detail message. 471 */ 472void 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 */ 478void dvmThrowVerifyError(const char* descriptor); 479 480/** 481 * Throw a VirtualMachineError in the current thread, with 482 * the given detail message. 483 */ 484void dvmThrowVirtualMachineError(const char* msg); 485 486#endif // DALVIK_EXCEPTION_H_ 487