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