1 /*
2  * Copyright (C) 2012 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 #include "common_throws.h"
18 
19 #include <sstream>
20 
21 #include "base/logging.h"
22 #include "class_linker-inl.h"
23 #include "dex_file-inl.h"
24 #include "dex_instruction-inl.h"
25 #include "invoke_type.h"
26 #include "mirror/art_method-inl.h"
27 #include "mirror/class-inl.h"
28 #include "mirror/object-inl.h"
29 #include "mirror/object_array-inl.h"
30 #include "thread.h"
31 #include "verifier/method_verifier.h"
32 
33 namespace art {
34 
AddReferrerLocation(std::ostream & os,mirror::Class * referrer)35 static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer)
36     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
37   if (referrer != NULL) {
38     std::string location(referrer->GetLocation());
39     if (!location.empty()) {
40       os << " (declaration of '" << PrettyDescriptor(referrer)
41             << "' appears in " << location << ")";
42     }
43   }
44 }
45 
ThrowException(const ThrowLocation * throw_location,const char * exception_descriptor,mirror::Class * referrer,const char * fmt,va_list * args=NULL)46 static void ThrowException(const ThrowLocation* throw_location, const char* exception_descriptor,
47                            mirror::Class* referrer, const char* fmt, va_list* args = NULL)
48     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
49   std::ostringstream msg;
50   if (args != NULL) {
51     std::string vmsg;
52     StringAppendV(&vmsg, fmt, *args);
53     msg << vmsg;
54   } else {
55     msg << fmt;
56   }
57   AddReferrerLocation(msg, referrer);
58   Thread* self = Thread::Current();
59   if (throw_location == NULL) {
60     ThrowLocation computed_throw_location = self->GetCurrentLocationForThrow();
61     self->ThrowNewException(computed_throw_location, exception_descriptor, msg.str().c_str());
62   } else {
63     self->ThrowNewException(*throw_location, exception_descriptor, msg.str().c_str());
64   }
65 }
66 
ThrowWrappedException(const ThrowLocation * throw_location,const char * exception_descriptor,mirror::Class * referrer,const char * fmt,va_list * args=NULL)67 static void ThrowWrappedException(const ThrowLocation* throw_location,
68                                   const char* exception_descriptor,
69                                   mirror::Class* referrer, const char* fmt, va_list* args = NULL)
70     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
71   std::ostringstream msg;
72   if (args != NULL) {
73     std::string vmsg;
74     StringAppendV(&vmsg, fmt, *args);
75     msg << vmsg;
76   } else {
77     msg << fmt;
78   }
79   AddReferrerLocation(msg, referrer);
80   Thread* self = Thread::Current();
81   if (throw_location == NULL) {
82     ThrowLocation computed_throw_location = self->GetCurrentLocationForThrow();
83     self->ThrowNewWrappedException(computed_throw_location, exception_descriptor, msg.str().c_str());
84   } else {
85     self->ThrowNewWrappedException(*throw_location, exception_descriptor, msg.str().c_str());
86   }
87 }
88 
89 // AbstractMethodError
90 
ThrowAbstractMethodError(mirror::ArtMethod * method)91 void ThrowAbstractMethodError(mirror::ArtMethod* method) {
92   ThrowException(NULL, "Ljava/lang/AbstractMethodError;", NULL,
93                  StringPrintf("abstract method \"%s\"",
94                               PrettyMethod(method).c_str()).c_str());
95 }
96 
97 // ArithmeticException
98 
ThrowArithmeticExceptionDivideByZero()99 void ThrowArithmeticExceptionDivideByZero() {
100   ThrowException(NULL, "Ljava/lang/ArithmeticException;", NULL, "divide by zero");
101 }
102 
103 // ArrayIndexOutOfBoundsException
104 
ThrowArrayIndexOutOfBoundsException(int index,int length)105 void ThrowArrayIndexOutOfBoundsException(int index, int length) {
106   ThrowException(NULL, "Ljava/lang/ArrayIndexOutOfBoundsException;", NULL,
107                  StringPrintf("length=%d; index=%d", length, index).c_str());
108 }
109 
110 // ArrayStoreException
111 
ThrowArrayStoreException(mirror::Class * element_class,mirror::Class * array_class)112 void ThrowArrayStoreException(mirror::Class* element_class, mirror::Class* array_class) {
113   ThrowException(NULL, "Ljava/lang/ArrayStoreException;", NULL,
114                  StringPrintf("%s cannot be stored in an array of type %s",
115                               PrettyDescriptor(element_class).c_str(),
116                               PrettyDescriptor(array_class).c_str()).c_str());
117 }
118 
119 // ClassCastException
120 
ThrowClassCastException(mirror::Class * dest_type,mirror::Class * src_type)121 void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type) {
122   ThrowException(NULL, "Ljava/lang/ClassCastException;", NULL,
123                  StringPrintf("%s cannot be cast to %s",
124                               PrettyDescriptor(src_type).c_str(),
125                               PrettyDescriptor(dest_type).c_str()).c_str());
126 }
127 
ThrowClassCastException(const ThrowLocation * throw_location,const char * msg)128 void ThrowClassCastException(const ThrowLocation* throw_location, const char* msg) {
129   ThrowException(throw_location, "Ljava/lang/ClassCastException;", NULL, msg);
130 }
131 
132 // ClassCircularityError
133 
ThrowClassCircularityError(mirror::Class * c)134 void ThrowClassCircularityError(mirror::Class* c) {
135   std::ostringstream msg;
136   msg << PrettyDescriptor(c);
137   ThrowException(NULL, "Ljava/lang/ClassCircularityError;", c, msg.str().c_str());
138 }
139 
140 // ClassFormatError
141 
ThrowClassFormatError(mirror::Class * referrer,const char * fmt,...)142 void ThrowClassFormatError(mirror::Class* referrer, const char* fmt, ...) {
143   va_list args;
144   va_start(args, fmt);
145   ThrowException(NULL, "Ljava/lang/ClassFormatError;", referrer, fmt, &args);
146   va_end(args);}
147 
148 // IllegalAccessError
149 
ThrowIllegalAccessErrorClass(mirror::Class * referrer,mirror::Class * accessed)150 void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* accessed) {
151   std::ostringstream msg;
152   msg << "Illegal class access: '" << PrettyDescriptor(referrer) << "' attempting to access '"
153       << PrettyDescriptor(accessed) << "'";
154   ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
155 }
156 
ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class * referrer,mirror::Class * accessed,mirror::ArtMethod * called,InvokeType type)157 void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
158                                                    mirror::ArtMethod* called,
159                                                    InvokeType type) {
160   std::ostringstream msg;
161   msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '"
162       << PrettyDescriptor(accessed) << "') in attempt to invoke " << type
163       << " method " << PrettyMethod(called).c_str();
164   ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
165 }
166 
ThrowIllegalAccessErrorMethod(mirror::Class * referrer,mirror::ArtMethod * accessed)167 void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed) {
168   std::ostringstream msg;
169   msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '"
170       << PrettyDescriptor(referrer) << "'";
171   ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
172 }
173 
ThrowIllegalAccessErrorField(mirror::Class * referrer,mirror::ArtField * accessed)174 void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed) {
175   std::ostringstream msg;
176   msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '"
177       << PrettyDescriptor(referrer) << "'";
178   ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
179 }
180 
ThrowIllegalAccessErrorFinalField(mirror::ArtMethod * referrer,mirror::ArtField * accessed)181 void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer,
182                                        mirror::ArtField* accessed) {
183   std::ostringstream msg;
184   msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
185       << PrettyMethod(referrer) << "'";
186   ThrowException(NULL, "Ljava/lang/IllegalAccessError;",
187                  referrer != NULL ? referrer->GetClass() : NULL,
188                  msg.str().c_str());
189 }
190 
ThrowIllegalAccessError(mirror::Class * referrer,const char * fmt,...)191 void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) {
192   va_list args;
193   va_start(args, fmt);
194   ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, fmt, &args);
195   va_end(args);
196 }
197 
198 // IllegalAccessException
199 
ThrowIllegalAccessException(const ThrowLocation * throw_location,const char * msg)200 void ThrowIllegalAccessException(const ThrowLocation* throw_location, const char* msg) {
201   ThrowException(throw_location, "Ljava/lang/IllegalAccessException;", NULL, msg);
202 }
203 
204 // IllegalArgumentException
205 
ThrowIllegalArgumentException(const ThrowLocation * throw_location,const char * msg)206 void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const char* msg) {
207   ThrowException(throw_location, "Ljava/lang/IllegalArgumentException;", NULL, msg);
208 }
209 
210 
211 // IncompatibleClassChangeError
212 
ThrowIncompatibleClassChangeError(InvokeType expected_type,InvokeType found_type,mirror::ArtMethod * method,mirror::ArtMethod * referrer)213 void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
214                                        mirror::ArtMethod* method,
215                                        mirror::ArtMethod* referrer) {
216   std::ostringstream msg;
217   msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
218       << expected_type << " but instead was found to be of type " << found_type;
219   ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;",
220                  referrer != NULL ? referrer->GetClass() : NULL,
221                  msg.str().c_str());
222 }
223 
ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod * interface_method,mirror::Object * this_object,mirror::ArtMethod * referrer)224 void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method,
225                                                                 mirror::Object* this_object,
226                                                                 mirror::ArtMethod* referrer) {
227   // Referrer is calling interface_method on this_object, however, the interface_method isn't
228   // implemented by this_object.
229   CHECK(this_object != NULL);
230   std::ostringstream msg;
231   msg << "Class '" << PrettyDescriptor(this_object->GetClass())
232       << "' does not implement interface '"
233       << PrettyDescriptor(interface_method->GetDeclaringClass())
234       << "' in call to '" << PrettyMethod(interface_method) << "'";
235   ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;",
236                  referrer != NULL ? referrer->GetClass() : NULL,
237                  msg.str().c_str());
238 }
239 
ThrowIncompatibleClassChangeErrorField(mirror::ArtField * resolved_field,bool is_static,mirror::ArtMethod * referrer)240 void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static,
241                                             mirror::ArtMethod* referrer) {
242   std::ostringstream msg;
243   msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
244       << (is_static ? "static" : "instance") << " field" << " rather than a "
245       << (is_static ? "instance" : "static") << " field";
246   ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer->GetClass(),
247                  msg.str().c_str());
248 }
249 
ThrowIncompatibleClassChangeError(mirror::Class * referrer,const char * fmt,...)250 void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...) {
251   va_list args;
252   va_start(args, fmt);
253   ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer, fmt, &args);
254   va_end(args);
255 }
256 
257 // IOException
258 
ThrowIOException(const char * fmt,...)259 void ThrowIOException(const char* fmt, ...) {
260   va_list args;
261   va_start(args, fmt);
262   ThrowException(NULL, "Ljava/io/IOException;", NULL, fmt, &args);
263   va_end(args);
264 }
265 
ThrowWrappedIOException(const char * fmt,...)266 void ThrowWrappedIOException(const char* fmt, ...) {
267   va_list args;
268   va_start(args, fmt);
269   ThrowWrappedException(NULL, "Ljava/io/IOException;", NULL, fmt, &args);
270   va_end(args);
271 }
272 
273 // LinkageError
274 
ThrowLinkageError(mirror::Class * referrer,const char * fmt,...)275 void ThrowLinkageError(mirror::Class* referrer, const char* fmt, ...) {
276   va_list args;
277   va_start(args, fmt);
278   ThrowException(NULL, "Ljava/lang/LinkageError;", referrer, fmt, &args);
279   va_end(args);
280 }
281 
282 // NegativeArraySizeException
283 
ThrowNegativeArraySizeException(int size)284 void ThrowNegativeArraySizeException(int size) {
285   ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL,
286                  StringPrintf("%d", size).c_str());
287 }
288 
ThrowNegativeArraySizeException(const char * msg)289 void ThrowNegativeArraySizeException(const char* msg) {
290   ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL, msg);
291 }
292 
293 // NoSuchFieldError
294 
ThrowNoSuchFieldError(const StringPiece & scope,mirror::Class * c,const StringPiece & type,const StringPiece & name)295 void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
296                            const StringPiece& type, const StringPiece& name)
297     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
298   std::ostringstream msg;
299   std::string temp;
300   msg << "No " << scope << "field " << name << " of type " << type
301       << " in class " << c->GetDescriptor(&temp) << " or its superclasses";
302   ThrowException(NULL, "Ljava/lang/NoSuchFieldError;", c, msg.str().c_str());
303 }
304 
305 // NoSuchMethodError
306 
ThrowNoSuchMethodError(InvokeType type,mirror::Class * c,const StringPiece & name,const Signature & signature)307 void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
308                             const Signature& signature) {
309   std::ostringstream msg;
310   std::string temp;
311   msg << "No " << type << " method " << name << signature
312       << " in class " << c->GetDescriptor(&temp) << " or its super classes";
313   ThrowException(NULL, "Ljava/lang/NoSuchMethodError;", c, msg.str().c_str());
314 }
315 
ThrowNoSuchMethodError(uint32_t method_idx)316 void ThrowNoSuchMethodError(uint32_t method_idx) {
317   Thread* self = Thread::Current();
318   ThrowLocation throw_location = self->GetCurrentLocationForThrow();
319   mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache();
320   const DexFile& dex_file = *dex_cache->GetDexFile();
321   std::ostringstream msg;
322   msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'";
323   ThrowException(&throw_location, "Ljava/lang/NoSuchMethodError;",
324                  throw_location.GetMethod()->GetDeclaringClass(), msg.str().c_str());
325 }
326 
327 // NullPointerException
328 
ThrowNullPointerExceptionForFieldAccess(const ThrowLocation & throw_location,mirror::ArtField * field,bool is_read)329 void ThrowNullPointerExceptionForFieldAccess(const ThrowLocation& throw_location,
330                                              mirror::ArtField* field, bool is_read) {
331   std::ostringstream msg;
332   msg << "Attempt to " << (is_read ? "read from" : "write to")
333       << " field '" << PrettyField(field, true) << "' on a null object reference";
334   ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str());
335 }
336 
ThrowNullPointerExceptionForMethodAccessImpl(const ThrowLocation & throw_location,uint32_t method_idx,const DexFile & dex_file,InvokeType type)337 static void ThrowNullPointerExceptionForMethodAccessImpl(const ThrowLocation& throw_location,
338                                                          uint32_t method_idx,
339                                                          const DexFile& dex_file,
340                                                          InvokeType type)
341     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
342   std::ostringstream msg;
343   msg << "Attempt to invoke " << type << " method '"
344       << PrettyMethod(method_idx, dex_file, true) << "' on a null object reference";
345   ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str());
346 }
347 
ThrowNullPointerExceptionForMethodAccess(const ThrowLocation & throw_location,uint32_t method_idx,InvokeType type)348 void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location,
349                                               uint32_t method_idx,
350                                               InvokeType type) {
351   mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache();
352   const DexFile& dex_file = *dex_cache->GetDexFile();
353   ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method_idx,
354                                                dex_file, type);
355 }
356 
ThrowNullPointerExceptionForMethodAccess(const ThrowLocation & throw_location,mirror::ArtMethod * method,InvokeType type)357 void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location,
358                                               mirror::ArtMethod* method,
359                                               InvokeType type) {
360   mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
361   const DexFile& dex_file = *dex_cache->GetDexFile();
362   ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method->GetDexMethodIndex(),
363                                                dex_file, type);
364 }
365 
ThrowNullPointerExceptionFromDexPC(const ThrowLocation & throw_location)366 void ThrowNullPointerExceptionFromDexPC(const ThrowLocation& throw_location) {
367   const DexFile::CodeItem* code = throw_location.GetMethod()->GetCodeItem();
368   uint32_t throw_dex_pc = throw_location.GetDexPc();
369   CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_);
370   const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]);
371   switch (instr->Opcode()) {
372     case Instruction::INVOKE_DIRECT:
373       ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kDirect);
374       break;
375     case Instruction::INVOKE_DIRECT_RANGE:
376       ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kDirect);
377       break;
378     case Instruction::INVOKE_VIRTUAL:
379       ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kVirtual);
380       break;
381     case Instruction::INVOKE_VIRTUAL_RANGE:
382       ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kVirtual);
383       break;
384     case Instruction::INVOKE_INTERFACE:
385       ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kInterface);
386       break;
387     case Instruction::INVOKE_INTERFACE_RANGE:
388       ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kInterface);
389       break;
390     case Instruction::INVOKE_VIRTUAL_QUICK:
391     case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
392       // Since we replaced the method index, we ask the verifier to tell us which
393       // method is invoked at this location.
394       mirror::ArtMethod* method =
395           verifier::MethodVerifier::FindInvokedMethodAtDexPc(throw_location.GetMethod(),
396                                                              throw_location.GetDexPc());
397       if (method != NULL) {
398         // NPE with precise message.
399         ThrowNullPointerExceptionForMethodAccess(throw_location, method, kVirtual);
400       } else {
401         // NPE with imprecise message.
402         ThrowNullPointerException(&throw_location,
403                                   "Attempt to invoke a virtual method on a null object reference");
404       }
405       break;
406     }
407     case Instruction::IGET:
408     case Instruction::IGET_WIDE:
409     case Instruction::IGET_OBJECT:
410     case Instruction::IGET_BOOLEAN:
411     case Instruction::IGET_BYTE:
412     case Instruction::IGET_CHAR:
413     case Instruction::IGET_SHORT: {
414       mirror::ArtField* field =
415           Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(),
416                                                              throw_location.GetMethod(), false);
417       ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */);
418       break;
419     }
420     case Instruction::IGET_QUICK:
421     case Instruction::IGET_WIDE_QUICK:
422     case Instruction::IGET_OBJECT_QUICK: {
423       // Since we replaced the field index, we ask the verifier to tell us which
424       // field is accessed at this location.
425       mirror::ArtField* field =
426           verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(),
427                                                              throw_location.GetDexPc());
428       if (field != NULL) {
429         // NPE with precise message.
430         ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */);
431       } else {
432         // NPE with imprecise message.
433         ThrowNullPointerException(&throw_location,
434                                   "Attempt to read from a field on a null object reference");
435       }
436       break;
437     }
438     case Instruction::IPUT:
439     case Instruction::IPUT_WIDE:
440     case Instruction::IPUT_OBJECT:
441     case Instruction::IPUT_BOOLEAN:
442     case Instruction::IPUT_BYTE:
443     case Instruction::IPUT_CHAR:
444     case Instruction::IPUT_SHORT: {
445       mirror::ArtField* field =
446           Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(),
447                                                              throw_location.GetMethod(), false);
448       ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */);
449       break;
450     }
451     case Instruction::IPUT_QUICK:
452     case Instruction::IPUT_WIDE_QUICK:
453     case Instruction::IPUT_OBJECT_QUICK: {
454       // Since we replaced the field index, we ask the verifier to tell us which
455       // field is accessed at this location.
456       mirror::ArtField* field =
457           verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(),
458                                                              throw_location.GetDexPc());
459       if (field != NULL) {
460         // NPE with precise message.
461         ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */);
462       } else {
463         // NPE with imprecise message.
464         ThrowNullPointerException(&throw_location,
465                                   "Attempt to write to a field on a null object reference");
466       }
467       break;
468     }
469     case Instruction::AGET:
470     case Instruction::AGET_WIDE:
471     case Instruction::AGET_OBJECT:
472     case Instruction::AGET_BOOLEAN:
473     case Instruction::AGET_BYTE:
474     case Instruction::AGET_CHAR:
475     case Instruction::AGET_SHORT:
476       ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
477                      "Attempt to read from null array");
478       break;
479     case Instruction::APUT:
480     case Instruction::APUT_WIDE:
481     case Instruction::APUT_OBJECT:
482     case Instruction::APUT_BOOLEAN:
483     case Instruction::APUT_BYTE:
484     case Instruction::APUT_CHAR:
485     case Instruction::APUT_SHORT:
486       ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
487                      "Attempt to write to null array");
488       break;
489     case Instruction::ARRAY_LENGTH:
490       ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
491                      "Attempt to get length of null array");
492       break;
493     default: {
494       // TODO: We should have covered all the cases where we expect a NPE above, this
495       //       message/logging is so we can improve any cases we've missed in the future.
496       const DexFile& dex_file =
497           *throw_location.GetMethod()->GetDeclaringClass()->GetDexCache()->GetDexFile();
498       ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL,
499                      StringPrintf("Null pointer exception during instruction '%s'",
500                                   instr->DumpString(&dex_file).c_str()).c_str());
501       break;
502     }
503   }
504 }
505 
ThrowNullPointerException(const ThrowLocation * throw_location,const char * msg)506 void ThrowNullPointerException(const ThrowLocation* throw_location, const char* msg) {
507   ThrowException(throw_location, "Ljava/lang/NullPointerException;", NULL, msg);
508 }
509 
510 // RuntimeException
511 
ThrowRuntimeException(const char * fmt,...)512 void ThrowRuntimeException(const char* fmt, ...) {
513   va_list args;
514   va_start(args, fmt);
515   ThrowException(NULL, "Ljava/lang/RuntimeException;", NULL, fmt, &args);
516   va_end(args);
517 }
518 
519 // VerifyError
520 
ThrowVerifyError(mirror::Class * referrer,const char * fmt,...)521 void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) {
522   va_list args;
523   va_start(args, fmt);
524   ThrowException(NULL, "Ljava/lang/VerifyError;", referrer, fmt, &args);
525   va_end(args);
526 }
527 
528 }  // namespace art
529