Home | History | Annotate | Download | only in runtime
      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 
     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 
     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 
     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 
     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 
     89 void ThrowArithmeticExceptionDivideByZero() {
     90   ThrowException("Ljava/lang/ArithmeticException;", nullptr, "divide by zero");
     91 }
     92 
     93 // ArrayIndexOutOfBoundsException
     94 
     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 
    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 
    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 
    118 void ThrowClassCastException(const char* msg) {
    119   ThrowException("Ljava/lang/ClassCastException;", nullptr, msg);
    120 }
    121 
    122 // ClassCircularityError
    123 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    189 void ThrowIllegalAccessException(const char* msg) {
    190   ThrowException("Ljava/lang/IllegalAccessException;", nullptr, msg);
    191 }
    192 
    193 // IllegalArgumentException
    194 
    195 void ThrowIllegalArgumentException(const char* msg) {
    196   ThrowException("Ljava/lang/IllegalArgumentException;", nullptr, msg);
    197 }
    198 
    199 
    200 // IncompatibleClassChangeError
    201 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    279 void ThrowNegativeArraySizeException(int size) {
    280   ThrowException("Ljava/lang/NegativeArraySizeException;", nullptr,
    281                  StringPrintf("%d", size).c_str());
    282 }
    283 
    284 void ThrowNegativeArraySizeException(const char* msg) {
    285   ThrowException("Ljava/lang/NegativeArraySizeException;", nullptr, msg);
    286 }
    287 
    288 // NoSuchFieldError
    289 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    503 void ThrowNullPointerException(const char* msg) {
    504   ThrowException("Ljava/lang/NullPointerException;", nullptr, msg);
    505 }
    506 
    507 // RuntimeException
    508 
    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 
    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