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 "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 
     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 
     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 
     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 
     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 
     99 void ThrowArithmeticExceptionDivideByZero() {
    100   ThrowException(NULL, "Ljava/lang/ArithmeticException;", NULL, "divide by zero");
    101 }
    102 
    103 // ArrayIndexOutOfBoundsException
    104 
    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 
    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 
    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 
    128 void ThrowClassCastException(const ThrowLocation* throw_location, const char* msg) {
    129   ThrowException(throw_location, "Ljava/lang/ClassCastException;", NULL, msg);
    130 }
    131 
    132 // ClassCircularityError
    133 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    200 void ThrowIllegalAccessException(const ThrowLocation* throw_location, const char* msg) {
    201   ThrowException(throw_location, "Ljava/lang/IllegalAccessException;", NULL, msg);
    202 }
    203 
    204 // IllegalArgumentException
    205 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    284 void ThrowNegativeArraySizeException(int size) {
    285   ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL,
    286                  StringPrintf("%d", size).c_str());
    287 }
    288 
    289 void ThrowNegativeArraySizeException(const char* msg) {
    290   ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL, msg);
    291 }
    292 
    293 // NoSuchFieldError
    294 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    506 void ThrowNullPointerException(const ThrowLocation* throw_location, const char* msg) {
    507   ThrowException(throw_location, "Ljava/lang/NullPointerException;", NULL, msg);
    508 }
    509 
    510 // RuntimeException
    511 
    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 
    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