• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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);
dvmThrowException(ClassObject * exceptionClass,const char * msg)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     ;
dvmThrowExceptionFmt(ClassObject * exceptionClass,const char * fmt,...)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  */
dvmThrowExceptionWithClassMessage(ClassObject * exceptionClass,const char * messageDescriptor)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  */
dvmGetException(Thread * self)93 INLINE Object* dvmGetException(Thread* self) {
94     return self->exception;
95 }
96 
97 /*
98  * Set the exception being thrown in the current thread.
99  */
dvmSetException(Thread * self,Object * exception)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  */
dvmClearException(Thread * self)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  */
dvmCheckException(Thread * self)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 */
dvmFillInStackTrace(Thread * thread)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 */
dvmFillInStackTraceRaw(Thread * thread,size_t * pCount)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 
467 /**
468  * Throw an UnsupportedOperationException in the current thread, with
469  * the given detail message.
470  */
471 void dvmThrowUnsupportedOperationException(const char* msg);
472 
473 /**
474  * Throw a VerifyError in the current thread, with the
475  * human-readable form of the given descriptor as the detail message.
476  */
477 void dvmThrowVerifyError(const char* descriptor);
478 
479 /**
480  * Throw a VirtualMachineError in the current thread, with
481  * the given detail message.
482  */
483 void dvmThrowVirtualMachineError(const char* msg);
484 
485 #endif  // DALVIK_EXCEPTION_H_
486