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 34namespace art { 35 36static 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 47static 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 63static 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 81void 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 89void ThrowArithmeticExceptionDivideByZero() { 90 ThrowException("Ljava/lang/ArithmeticException;", nullptr, "divide by zero"); 91} 92 93// ArrayIndexOutOfBoundsException 94 95void 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 102void 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 111void 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 118void ThrowClassCastException(const char* msg) { 119 ThrowException("Ljava/lang/ClassCastException;", nullptr, msg); 120} 121 122// ClassCircularityError 123 124void 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 132void 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 140void 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 147void 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 157void 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 164void 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 171void 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 180void 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 189void ThrowIllegalAccessException(const char* msg) { 190 ThrowException("Ljava/lang/IllegalAccessException;", nullptr, msg); 191} 192 193// IllegalArgumentException 194 195void ThrowIllegalArgumentException(const char* msg) { 196 ThrowException("Ljava/lang/IllegalArgumentException;", nullptr, msg); 197} 198 199 200// IncompatibleClassChangeError 201 202void 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 212void 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 228void 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 238void 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 247void 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 254void 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 263void 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 270void 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 279void ThrowNegativeArraySizeException(int size) { 280 ThrowException("Ljava/lang/NegativeArraySizeException;", nullptr, 281 StringPrintf("%d", size).c_str()); 282} 283 284void ThrowNegativeArraySizeException(const char* msg) { 285 ThrowException("Ljava/lang/NegativeArraySizeException;", nullptr, msg); 286} 287 288// NoSuchFieldError 289 290void 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 299void 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 308void 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 317void 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 329void 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 336static 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 346void 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 354void 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 362void 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 503void ThrowNullPointerException(const char* msg) { 504 ThrowException("Ljava/lang/NullPointerException;", nullptr, msg); 505} 506 507// RuntimeException 508 509void 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 518void 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