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