• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 "ScopedLocalRef.h"
22 
23 #include "art_field-inl.h"
24 #include "art_method-inl.h"
25 #include "base/logging.h"
26 #include "class_linker-inl.h"
27 #include "dex_file-inl.h"
28 #include "dex_instruction-inl.h"
29 #include "invoke_type.h"
30 #include "mirror/class-inl.h"
31 #include "mirror/object-inl.h"
32 #include "mirror/object_array-inl.h"
33 #include "thread.h"
34 #include "verifier/method_verifier.h"
35 
36 namespace art {
37 
AddReferrerLocation(std::ostream & os,mirror::Class * referrer)38 static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer)
39     SHARED_REQUIRES(Locks::mutator_lock_) {
40   if (referrer != nullptr) {
41     std::string location(referrer->GetLocation());
42     if (!location.empty()) {
43       os << " (declaration of '" << PrettyDescriptor(referrer)
44             << "' appears in " << location << ")";
45     }
46   }
47 }
48 
ThrowException(const char * exception_descriptor,mirror::Class * referrer,const char * fmt,va_list * args=nullptr)49 static void ThrowException(const char* exception_descriptor,
50                            mirror::Class* referrer, const char* fmt, va_list* args = nullptr)
51     SHARED_REQUIRES(Locks::mutator_lock_) {
52   std::ostringstream msg;
53   if (args != nullptr) {
54     std::string vmsg;
55     StringAppendV(&vmsg, fmt, *args);
56     msg << vmsg;
57   } else {
58     msg << fmt;
59   }
60   AddReferrerLocation(msg, referrer);
61   Thread* self = Thread::Current();
62   self->ThrowNewException(exception_descriptor, msg.str().c_str());
63 }
64 
ThrowWrappedException(const char * exception_descriptor,mirror::Class * referrer,const char * fmt,va_list * args=nullptr)65 static void ThrowWrappedException(const char* exception_descriptor,
66                                   mirror::Class* referrer, const char* fmt, va_list* args = nullptr)
67     SHARED_REQUIRES(Locks::mutator_lock_) {
68   std::ostringstream msg;
69   if (args != nullptr) {
70     std::string vmsg;
71     StringAppendV(&vmsg, fmt, *args);
72     msg << vmsg;
73   } else {
74     msg << fmt;
75   }
76   AddReferrerLocation(msg, referrer);
77   Thread* self = Thread::Current();
78   self->ThrowNewWrappedException(exception_descriptor, msg.str().c_str());
79 }
80 
81 // AbstractMethodError
82 
ThrowAbstractMethodError(ArtMethod * method)83 void ThrowAbstractMethodError(ArtMethod* method) {
84   ThrowException("Ljava/lang/AbstractMethodError;", nullptr,
85                  StringPrintf("abstract method \"%s\"",
86                               PrettyMethod(method).c_str()).c_str());
87 }
88 
ThrowAbstractMethodError(uint32_t method_idx,const DexFile & dex_file)89 void ThrowAbstractMethodError(uint32_t method_idx, const DexFile& dex_file) {
90   ThrowException("Ljava/lang/AbstractMethodError;", /* referrer */ nullptr,
91                  StringPrintf("abstract method \"%s\"",
92                               PrettyMethod(method_idx,
93                                            dex_file,
94                                            /* with_signature */ true).c_str()).c_str());
95 }
96 
97 // ArithmeticException
98 
ThrowArithmeticExceptionDivideByZero()99 void ThrowArithmeticExceptionDivideByZero() {
100   ThrowException("Ljava/lang/ArithmeticException;", nullptr, "divide by zero");
101 }
102 
103 // ArrayIndexOutOfBoundsException
104 
ThrowArrayIndexOutOfBoundsException(int index,int length)105 void ThrowArrayIndexOutOfBoundsException(int index, int length) {
106   ThrowException("Ljava/lang/ArrayIndexOutOfBoundsException;", nullptr,
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("Ljava/lang/ArrayStoreException;", nullptr,
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("Ljava/lang/ClassCastException;", nullptr,
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 char * msg)128 void ThrowClassCastException(const char* msg) {
129   ThrowException("Ljava/lang/ClassCastException;", nullptr, 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("Ljava/lang/ClassCircularityError;", c, msg.str().c_str());
138 }
139 
ThrowClassCircularityError(mirror::Class * c,const char * fmt,...)140 void ThrowClassCircularityError(mirror::Class* c, const char* fmt, ...) {
141   va_list args;
142   va_start(args, fmt);
143   ThrowException("Ljava/lang/ClassCircularityError;", c, fmt, &args);
144   va_end(args);
145 }
146 
147 // ClassFormatError
148 
ThrowClassFormatError(mirror::Class * referrer,const char * fmt,...)149 void ThrowClassFormatError(mirror::Class* referrer, const char* fmt, ...) {
150   va_list args;
151   va_start(args, fmt);
152   ThrowException("Ljava/lang/ClassFormatError;", referrer, fmt, &args);
153   va_end(args);}
154 
155 // IllegalAccessError
156 
ThrowIllegalAccessErrorClass(mirror::Class * referrer,mirror::Class * accessed)157 void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* accessed) {
158   std::ostringstream msg;
159   msg << "Illegal class access: '" << PrettyDescriptor(referrer) << "' attempting to access '"
160       << PrettyDescriptor(accessed) << "'";
161   ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
162 }
163 
ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class * referrer,mirror::Class * accessed,ArtMethod * called,InvokeType type)164 void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed,
165                                                    ArtMethod* called,
166                                                    InvokeType type) {
167   std::ostringstream msg;
168   msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '"
169       << PrettyDescriptor(accessed) << "') in attempt to invoke " << type
170       << " method " << PrettyMethod(called).c_str();
171   ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
172 }
173 
ThrowIllegalAccessErrorMethod(mirror::Class * referrer,ArtMethod * accessed)174 void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, ArtMethod* accessed) {
175   std::ostringstream msg;
176   msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '"
177       << PrettyDescriptor(referrer) << "'";
178   ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
179 }
180 
ThrowIllegalAccessErrorField(mirror::Class * referrer,ArtField * accessed)181 void ThrowIllegalAccessErrorField(mirror::Class* referrer, ArtField* accessed) {
182   std::ostringstream msg;
183   msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '"
184       << PrettyDescriptor(referrer) << "'";
185   ThrowException("Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str());
186 }
187 
ThrowIllegalAccessErrorFinalField(ArtMethod * referrer,ArtField * accessed)188 void ThrowIllegalAccessErrorFinalField(ArtMethod* referrer, ArtField* accessed) {
189   std::ostringstream msg;
190   msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '"
191       << PrettyMethod(referrer) << "'";
192   ThrowException("Ljava/lang/IllegalAccessError;",
193                  referrer != nullptr ? referrer->GetDeclaringClass() : nullptr,
194                  msg.str().c_str());
195 }
196 
ThrowIllegalAccessError(mirror::Class * referrer,const char * fmt,...)197 void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) {
198   va_list args;
199   va_start(args, fmt);
200   ThrowException("Ljava/lang/IllegalAccessError;", referrer, fmt, &args);
201   va_end(args);
202 }
203 
204 // IllegalAccessException
205 
ThrowIllegalAccessException(const char * msg)206 void ThrowIllegalAccessException(const char* msg) {
207   ThrowException("Ljava/lang/IllegalAccessException;", nullptr, msg);
208 }
209 
210 // IllegalArgumentException
211 
ThrowIllegalArgumentException(const char * msg)212 void ThrowIllegalArgumentException(const char* msg) {
213   ThrowException("Ljava/lang/IllegalArgumentException;", nullptr, msg);
214 }
215 
216 
217 // IncompatibleClassChangeError
218 
ThrowIncompatibleClassChangeError(InvokeType expected_type,InvokeType found_type,ArtMethod * method,ArtMethod * referrer)219 void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type,
220                                        ArtMethod* method, ArtMethod* referrer) {
221   std::ostringstream msg;
222   msg << "The method '" << PrettyMethod(method) << "' was expected to be of type "
223       << expected_type << " but instead was found to be of type " << found_type;
224   ThrowException("Ljava/lang/IncompatibleClassChangeError;",
225                  referrer != nullptr ? referrer->GetDeclaringClass() : nullptr,
226                  msg.str().c_str());
227 }
228 
ThrowIncompatibleClassChangeErrorClassForInterfaceSuper(ArtMethod * method,mirror::Class * target_class,mirror::Object * this_object,ArtMethod * referrer)229 void ThrowIncompatibleClassChangeErrorClassForInterfaceSuper(ArtMethod* method,
230                                                              mirror::Class* target_class,
231                                                              mirror::Object* this_object,
232                                                              ArtMethod* referrer) {
233   // Referrer is calling interface_method on this_object, however, the interface_method isn't
234   // implemented by this_object.
235   CHECK(this_object != nullptr);
236   std::ostringstream msg;
237   msg << "Class '" << PrettyDescriptor(this_object->GetClass())
238       << "' does not implement interface '" << PrettyDescriptor(target_class) << "' in call to '"
239       << PrettyMethod(method) << "'";
240   ThrowException("Ljava/lang/IncompatibleClassChangeError;",
241                  referrer != nullptr ? referrer->GetDeclaringClass() : nullptr,
242                  msg.str().c_str());
243 }
244 
ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(ArtMethod * interface_method,mirror::Object * this_object,ArtMethod * referrer)245 void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(ArtMethod* interface_method,
246                                                                 mirror::Object* this_object,
247                                                                 ArtMethod* referrer) {
248   // Referrer is calling interface_method on this_object, however, the interface_method isn't
249   // implemented by this_object.
250   CHECK(this_object != nullptr);
251   std::ostringstream msg;
252   msg << "Class '" << PrettyDescriptor(this_object->GetClass())
253       << "' does not implement interface '"
254       << PrettyDescriptor(interface_method->GetDeclaringClass())
255       << "' in call to '" << PrettyMethod(interface_method) << "'";
256   ThrowException("Ljava/lang/IncompatibleClassChangeError;",
257                  referrer != nullptr ? referrer->GetDeclaringClass() : nullptr,
258                  msg.str().c_str());
259 }
260 
ThrowIncompatibleClassChangeErrorField(ArtField * resolved_field,bool is_static,ArtMethod * referrer)261 void ThrowIncompatibleClassChangeErrorField(ArtField* resolved_field, bool is_static,
262                                             ArtMethod* referrer) {
263   std::ostringstream msg;
264   msg << "Expected '" << PrettyField(resolved_field) << "' to be a "
265       << (is_static ? "static" : "instance") << " field" << " rather than a "
266       << (is_static ? "instance" : "static") << " field";
267   ThrowException("Ljava/lang/IncompatibleClassChangeError;", referrer->GetDeclaringClass(),
268                  msg.str().c_str());
269 }
270 
ThrowIncompatibleClassChangeError(mirror::Class * referrer,const char * fmt,...)271 void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...) {
272   va_list args;
273   va_start(args, fmt);
274   ThrowException("Ljava/lang/IncompatibleClassChangeError;", referrer, fmt, &args);
275   va_end(args);
276 }
277 
ThrowIncompatibleClassChangeErrorForMethodConflict(ArtMethod * method)278 void ThrowIncompatibleClassChangeErrorForMethodConflict(ArtMethod* method) {
279   DCHECK(method != nullptr);
280   ThrowException("Ljava/lang/IncompatibleClassChangeError;",
281                  /*referrer*/nullptr,
282                  StringPrintf("Conflicting default method implementations %s",
283                               PrettyMethod(method).c_str()).c_str());
284 }
285 
286 
287 // IOException
288 
ThrowIOException(const char * fmt,...)289 void ThrowIOException(const char* fmt, ...) {
290   va_list args;
291   va_start(args, fmt);
292   ThrowException("Ljava/io/IOException;", nullptr, fmt, &args);
293   va_end(args);
294 }
295 
ThrowWrappedIOException(const char * fmt,...)296 void ThrowWrappedIOException(const char* fmt, ...) {
297   va_list args;
298   va_start(args, fmt);
299   ThrowWrappedException("Ljava/io/IOException;", nullptr, fmt, &args);
300   va_end(args);
301 }
302 
303 // LinkageError
304 
ThrowLinkageError(mirror::Class * referrer,const char * fmt,...)305 void ThrowLinkageError(mirror::Class* referrer, const char* fmt, ...) {
306   va_list args;
307   va_start(args, fmt);
308   ThrowException("Ljava/lang/LinkageError;", referrer, fmt, &args);
309   va_end(args);
310 }
311 
ThrowWrappedLinkageError(mirror::Class * referrer,const char * fmt,...)312 void ThrowWrappedLinkageError(mirror::Class* referrer, const char* fmt, ...) {
313   va_list args;
314   va_start(args, fmt);
315   ThrowWrappedException("Ljava/lang/LinkageError;", referrer, fmt, &args);
316   va_end(args);
317 }
318 
319 // NegativeArraySizeException
320 
ThrowNegativeArraySizeException(int size)321 void ThrowNegativeArraySizeException(int size) {
322   ThrowException("Ljava/lang/NegativeArraySizeException;", nullptr,
323                  StringPrintf("%d", size).c_str());
324 }
325 
ThrowNegativeArraySizeException(const char * msg)326 void ThrowNegativeArraySizeException(const char* msg) {
327   ThrowException("Ljava/lang/NegativeArraySizeException;", nullptr, msg);
328 }
329 
330 // NoSuchFieldError
331 
ThrowNoSuchFieldError(const StringPiece & scope,mirror::Class * c,const StringPiece & type,const StringPiece & name)332 void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c,
333                            const StringPiece& type, const StringPiece& name) {
334   std::ostringstream msg;
335   std::string temp;
336   msg << "No " << scope << "field " << name << " of type " << type
337       << " in class " << c->GetDescriptor(&temp) << " or its superclasses";
338   ThrowException("Ljava/lang/NoSuchFieldError;", c, msg.str().c_str());
339 }
340 
ThrowNoSuchFieldException(mirror::Class * c,const StringPiece & name)341 void ThrowNoSuchFieldException(mirror::Class* c, const StringPiece& name) {
342   std::ostringstream msg;
343   std::string temp;
344   msg << "No field " << name << " in class " << c->GetDescriptor(&temp);
345   ThrowException("Ljava/lang/NoSuchFieldException;", c, msg.str().c_str());
346 }
347 
348 // NoSuchMethodError
349 
ThrowNoSuchMethodError(InvokeType type,mirror::Class * c,const StringPiece & name,const Signature & signature)350 void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name,
351                             const Signature& signature) {
352   std::ostringstream msg;
353   std::string temp;
354   msg << "No " << type << " method " << name << signature
355       << " in class " << c->GetDescriptor(&temp) << " or its super classes";
356   ThrowException("Ljava/lang/NoSuchMethodError;", c, msg.str().c_str());
357 }
358 
ThrowNoSuchMethodError(uint32_t method_idx)359 void ThrowNoSuchMethodError(uint32_t method_idx) {
360   ArtMethod* method = Thread::Current()->GetCurrentMethod(nullptr);
361   mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
362   const DexFile& dex_file = *dex_cache->GetDexFile();
363   std::ostringstream msg;
364   msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'";
365   ThrowException("Ljava/lang/NoSuchMethodError;",
366                  method->GetDeclaringClass(), msg.str().c_str());
367 }
368 
369 // NullPointerException
370 
ThrowNullPointerExceptionForFieldAccess(ArtField * field,bool is_read)371 void ThrowNullPointerExceptionForFieldAccess(ArtField* field, bool is_read) {
372   std::ostringstream msg;
373   msg << "Attempt to " << (is_read ? "read from" : "write to")
374       << " field '" << PrettyField(field, true) << "' on a null object reference";
375   ThrowException("Ljava/lang/NullPointerException;", nullptr, msg.str().c_str());
376 }
377 
ThrowNullPointerExceptionForMethodAccessImpl(uint32_t method_idx,const DexFile & dex_file,InvokeType type)378 static void ThrowNullPointerExceptionForMethodAccessImpl(uint32_t method_idx,
379                                                          const DexFile& dex_file,
380                                                          InvokeType type)
381     SHARED_REQUIRES(Locks::mutator_lock_) {
382   std::ostringstream msg;
383   msg << "Attempt to invoke " << type << " method '"
384       << PrettyMethod(method_idx, dex_file, true) << "' on a null object reference";
385   ThrowException("Ljava/lang/NullPointerException;", nullptr, msg.str().c_str());
386 }
387 
ThrowNullPointerExceptionForMethodAccess(uint32_t method_idx,InvokeType type)388 void ThrowNullPointerExceptionForMethodAccess(uint32_t method_idx,
389                                               InvokeType type) {
390   mirror::DexCache* dex_cache =
391       Thread::Current()->GetCurrentMethod(nullptr)->GetDeclaringClass()->GetDexCache();
392   const DexFile& dex_file = *dex_cache->GetDexFile();
393   ThrowNullPointerExceptionForMethodAccessImpl(method_idx, dex_file, type);
394 }
395 
ThrowNullPointerExceptionForMethodAccess(ArtMethod * method,InvokeType type)396 void ThrowNullPointerExceptionForMethodAccess(ArtMethod* method,
397                                               InvokeType type) {
398   mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache();
399   const DexFile& dex_file = *dex_cache->GetDexFile();
400   ThrowNullPointerExceptionForMethodAccessImpl(method->GetDexMethodIndex(),
401                                                dex_file, type);
402 }
403 
ThrowNullPointerExceptionFromDexPC()404 void ThrowNullPointerExceptionFromDexPC() {
405   uint32_t throw_dex_pc;
406   ArtMethod* method = Thread::Current()->GetCurrentMethod(&throw_dex_pc);
407   const DexFile::CodeItem* code = method->GetCodeItem();
408   CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_);
409   const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]);
410   switch (instr->Opcode()) {
411     case Instruction::INVOKE_DIRECT:
412       ThrowNullPointerExceptionForMethodAccess(instr->VRegB_35c(), kDirect);
413       break;
414     case Instruction::INVOKE_DIRECT_RANGE:
415       ThrowNullPointerExceptionForMethodAccess(instr->VRegB_3rc(), kDirect);
416       break;
417     case Instruction::INVOKE_VIRTUAL:
418       ThrowNullPointerExceptionForMethodAccess(instr->VRegB_35c(), kVirtual);
419       break;
420     case Instruction::INVOKE_VIRTUAL_RANGE:
421       ThrowNullPointerExceptionForMethodAccess(instr->VRegB_3rc(), kVirtual);
422       break;
423     case Instruction::INVOKE_INTERFACE:
424       ThrowNullPointerExceptionForMethodAccess(instr->VRegB_35c(), kInterface);
425       break;
426     case Instruction::INVOKE_INTERFACE_RANGE:
427       ThrowNullPointerExceptionForMethodAccess(instr->VRegB_3rc(), kInterface);
428       break;
429     case Instruction::INVOKE_VIRTUAL_QUICK:
430     case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: {
431       // Since we replaced the method index, we ask the verifier to tell us which
432       // method is invoked at this location.
433       ArtMethod* invoked_method =
434           verifier::MethodVerifier::FindInvokedMethodAtDexPc(method, throw_dex_pc);
435       if (invoked_method != nullptr) {
436         // NPE with precise message.
437         ThrowNullPointerExceptionForMethodAccess(invoked_method, kVirtual);
438       } else {
439         // NPE with imprecise message.
440         ThrowNullPointerException("Attempt to invoke a virtual method on a null object reference");
441       }
442       break;
443     }
444     case Instruction::IGET:
445     case Instruction::IGET_WIDE:
446     case Instruction::IGET_OBJECT:
447     case Instruction::IGET_BOOLEAN:
448     case Instruction::IGET_BYTE:
449     case Instruction::IGET_CHAR:
450     case Instruction::IGET_SHORT: {
451       ArtField* field =
452           Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), method, false);
453       ThrowNullPointerExceptionForFieldAccess(field, true /* read */);
454       break;
455     }
456     case Instruction::IGET_QUICK:
457     case Instruction::IGET_BOOLEAN_QUICK:
458     case Instruction::IGET_BYTE_QUICK:
459     case Instruction::IGET_CHAR_QUICK:
460     case Instruction::IGET_SHORT_QUICK:
461     case Instruction::IGET_WIDE_QUICK:
462     case Instruction::IGET_OBJECT_QUICK: {
463       // Since we replaced the field index, we ask the verifier to tell us which
464       // field is accessed at this location.
465       ArtField* field =
466           verifier::MethodVerifier::FindAccessedFieldAtDexPc(method, throw_dex_pc);
467       if (field != nullptr) {
468         // NPE with precise message.
469         ThrowNullPointerExceptionForFieldAccess(field, true /* read */);
470       } else {
471         // NPE with imprecise message.
472         ThrowNullPointerException("Attempt to read from a field on a null object reference");
473       }
474       break;
475     }
476     case Instruction::IPUT:
477     case Instruction::IPUT_WIDE:
478     case Instruction::IPUT_OBJECT:
479     case Instruction::IPUT_BOOLEAN:
480     case Instruction::IPUT_BYTE:
481     case Instruction::IPUT_CHAR:
482     case Instruction::IPUT_SHORT: {
483       ArtField* field =
484           Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), method, false);
485       ThrowNullPointerExceptionForFieldAccess(field, false /* write */);
486       break;
487     }
488     case Instruction::IPUT_QUICK:
489     case Instruction::IPUT_BOOLEAN_QUICK:
490     case Instruction::IPUT_BYTE_QUICK:
491     case Instruction::IPUT_CHAR_QUICK:
492     case Instruction::IPUT_SHORT_QUICK:
493     case Instruction::IPUT_WIDE_QUICK:
494     case Instruction::IPUT_OBJECT_QUICK: {
495       // Since we replaced the field index, we ask the verifier to tell us which
496       // field is accessed at this location.
497       ArtField* field =
498           verifier::MethodVerifier::FindAccessedFieldAtDexPc(method, throw_dex_pc);
499       if (field != nullptr) {
500         // NPE with precise message.
501         ThrowNullPointerExceptionForFieldAccess(field, false /* write */);
502       } else {
503         // NPE with imprecise message.
504         ThrowNullPointerException("Attempt to write to a field on a null object reference");
505       }
506       break;
507     }
508     case Instruction::AGET:
509     case Instruction::AGET_WIDE:
510     case Instruction::AGET_OBJECT:
511     case Instruction::AGET_BOOLEAN:
512     case Instruction::AGET_BYTE:
513     case Instruction::AGET_CHAR:
514     case Instruction::AGET_SHORT:
515       ThrowException("Ljava/lang/NullPointerException;", nullptr,
516                      "Attempt to read from null array");
517       break;
518     case Instruction::APUT:
519     case Instruction::APUT_WIDE:
520     case Instruction::APUT_OBJECT:
521     case Instruction::APUT_BOOLEAN:
522     case Instruction::APUT_BYTE:
523     case Instruction::APUT_CHAR:
524     case Instruction::APUT_SHORT:
525       ThrowException("Ljava/lang/NullPointerException;", nullptr,
526                      "Attempt to write to null array");
527       break;
528     case Instruction::ARRAY_LENGTH:
529       ThrowException("Ljava/lang/NullPointerException;", nullptr,
530                      "Attempt to get length of null array");
531       break;
532     default: {
533       // TODO: We should have covered all the cases where we expect a NPE above, this
534       //       message/logging is so we can improve any cases we've missed in the future.
535       const DexFile* dex_file =
536           method->GetDeclaringClass()->GetDexCache()->GetDexFile();
537       ThrowException("Ljava/lang/NullPointerException;", nullptr,
538                      StringPrintf("Null pointer exception during instruction '%s'",
539                                   instr->DumpString(dex_file).c_str()).c_str());
540       break;
541     }
542   }
543 }
544 
ThrowNullPointerException(const char * msg)545 void ThrowNullPointerException(const char* msg) {
546   ThrowException("Ljava/lang/NullPointerException;", nullptr, msg);
547 }
548 
549 // RuntimeException
550 
ThrowRuntimeException(const char * fmt,...)551 void ThrowRuntimeException(const char* fmt, ...) {
552   va_list args;
553   va_start(args, fmt);
554   ThrowException("Ljava/lang/RuntimeException;", nullptr, fmt, &args);
555   va_end(args);
556 }
557 
558 // Stack overflow.
559 
ThrowStackOverflowError(Thread * self)560 void ThrowStackOverflowError(Thread* self) {
561   if (self->IsHandlingStackOverflow()) {
562     LOG(ERROR) << "Recursive stack overflow.";
563     // We don't fail here because SetStackEndForStackOverflow will print better diagnostics.
564   }
565 
566   self->SetStackEndForStackOverflow();  // Allow space on the stack for constructor to execute.
567   JNIEnvExt* env = self->GetJniEnv();
568   std::string msg("stack size ");
569   msg += PrettySize(self->GetStackSize());
570 
571   // Avoid running Java code for exception initialization.
572   // TODO: Checks to make this a bit less brittle.
573 
574   std::string error_msg;
575 
576   // Allocate an uninitialized object.
577   ScopedLocalRef<jobject> exc(env,
578                               env->AllocObject(WellKnownClasses::java_lang_StackOverflowError));
579   if (exc.get() != nullptr) {
580     // "Initialize".
581     // StackOverflowError -> VirtualMachineError -> Error -> Throwable -> Object.
582     // Only Throwable has "custom" fields:
583     //   String detailMessage.
584     //   Throwable cause (= this).
585     //   List<Throwable> suppressedExceptions (= Collections.emptyList()).
586     //   Object stackState;
587     //   StackTraceElement[] stackTrace;
588     // Only Throwable has a non-empty constructor:
589     //   this.stackTrace = EmptyArray.STACK_TRACE_ELEMENT;
590     //   fillInStackTrace();
591 
592     // detailMessage.
593     // TODO: Use String::FromModifiedUTF...?
594     ScopedLocalRef<jstring> s(env, env->NewStringUTF(msg.c_str()));
595     if (s.get() != nullptr) {
596       env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_detailMessage, s.get());
597 
598       // cause.
599       env->SetObjectField(exc.get(), WellKnownClasses::java_lang_Throwable_cause, exc.get());
600 
601       // suppressedExceptions.
602       ScopedLocalRef<jobject> emptylist(env, env->GetStaticObjectField(
603           WellKnownClasses::java_util_Collections,
604           WellKnownClasses::java_util_Collections_EMPTY_LIST));
605       CHECK(emptylist.get() != nullptr);
606       env->SetObjectField(exc.get(),
607                           WellKnownClasses::java_lang_Throwable_suppressedExceptions,
608                           emptylist.get());
609 
610       // stackState is set as result of fillInStackTrace. fillInStackTrace calls
611       // nativeFillInStackTrace.
612       ScopedLocalRef<jobject> stack_state_val(env, nullptr);
613       {
614         ScopedObjectAccessUnchecked soa(env);
615         stack_state_val.reset(soa.Self()->CreateInternalStackTrace<false>(soa));
616       }
617       if (stack_state_val.get() != nullptr) {
618         env->SetObjectField(exc.get(),
619                             WellKnownClasses::java_lang_Throwable_stackState,
620                             stack_state_val.get());
621 
622         // stackTrace.
623         ScopedLocalRef<jobject> stack_trace_elem(env, env->GetStaticObjectField(
624             WellKnownClasses::libcore_util_EmptyArray,
625             WellKnownClasses::libcore_util_EmptyArray_STACK_TRACE_ELEMENT));
626         env->SetObjectField(exc.get(),
627                             WellKnownClasses::java_lang_Throwable_stackTrace,
628                             stack_trace_elem.get());
629       } else {
630         error_msg = "Could not create stack trace.";
631       }
632       // Throw the exception.
633       self->SetException(reinterpret_cast<mirror::Throwable*>(self->DecodeJObject(exc.get())));
634     } else {
635       // Could not allocate a string object.
636       error_msg = "Couldn't throw new StackOverflowError because JNI NewStringUTF failed.";
637     }
638   } else {
639     error_msg = "Could not allocate StackOverflowError object.";
640   }
641 
642   if (!error_msg.empty()) {
643     LOG(WARNING) << error_msg;
644     CHECK(self->IsExceptionPending());
645   }
646 
647   bool explicit_overflow_check = Runtime::Current()->ExplicitStackOverflowChecks();
648   self->ResetDefaultStackEnd();  // Return to default stack size.
649 
650   // And restore protection if implicit checks are on.
651   if (!explicit_overflow_check) {
652     self->ProtectStack();
653   }
654 }
655 
656 // VerifyError
657 
ThrowVerifyError(mirror::Class * referrer,const char * fmt,...)658 void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) {
659   va_list args;
660   va_start(args, fmt);
661   ThrowException("Ljava/lang/VerifyError;", referrer, fmt, &args);
662   va_end(args);
663 }
664 
665 }  // namespace art
666