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