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