common_throws.cc revision ef7d42fca18c16fbaf103822ad16f23246e2905d
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 "base/logging.h" 20#include "class_linker-inl.h" 21#include "dex_file-inl.h" 22#include "dex_instruction-inl.h" 23#include "invoke_type.h" 24#include "mirror/art_method-inl.h" 25#include "mirror/class-inl.h" 26#include "mirror/object-inl.h" 27#include "mirror/object_array-inl.h" 28#include "object_utils.h" 29#include "thread.h" 30#include "verifier/method_verifier.h" 31 32#include <sstream> 33 34namespace art { 35 36static void AddReferrerLocation(std::ostream& os, mirror::Class* referrer) 37 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 38 if (referrer != NULL) { 39 ClassHelper kh(referrer); 40 std::string location(kh.GetLocation()); 41 if (!location.empty()) { 42 os << " (declaration of '" << PrettyDescriptor(referrer) 43 << "' appears in " << location << ")"; 44 } 45 } 46} 47 48static void ThrowException(const ThrowLocation* throw_location, const char* exception_descriptor, 49 mirror::Class* referrer, const char* fmt, va_list* args = NULL) 50 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 51 std::ostringstream msg; 52 if (args != NULL) { 53 std::string vmsg; 54 StringAppendV(&vmsg, fmt, *args); 55 msg << vmsg; 56 } else { 57 msg << fmt; 58 } 59 AddReferrerLocation(msg, referrer); 60 Thread* self = Thread::Current(); 61 if (throw_location == NULL) { 62 ThrowLocation computed_throw_location = self->GetCurrentLocationForThrow(); 63 self->ThrowNewException(computed_throw_location, exception_descriptor, msg.str().c_str()); 64 } else { 65 self->ThrowNewException(*throw_location, exception_descriptor, msg.str().c_str()); 66 } 67} 68 69// AbstractMethodError 70 71void ThrowAbstractMethodError(mirror::ArtMethod* method) { 72 ThrowException(NULL, "Ljava/lang/AbstractMethodError;", NULL, 73 StringPrintf("abstract method \"%s\"", 74 PrettyMethod(method).c_str()).c_str()); 75} 76 77// ArithmeticException 78 79void ThrowArithmeticExceptionDivideByZero() { 80 ThrowException(NULL, "Ljava/lang/ArithmeticException;", NULL, "divide by zero"); 81} 82 83// ArrayIndexOutOfBoundsException 84 85void ThrowArrayIndexOutOfBoundsException(int index, int length) { 86 ThrowException(NULL, "Ljava/lang/ArrayIndexOutOfBoundsException;", NULL, 87 StringPrintf("length=%d; index=%d", length, index).c_str()); 88} 89 90// ArrayStoreException 91 92void ThrowArrayStoreException(mirror::Class* element_class, mirror::Class* array_class) { 93 ThrowException(NULL, "Ljava/lang/ArrayStoreException;", NULL, 94 StringPrintf("%s cannot be stored in an array of type %s", 95 PrettyDescriptor(element_class).c_str(), 96 PrettyDescriptor(array_class).c_str()).c_str()); 97} 98 99// ClassCastException 100 101void ThrowClassCastException(mirror::Class* dest_type, mirror::Class* src_type) { 102 ThrowException(NULL, "Ljava/lang/ClassCastException;", NULL, 103 StringPrintf("%s cannot be cast to %s", 104 PrettyDescriptor(src_type).c_str(), 105 PrettyDescriptor(dest_type).c_str()).c_str()); 106} 107 108void ThrowClassCastException(const ThrowLocation* throw_location, const char* msg) { 109 ThrowException(throw_location, "Ljava/lang/ClassCastException;", NULL, msg); 110} 111 112// ClassCircularityError 113 114void ThrowClassCircularityError(mirror::Class* c) { 115 std::ostringstream msg; 116 msg << PrettyDescriptor(c); 117 ThrowException(NULL, "Ljava/lang/ClassCircularityError;", c, msg.str().c_str()); 118} 119 120// ClassFormatError 121 122void ThrowClassFormatError(mirror::Class* referrer, const char* fmt, ...) { 123 va_list args; 124 va_start(args, fmt); 125 ThrowException(NULL, "Ljava/lang/ClassFormatError;", referrer, fmt, &args); 126 va_end(args);} 127 128// IllegalAccessError 129 130void ThrowIllegalAccessErrorClass(mirror::Class* referrer, mirror::Class* accessed) { 131 std::ostringstream msg; 132 msg << "Illegal class access: '" << PrettyDescriptor(referrer) << "' attempting to access '" 133 << PrettyDescriptor(accessed) << "'"; 134 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str()); 135} 136 137void ThrowIllegalAccessErrorClassForMethodDispatch(mirror::Class* referrer, mirror::Class* accessed, 138 mirror::ArtMethod* called, 139 InvokeType type) { 140 std::ostringstream msg; 141 msg << "Illegal class access ('" << PrettyDescriptor(referrer) << "' attempting to access '" 142 << PrettyDescriptor(accessed) << "') in attempt to invoke " << type 143 << " method " << PrettyMethod(called).c_str(); 144 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str()); 145} 146 147void ThrowIllegalAccessErrorMethod(mirror::Class* referrer, mirror::ArtMethod* accessed) { 148 std::ostringstream msg; 149 msg << "Method '" << PrettyMethod(accessed) << "' is inaccessible to class '" 150 << PrettyDescriptor(referrer) << "'"; 151 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str()); 152} 153 154void ThrowIllegalAccessErrorField(mirror::Class* referrer, mirror::ArtField* accessed) { 155 std::ostringstream msg; 156 msg << "Field '" << PrettyField(accessed, false) << "' is inaccessible to class '" 157 << PrettyDescriptor(referrer) << "'"; 158 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, msg.str().c_str()); 159} 160 161void ThrowIllegalAccessErrorFinalField(mirror::ArtMethod* referrer, 162 mirror::ArtField* accessed) { 163 std::ostringstream msg; 164 msg << "Final field '" << PrettyField(accessed, false) << "' cannot be written to by method '" 165 << PrettyMethod(referrer) << "'"; 166 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", 167 referrer != NULL ? referrer->GetClass() : NULL, 168 msg.str().c_str()); 169} 170 171void ThrowIllegalAccessError(mirror::Class* referrer, const char* fmt, ...) { 172 va_list args; 173 va_start(args, fmt); 174 ThrowException(NULL, "Ljava/lang/IllegalAccessError;", referrer, fmt, &args); 175 va_end(args); 176} 177 178// IllegalArgumentException 179 180void ThrowIllegalArgumentException(const ThrowLocation* throw_location, const char* msg) { 181 ThrowException(throw_location, "Ljava/lang/IllegalArgumentException;", NULL, msg); 182} 183 184 185// IncompatibleClassChangeError 186 187void ThrowIncompatibleClassChangeError(InvokeType expected_type, InvokeType found_type, 188 mirror::ArtMethod* method, 189 mirror::ArtMethod* referrer) { 190 std::ostringstream msg; 191 msg << "The method '" << PrettyMethod(method) << "' was expected to be of type " 192 << expected_type << " but instead was found to be of type " << found_type; 193 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", 194 referrer != NULL ? referrer->GetClass() : NULL, 195 msg.str().c_str()); 196} 197 198void ThrowIncompatibleClassChangeErrorClassForInterfaceDispatch(mirror::ArtMethod* interface_method, 199 mirror::Object* this_object, 200 mirror::ArtMethod* referrer) { 201 // Referrer is calling interface_method on this_object, however, the interface_method isn't 202 // implemented by this_object. 203 CHECK(this_object != NULL); 204 std::ostringstream msg; 205 msg << "Class '" << PrettyDescriptor(this_object->GetClass()) 206 << "' does not implement interface '" 207 << PrettyDescriptor(interface_method->GetDeclaringClass()) 208 << "' in call to '" << PrettyMethod(interface_method) << "'"; 209 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", 210 referrer != NULL ? referrer->GetClass() : NULL, 211 msg.str().c_str()); 212} 213 214void ThrowIncompatibleClassChangeErrorField(mirror::ArtField* resolved_field, bool is_static, 215 mirror::ArtMethod* referrer) { 216 std::ostringstream msg; 217 msg << "Expected '" << PrettyField(resolved_field) << "' to be a " 218 << (is_static ? "static" : "instance") << " field" << " rather than a " 219 << (is_static ? "instance" : "static") << " field"; 220 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer->GetClass(), 221 msg.str().c_str()); 222} 223 224void ThrowIncompatibleClassChangeError(mirror::Class* referrer, const char* fmt, ...) { 225 va_list args; 226 va_start(args, fmt); 227 ThrowException(NULL, "Ljava/lang/IncompatibleClassChangeError;", referrer, fmt, &args); 228 va_end(args); 229} 230 231// IOException 232 233void ThrowIOException(const char* fmt, ...) { 234 va_list args; 235 va_start(args, fmt); 236 ThrowException(NULL, "Ljava/io/IOException;", NULL, fmt, &args); 237 va_end(args); 238} 239 240// LinkageError 241 242void ThrowLinkageError(mirror::Class* referrer, const char* fmt, ...) { 243 va_list args; 244 va_start(args, fmt); 245 ThrowException(NULL, "Ljava/lang/LinkageError;", referrer, fmt, &args); 246 va_end(args); 247} 248 249// NegativeArraySizeException 250 251void ThrowNegativeArraySizeException(int size) { 252 ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL, 253 StringPrintf("%d", size).c_str()); 254} 255 256void ThrowNegativeArraySizeException(const char* msg) { 257 ThrowException(NULL, "Ljava/lang/NegativeArraySizeException;", NULL, msg); 258} 259 260// NoSuchFieldError 261 262void ThrowNoSuchFieldError(const StringPiece& scope, mirror::Class* c, 263 const StringPiece& type, const StringPiece& name) 264 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 265 ClassHelper kh(c); 266 std::ostringstream msg; 267 msg << "No " << scope << "field " << name << " of type " << type 268 << " in class " << kh.GetDescriptor() << " or its superclasses"; 269 ThrowException(NULL, "Ljava/lang/NoSuchFieldError;", c, msg.str().c_str()); 270} 271 272// NoSuchMethodError 273 274void ThrowNoSuchMethodError(InvokeType type, mirror::Class* c, const StringPiece& name, 275 const Signature& signature) { 276 std::ostringstream msg; 277 ClassHelper kh(c); 278 msg << "No " << type << " method " << name << signature 279 << " in class " << kh.GetDescriptor() << " or its super classes"; 280 ThrowException(NULL, "Ljava/lang/NoSuchMethodError;", c, msg.str().c_str()); 281} 282 283void ThrowNoSuchMethodError(uint32_t method_idx) { 284 Thread* self = Thread::Current(); 285 ThrowLocation throw_location = self->GetCurrentLocationForThrow(); 286 mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache(); 287 const DexFile& dex_file = *dex_cache->GetDexFile(); 288 std::ostringstream msg; 289 msg << "No method '" << PrettyMethod(method_idx, dex_file, true) << "'"; 290 ThrowException(&throw_location, "Ljava/lang/NoSuchMethodError;", 291 throw_location.GetMethod()->GetDeclaringClass(), msg.str().c_str()); 292} 293 294// NullPointerException 295 296void ThrowNullPointerExceptionForFieldAccess(const ThrowLocation& throw_location, 297 mirror::ArtField* field, bool is_read) { 298 std::ostringstream msg; 299 msg << "Attempt to " << (is_read ? "read from" : "write to") 300 << " field '" << PrettyField(field, true) << "' on a null object reference"; 301 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str()); 302} 303 304static void ThrowNullPointerExceptionForMethodAccessImpl(const ThrowLocation& throw_location, 305 uint32_t method_idx, 306 const DexFile& dex_file, 307 InvokeType type) 308 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 309 std::ostringstream msg; 310 msg << "Attempt to invoke " << type << " method '" 311 << PrettyMethod(method_idx, dex_file, true) << "' on a null object reference"; 312 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, msg.str().c_str()); 313} 314 315void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location, 316 uint32_t method_idx, 317 InvokeType type) { 318 mirror::DexCache* dex_cache = throw_location.GetMethod()->GetDeclaringClass()->GetDexCache(); 319 const DexFile& dex_file = *dex_cache->GetDexFile(); 320 ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method_idx, 321 dex_file, type); 322} 323 324void ThrowNullPointerExceptionForMethodAccess(const ThrowLocation& throw_location, 325 mirror::ArtMethod* method, 326 InvokeType type) { 327 mirror::DexCache* dex_cache = method->GetDeclaringClass()->GetDexCache(); 328 const DexFile& dex_file = *dex_cache->GetDexFile(); 329 ThrowNullPointerExceptionForMethodAccessImpl(throw_location, method->GetDexMethodIndex(), 330 dex_file, type); 331} 332 333void ThrowNullPointerExceptionFromDexPC(const ThrowLocation& throw_location) { 334 const DexFile::CodeItem* code = MethodHelper(throw_location.GetMethod()).GetCodeItem(); 335 uint32_t throw_dex_pc = throw_location.GetDexPc(); 336 CHECK_LT(throw_dex_pc, code->insns_size_in_code_units_); 337 const Instruction* instr = Instruction::At(&code->insns_[throw_dex_pc]); 338 switch (instr->Opcode()) { 339 case Instruction::INVOKE_DIRECT: 340 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kDirect); 341 break; 342 case Instruction::INVOKE_DIRECT_RANGE: 343 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kDirect); 344 break; 345 case Instruction::INVOKE_VIRTUAL: 346 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kVirtual); 347 break; 348 case Instruction::INVOKE_VIRTUAL_RANGE: 349 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kVirtual); 350 break; 351 case Instruction::INVOKE_INTERFACE: 352 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_35c(), kInterface); 353 break; 354 case Instruction::INVOKE_INTERFACE_RANGE: 355 ThrowNullPointerExceptionForMethodAccess(throw_location, instr->VRegB_3rc(), kInterface); 356 break; 357 case Instruction::INVOKE_VIRTUAL_QUICK: 358 case Instruction::INVOKE_VIRTUAL_RANGE_QUICK: { 359 // Since we replaced the method index, we ask the verifier to tell us which 360 // method is invoked at this location. 361 mirror::ArtMethod* method = 362 verifier::MethodVerifier::FindInvokedMethodAtDexPc(throw_location.GetMethod(), 363 throw_location.GetDexPc()); 364 if (method != NULL) { 365 // NPE with precise message. 366 ThrowNullPointerExceptionForMethodAccess(throw_location, method, kVirtual); 367 } else { 368 // NPE with imprecise message. 369 ThrowNullPointerException(&throw_location, 370 "Attempt to invoke a virtual method on a null object reference"); 371 } 372 break; 373 } 374 case Instruction::IGET: 375 case Instruction::IGET_WIDE: 376 case Instruction::IGET_OBJECT: 377 case Instruction::IGET_BOOLEAN: 378 case Instruction::IGET_BYTE: 379 case Instruction::IGET_CHAR: 380 case Instruction::IGET_SHORT: { 381 mirror::ArtField* field = 382 Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), 383 throw_location.GetMethod(), false); 384 ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */); 385 break; 386 } 387 case Instruction::IGET_QUICK: 388 case Instruction::IGET_WIDE_QUICK: 389 case Instruction::IGET_OBJECT_QUICK: { 390 // Since we replaced the field index, we ask the verifier to tell us which 391 // field is accessed at this location. 392 mirror::ArtField* field = 393 verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(), 394 throw_location.GetDexPc()); 395 if (field != NULL) { 396 // NPE with precise message. 397 ThrowNullPointerExceptionForFieldAccess(throw_location, field, true /* read */); 398 } else { 399 // NPE with imprecise message. 400 ThrowNullPointerException(&throw_location, 401 "Attempt to read from a field on a null object reference"); 402 } 403 break; 404 } 405 case Instruction::IPUT: 406 case Instruction::IPUT_WIDE: 407 case Instruction::IPUT_OBJECT: 408 case Instruction::IPUT_BOOLEAN: 409 case Instruction::IPUT_BYTE: 410 case Instruction::IPUT_CHAR: 411 case Instruction::IPUT_SHORT: { 412 mirror::ArtField* field = 413 Runtime::Current()->GetClassLinker()->ResolveField(instr->VRegC_22c(), 414 throw_location.GetMethod(), false); 415 ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */); 416 break; 417 } 418 case Instruction::IPUT_QUICK: 419 case Instruction::IPUT_WIDE_QUICK: 420 case Instruction::IPUT_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 mirror::ArtField* field = 424 verifier::MethodVerifier::FindAccessedFieldAtDexPc(throw_location.GetMethod(), 425 throw_location.GetDexPc()); 426 if (field != NULL) { 427 // NPE with precise message. 428 ThrowNullPointerExceptionForFieldAccess(throw_location, field, false /* write */); 429 } else { 430 // NPE with imprecise message. 431 ThrowNullPointerException(&throw_location, 432 "Attempt to write to a field on a null object reference"); 433 } 434 break; 435 } 436 case Instruction::AGET: 437 case Instruction::AGET_WIDE: 438 case Instruction::AGET_OBJECT: 439 case Instruction::AGET_BOOLEAN: 440 case Instruction::AGET_BYTE: 441 case Instruction::AGET_CHAR: 442 case Instruction::AGET_SHORT: 443 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, 444 "Attempt to read from null array"); 445 break; 446 case Instruction::APUT: 447 case Instruction::APUT_WIDE: 448 case Instruction::APUT_OBJECT: 449 case Instruction::APUT_BOOLEAN: 450 case Instruction::APUT_BYTE: 451 case Instruction::APUT_CHAR: 452 case Instruction::APUT_SHORT: 453 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, 454 "Attempt to write to null array"); 455 break; 456 case Instruction::ARRAY_LENGTH: 457 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, 458 "Attempt to get length of null array"); 459 break; 460 default: { 461 // TODO: We should have covered all the cases where we expect a NPE above, this 462 // message/logging is so we can improve any cases we've missed in the future. 463 const DexFile& dex_file = 464 *throw_location.GetMethod()->GetDeclaringClass()->GetDexCache()->GetDexFile(); 465 ThrowException(&throw_location, "Ljava/lang/NullPointerException;", NULL, 466 StringPrintf("Null pointer exception during instruction '%s'", 467 instr->DumpString(&dex_file).c_str()).c_str()); 468 break; 469 } 470 } 471} 472 473void ThrowNullPointerException(const ThrowLocation* throw_location, const char* msg) { 474 ThrowException(throw_location, "Ljava/lang/NullPointerException;", NULL, msg); 475} 476 477// RuntimeException 478 479void ThrowRuntimeException(const char* fmt, ...) { 480 va_list args; 481 va_start(args, fmt); 482 ThrowException(NULL, "Ljava/lang/RuntimeException;", NULL, fmt, &args); 483 va_end(args); 484} 485 486// VerifyError 487 488void ThrowVerifyError(mirror::Class* referrer, const char* fmt, ...) { 489 va_list args; 490 va_start(args, fmt); 491 ThrowException(NULL, "Ljava/lang/VerifyError;", referrer, fmt, &args); 492 va_end(args); 493} 494 495} // namespace art 496