Home | History | Annotate | Download | only in vm
      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