reflection.cc revision e401d146407d61eeb99f8d6176b2ac13c4df1e33
1/* 2 * Copyright (C) 2011 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 "reflection-inl.h" 18 19#include "art_field-inl.h" 20#include "art_method-inl.h" 21#include "class_linker.h" 22#include "common_throws.h" 23#include "dex_file-inl.h" 24#include "entrypoints/entrypoint_utils.h" 25#include "indirect_reference_table-inl.h" 26#include "jni_internal.h" 27#include "mirror/abstract_method.h" 28#include "mirror/class-inl.h" 29#include "mirror/object_array-inl.h" 30#include "nth_caller_visitor.h" 31#include "scoped_thread_state_change.h" 32#include "stack.h" 33#include "well_known_classes.h" 34 35namespace art { 36 37class ArgArray { 38 public: 39 explicit ArgArray(const char* shorty, uint32_t shorty_len) 40 : shorty_(shorty), shorty_len_(shorty_len), num_bytes_(0) { 41 size_t num_slots = shorty_len + 1; // +1 in case of receiver. 42 if (LIKELY((num_slots * 2) < kSmallArgArraySize)) { 43 // We can trivially use the small arg array. 44 arg_array_ = small_arg_array_; 45 } else { 46 // Analyze shorty to see if we need the large arg array. 47 for (size_t i = 1; i < shorty_len; ++i) { 48 char c = shorty[i]; 49 if (c == 'J' || c == 'D') { 50 num_slots++; 51 } 52 } 53 if (num_slots <= kSmallArgArraySize) { 54 arg_array_ = small_arg_array_; 55 } else { 56 large_arg_array_.reset(new uint32_t[num_slots]); 57 arg_array_ = large_arg_array_.get(); 58 } 59 } 60 } 61 62 uint32_t* GetArray() { 63 return arg_array_; 64 } 65 66 uint32_t GetNumBytes() { 67 return num_bytes_; 68 } 69 70 void Append(uint32_t value) { 71 arg_array_[num_bytes_ / 4] = value; 72 num_bytes_ += 4; 73 } 74 75 void Append(mirror::Object* obj) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 76 Append(StackReference<mirror::Object>::FromMirrorPtr(obj).AsVRegValue()); 77 } 78 79 void AppendWide(uint64_t value) { 80 arg_array_[num_bytes_ / 4] = value; 81 arg_array_[(num_bytes_ / 4) + 1] = value >> 32; 82 num_bytes_ += 8; 83 } 84 85 void AppendFloat(float value) { 86 jvalue jv; 87 jv.f = value; 88 Append(jv.i); 89 } 90 91 void AppendDouble(double value) { 92 jvalue jv; 93 jv.d = value; 94 AppendWide(jv.j); 95 } 96 97 void BuildArgArrayFromVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, 98 mirror::Object* receiver, va_list ap) 99 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 100 // Set receiver if non-null (method is not static) 101 if (receiver != nullptr) { 102 Append(receiver); 103 } 104 for (size_t i = 1; i < shorty_len_; ++i) { 105 switch (shorty_[i]) { 106 case 'Z': 107 case 'B': 108 case 'C': 109 case 'S': 110 case 'I': 111 Append(va_arg(ap, jint)); 112 break; 113 case 'F': 114 AppendFloat(va_arg(ap, jdouble)); 115 break; 116 case 'L': 117 Append(soa.Decode<mirror::Object*>(va_arg(ap, jobject))); 118 break; 119 case 'D': 120 AppendDouble(va_arg(ap, jdouble)); 121 break; 122 case 'J': 123 AppendWide(va_arg(ap, jlong)); 124 break; 125#ifndef NDEBUG 126 default: 127 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i]; 128#endif 129 } 130 } 131 } 132 133 void BuildArgArrayFromJValues(const ScopedObjectAccessAlreadyRunnable& soa, 134 mirror::Object* receiver, jvalue* args) 135 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 136 // Set receiver if non-null (method is not static) 137 if (receiver != nullptr) { 138 Append(receiver); 139 } 140 for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) { 141 switch (shorty_[i]) { 142 case 'Z': 143 Append(args[args_offset].z); 144 break; 145 case 'B': 146 Append(args[args_offset].b); 147 break; 148 case 'C': 149 Append(args[args_offset].c); 150 break; 151 case 'S': 152 Append(args[args_offset].s); 153 break; 154 case 'I': 155 case 'F': 156 Append(args[args_offset].i); 157 break; 158 case 'L': 159 Append(soa.Decode<mirror::Object*>(args[args_offset].l)); 160 break; 161 case 'D': 162 case 'J': 163 AppendWide(args[args_offset].j); 164 break; 165#ifndef NDEBUG 166 default: 167 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i]; 168#endif 169 } 170 } 171 } 172 173 void BuildArgArrayFromFrame(ShadowFrame* shadow_frame, uint32_t arg_offset) 174 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 175 // Set receiver if non-null (method is not static) 176 size_t cur_arg = arg_offset; 177 if (!shadow_frame->GetMethod()->IsStatic()) { 178 Append(shadow_frame->GetVReg(cur_arg)); 179 cur_arg++; 180 } 181 for (size_t i = 1; i < shorty_len_; ++i) { 182 switch (shorty_[i]) { 183 case 'Z': 184 case 'B': 185 case 'C': 186 case 'S': 187 case 'I': 188 case 'F': 189 case 'L': 190 Append(shadow_frame->GetVReg(cur_arg)); 191 cur_arg++; 192 break; 193 case 'D': 194 case 'J': 195 AppendWide(shadow_frame->GetVRegLong(cur_arg)); 196 cur_arg++; 197 cur_arg++; 198 break; 199#ifndef NDEBUG 200 default: 201 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i]; 202#endif 203 } 204 } 205 } 206 207 static void ThrowIllegalPrimitiveArgumentException(const char* expected, 208 const char* found_descriptor) 209 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 210 ThrowIllegalArgumentException( 211 StringPrintf("Invalid primitive conversion from %s to %s", expected, 212 PrettyDescriptor(found_descriptor).c_str()).c_str()); 213 } 214 215 bool BuildArgArrayFromObjectArray(mirror::Object* receiver, 216 mirror::ObjectArray<mirror::Object>* args, ArtMethod* m) 217 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 218 const DexFile::TypeList* classes = m->GetParameterTypeList(); 219 // Set receiver if non-null (method is not static) 220 if (receiver != nullptr) { 221 Append(receiver); 222 } 223 for (size_t i = 1, args_offset = 0; i < shorty_len_; ++i, ++args_offset) { 224 mirror::Object* arg = args->Get(args_offset); 225 if (((shorty_[i] == 'L') && (arg != nullptr)) || ((arg == nullptr && shorty_[i] != 'L'))) { 226 mirror::Class* dst_class = 227 m->GetClassFromTypeIndex(classes->GetTypeItem(args_offset).type_idx_, true); 228 if (UNLIKELY(arg == nullptr || !arg->InstanceOf(dst_class))) { 229 ThrowIllegalArgumentException( 230 StringPrintf("method %s argument %zd has type %s, got %s", 231 PrettyMethod(m, false).c_str(), 232 args_offset + 1, // Humans don't count from 0. 233 PrettyDescriptor(dst_class).c_str(), 234 PrettyTypeOf(arg).c_str()).c_str()); 235 return false; 236 } 237 } 238 239#define DO_FIRST_ARG(match_descriptor, get_fn, append) { \ 240 if (LIKELY(arg != nullptr && arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \ 241 ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \ 242 append(primitive_field-> get_fn(arg)); 243 244#define DO_ARG(match_descriptor, get_fn, append) \ 245 } else if (LIKELY(arg != nullptr && \ 246 arg->GetClass<>()->DescriptorEquals(match_descriptor))) { \ 247 ArtField* primitive_field = arg->GetClass()->GetInstanceField(0); \ 248 append(primitive_field-> get_fn(arg)); 249 250#define DO_FAIL(expected) \ 251 } else { \ 252 if (arg->GetClass<>()->IsPrimitive()) { \ 253 std::string temp; \ 254 ThrowIllegalPrimitiveArgumentException(expected, \ 255 arg->GetClass<>()->GetDescriptor(&temp)); \ 256 } else { \ 257 ThrowIllegalArgumentException(\ 258 StringPrintf("method %s argument %zd has type %s, got %s", \ 259 PrettyMethod(m, false).c_str(), \ 260 args_offset + 1, \ 261 expected, \ 262 PrettyTypeOf(arg).c_str()).c_str()); \ 263 } \ 264 return false; \ 265 } } 266 267 switch (shorty_[i]) { 268 case 'L': 269 Append(arg); 270 break; 271 case 'Z': 272 DO_FIRST_ARG("Ljava/lang/Boolean;", GetBoolean, Append) 273 DO_FAIL("boolean") 274 break; 275 case 'B': 276 DO_FIRST_ARG("Ljava/lang/Byte;", GetByte, Append) 277 DO_FAIL("byte") 278 break; 279 case 'C': 280 DO_FIRST_ARG("Ljava/lang/Character;", GetChar, Append) 281 DO_FAIL("char") 282 break; 283 case 'S': 284 DO_FIRST_ARG("Ljava/lang/Short;", GetShort, Append) 285 DO_ARG("Ljava/lang/Byte;", GetByte, Append) 286 DO_FAIL("short") 287 break; 288 case 'I': 289 DO_FIRST_ARG("Ljava/lang/Integer;", GetInt, Append) 290 DO_ARG("Ljava/lang/Character;", GetChar, Append) 291 DO_ARG("Ljava/lang/Short;", GetShort, Append) 292 DO_ARG("Ljava/lang/Byte;", GetByte, Append) 293 DO_FAIL("int") 294 break; 295 case 'J': 296 DO_FIRST_ARG("Ljava/lang/Long;", GetLong, AppendWide) 297 DO_ARG("Ljava/lang/Integer;", GetInt, AppendWide) 298 DO_ARG("Ljava/lang/Character;", GetChar, AppendWide) 299 DO_ARG("Ljava/lang/Short;", GetShort, AppendWide) 300 DO_ARG("Ljava/lang/Byte;", GetByte, AppendWide) 301 DO_FAIL("long") 302 break; 303 case 'F': 304 DO_FIRST_ARG("Ljava/lang/Float;", GetFloat, AppendFloat) 305 DO_ARG("Ljava/lang/Long;", GetLong, AppendFloat) 306 DO_ARG("Ljava/lang/Integer;", GetInt, AppendFloat) 307 DO_ARG("Ljava/lang/Character;", GetChar, AppendFloat) 308 DO_ARG("Ljava/lang/Short;", GetShort, AppendFloat) 309 DO_ARG("Ljava/lang/Byte;", GetByte, AppendFloat) 310 DO_FAIL("float") 311 break; 312 case 'D': 313 DO_FIRST_ARG("Ljava/lang/Double;", GetDouble, AppendDouble) 314 DO_ARG("Ljava/lang/Float;", GetFloat, AppendDouble) 315 DO_ARG("Ljava/lang/Long;", GetLong, AppendDouble) 316 DO_ARG("Ljava/lang/Integer;", GetInt, AppendDouble) 317 DO_ARG("Ljava/lang/Character;", GetChar, AppendDouble) 318 DO_ARG("Ljava/lang/Short;", GetShort, AppendDouble) 319 DO_ARG("Ljava/lang/Byte;", GetByte, AppendDouble) 320 DO_FAIL("double") 321 break; 322#ifndef NDEBUG 323 default: 324 LOG(FATAL) << "Unexpected shorty character: " << shorty_[i]; 325 UNREACHABLE(); 326#endif 327 } 328#undef DO_FIRST_ARG 329#undef DO_ARG 330#undef DO_FAIL 331 } 332 return true; 333 } 334 335 private: 336 enum { kSmallArgArraySize = 16 }; 337 const char* const shorty_; 338 const uint32_t shorty_len_; 339 uint32_t num_bytes_; 340 uint32_t* arg_array_; 341 uint32_t small_arg_array_[kSmallArgArraySize]; 342 std::unique_ptr<uint32_t[]> large_arg_array_; 343}; 344 345static void CheckMethodArguments(JavaVMExt* vm, ArtMethod* m, uint32_t* args) 346 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 347 const DexFile::TypeList* params = m->GetParameterTypeList(); 348 if (params == nullptr) { 349 return; // No arguments so nothing to check. 350 } 351 uint32_t offset = 0; 352 uint32_t num_params = params->Size(); 353 size_t error_count = 0; 354 if (!m->IsStatic()) { 355 offset = 1; 356 } 357 // TODO: If args contain object references, it may cause problems. 358 Thread* const self = Thread::Current(); 359 for (uint32_t i = 0; i < num_params; i++) { 360 uint16_t type_idx = params->GetTypeItem(i).type_idx_; 361 mirror::Class* param_type = m->GetClassFromTypeIndex(type_idx, true); 362 if (param_type == nullptr) { 363 CHECK(self->IsExceptionPending()); 364 LOG(ERROR) << "Internal error: unresolvable type for argument type in JNI invoke: " 365 << m->GetTypeDescriptorFromTypeIdx(type_idx) << "\n" 366 << self->GetException()->Dump(); 367 self->ClearException(); 368 ++error_count; 369 } else if (!param_type->IsPrimitive()) { 370 // TODO: There is a compaction bug here since GetClassFromTypeIdx can cause thread suspension, 371 // this is a hard to fix problem since the args can contain Object*, we need to save and 372 // restore them by using a visitor similar to the ones used in the trampoline entrypoints. 373 mirror::Object* argument = 374 (reinterpret_cast<StackReference<mirror::Object>*>(&args[i + offset]))->AsMirrorPtr(); 375 if (argument != nullptr && !argument->InstanceOf(param_type)) { 376 LOG(ERROR) << "JNI ERROR (app bug): attempt to pass an instance of " 377 << PrettyTypeOf(argument) << " as argument " << (i + 1) 378 << " to " << PrettyMethod(m); 379 ++error_count; 380 } 381 } else if (param_type->IsPrimitiveLong() || param_type->IsPrimitiveDouble()) { 382 offset++; 383 } else { 384 int32_t arg = static_cast<int32_t>(args[i + offset]); 385 if (param_type->IsPrimitiveBoolean()) { 386 if (arg != JNI_TRUE && arg != JNI_FALSE) { 387 LOG(ERROR) << "JNI ERROR (app bug): expected jboolean (0/1) but got value of " 388 << arg << " as argument " << (i + 1) << " to " << PrettyMethod(m); 389 ++error_count; 390 } 391 } else if (param_type->IsPrimitiveByte()) { 392 if (arg < -128 || arg > 127) { 393 LOG(ERROR) << "JNI ERROR (app bug): expected jbyte but got value of " 394 << arg << " as argument " << (i + 1) << " to " << PrettyMethod(m); 395 ++error_count; 396 } 397 } else if (param_type->IsPrimitiveChar()) { 398 if (args[i + offset] > 0xFFFF) { 399 LOG(ERROR) << "JNI ERROR (app bug): expected jchar but got value of " 400 << arg << " as argument " << (i + 1) << " to " << PrettyMethod(m); 401 ++error_count; 402 } 403 } else if (param_type->IsPrimitiveShort()) { 404 if (arg < -32768 || arg > 0x7FFF) { 405 LOG(ERROR) << "JNI ERROR (app bug): expected jshort but got value of " 406 << arg << " as argument " << (i + 1) << " to " << PrettyMethod(m); 407 ++error_count; 408 } 409 } 410 } 411 } 412 if (UNLIKELY(error_count > 0)) { 413 // TODO: pass the JNI function name (such as "CallVoidMethodV") through so we can call JniAbort 414 // with an argument. 415 vm->JniAbortF(nullptr, "bad arguments passed to %s (see above for details)", 416 PrettyMethod(m).c_str()); 417 } 418} 419 420static ArtMethod* FindVirtualMethod(mirror::Object* receiver, ArtMethod* method) 421 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 422 return receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(method, sizeof(void*)); 423} 424 425 426static void InvokeWithArgArray(const ScopedObjectAccessAlreadyRunnable& soa, 427 ArtMethod* method, ArgArray* arg_array, JValue* result, 428 const char* shorty) 429 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 430 uint32_t* args = arg_array->GetArray(); 431 if (UNLIKELY(soa.Env()->check_jni)) { 432 CheckMethodArguments(soa.Vm(), method->GetInterfaceMethodIfProxy(sizeof(void*)), args); 433 } 434 method->Invoke(soa.Self(), args, arg_array->GetNumBytes(), result, shorty); 435} 436 437JValue InvokeWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid, 438 va_list args) 439 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 440 // We want to make sure that the stack is not within a small distance from the 441 // protected region in case we are calling into a leaf function whose stack 442 // check has been elided. 443 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) { 444 ThrowStackOverflowError(soa.Self()); 445 return JValue(); 446 } 447 448 ArtMethod* method = soa.DecodeMethod(mid); 449 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); 450 if (is_string_init) { 451 // Replace calls to String.<init> with equivalent StringFactory call. 452 method = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid)); 453 } 454 mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj); 455 uint32_t shorty_len = 0; 456 const char* shorty = method->GetShorty(&shorty_len); 457 JValue result; 458 ArgArray arg_array(shorty, shorty_len); 459 arg_array.BuildArgArrayFromVarArgs(soa, receiver, args); 460 InvokeWithArgArray(soa, method, &arg_array, &result, shorty); 461 if (is_string_init) { 462 // For string init, remap original receiver to StringFactory result. 463 UpdateReference(soa.Self(), obj, result.GetL()); 464 } 465 return result; 466} 467 468JValue InvokeWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, jobject obj, jmethodID mid, 469 jvalue* args) { 470 // We want to make sure that the stack is not within a small distance from the 471 // protected region in case we are calling into a leaf function whose stack 472 // check has been elided. 473 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) { 474 ThrowStackOverflowError(soa.Self()); 475 return JValue(); 476 } 477 478 ArtMethod* method = soa.DecodeMethod(mid); 479 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); 480 if (is_string_init) { 481 // Replace calls to String.<init> with equivalent StringFactory call. 482 method = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid)); 483 } 484 mirror::Object* receiver = method->IsStatic() ? nullptr : soa.Decode<mirror::Object*>(obj); 485 uint32_t shorty_len = 0; 486 const char* shorty = method->GetShorty(&shorty_len); 487 JValue result; 488 ArgArray arg_array(shorty, shorty_len); 489 arg_array.BuildArgArrayFromJValues(soa, receiver, args); 490 InvokeWithArgArray(soa, method, &arg_array, &result, shorty); 491 if (is_string_init) { 492 // For string init, remap original receiver to StringFactory result. 493 UpdateReference(soa.Self(), obj, result.GetL()); 494 } 495 return result; 496} 497 498JValue InvokeVirtualOrInterfaceWithJValues(const ScopedObjectAccessAlreadyRunnable& soa, 499 jobject obj, jmethodID mid, jvalue* args) { 500 // We want to make sure that the stack is not within a small distance from the 501 // protected region in case we are calling into a leaf function whose stack 502 // check has been elided. 503 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) { 504 ThrowStackOverflowError(soa.Self()); 505 return JValue(); 506 } 507 508 mirror::Object* receiver = soa.Decode<mirror::Object*>(obj); 509 ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid)); 510 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); 511 if (is_string_init) { 512 // Replace calls to String.<init> with equivalent StringFactory call. 513 method = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid)); 514 receiver = nullptr; 515 } 516 uint32_t shorty_len = 0; 517 const char* shorty = method->GetShorty(&shorty_len); 518 JValue result; 519 ArgArray arg_array(shorty, shorty_len); 520 arg_array.BuildArgArrayFromJValues(soa, receiver, args); 521 InvokeWithArgArray(soa, method, &arg_array, &result, shorty); 522 if (is_string_init) { 523 // For string init, remap original receiver to StringFactory result. 524 UpdateReference(soa.Self(), obj, result.GetL()); 525 } 526 return result; 527} 528 529JValue InvokeVirtualOrInterfaceWithVarArgs(const ScopedObjectAccessAlreadyRunnable& soa, 530 jobject obj, jmethodID mid, va_list args) { 531 // We want to make sure that the stack is not within a small distance from the 532 // protected region in case we are calling into a leaf function whose stack 533 // check has been elided. 534 if (UNLIKELY(__builtin_frame_address(0) < soa.Self()->GetStackEnd())) { 535 ThrowStackOverflowError(soa.Self()); 536 return JValue(); 537 } 538 539 mirror::Object* receiver = soa.Decode<mirror::Object*>(obj); 540 ArtMethod* method = FindVirtualMethod(receiver, soa.DecodeMethod(mid)); 541 bool is_string_init = method->GetDeclaringClass()->IsStringClass() && method->IsConstructor(); 542 if (is_string_init) { 543 // Replace calls to String.<init> with equivalent StringFactory call. 544 method = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid)); 545 receiver = nullptr; 546 } 547 uint32_t shorty_len = 0; 548 const char* shorty = method->GetShorty(&shorty_len); 549 JValue result; 550 ArgArray arg_array(shorty, shorty_len); 551 arg_array.BuildArgArrayFromVarArgs(soa, receiver, args); 552 InvokeWithArgArray(soa, method, &arg_array, &result, shorty); 553 if (is_string_init) { 554 // For string init, remap original receiver to StringFactory result. 555 UpdateReference(soa.Self(), obj, result.GetL()); 556 } 557 return result; 558} 559 560jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaMethod, 561 jobject javaReceiver, jobject javaArgs, size_t num_frames) { 562 // We want to make sure that the stack is not within a small distance from the 563 // protected region in case we are calling into a leaf function whose stack 564 // check has been elided. 565 if (UNLIKELY(__builtin_frame_address(0) < 566 soa.Self()->GetStackEndForInterpreter(true))) { 567 ThrowStackOverflowError(soa.Self()); 568 return nullptr; 569 } 570 571 auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(javaMethod); 572 const bool accessible = abstract_method->IsAccessible(); 573 ArtMethod* m = abstract_method->GetArtMethod(); 574 575 mirror::Class* declaring_class = m->GetDeclaringClass(); 576 if (UNLIKELY(!declaring_class->IsInitialized())) { 577 StackHandleScope<1> hs(soa.Self()); 578 Handle<mirror::Class> h_class(hs.NewHandle(declaring_class)); 579 if (!Runtime::Current()->GetClassLinker()->EnsureInitialized(soa.Self(), h_class, true, true)) { 580 return nullptr; 581 } 582 declaring_class = h_class.Get(); 583 } 584 585 mirror::Object* receiver = nullptr; 586 if (!m->IsStatic()) { 587 // Replace calls to String.<init> with equivalent StringFactory call. 588 if (declaring_class->IsStringClass() && m->IsConstructor()) { 589 jmethodID mid = soa.EncodeMethod(m); 590 m = soa.DecodeMethod(WellKnownClasses::StringInitToStringFactoryMethodID(mid)); 591 CHECK(javaReceiver == nullptr); 592 } else { 593 // Check that the receiver is non-null and an instance of the field's declaring class. 594 receiver = soa.Decode<mirror::Object*>(javaReceiver); 595 if (!VerifyObjectIsClass(receiver, declaring_class)) { 596 return nullptr; 597 } 598 599 // Find the actual implementation of the virtual method. 600 m = receiver->GetClass()->FindVirtualMethodForVirtualOrInterface(m, sizeof(void*)); 601 } 602 } 603 604 // Get our arrays of arguments and their types, and check they're the same size. 605 auto* objects = soa.Decode<mirror::ObjectArray<mirror::Object>*>(javaArgs); 606 auto* np_method = m->GetInterfaceMethodIfProxy(sizeof(void*)); 607 const DexFile::TypeList* classes = np_method->GetParameterTypeList(); 608 uint32_t classes_size = (classes == nullptr) ? 0 : classes->Size(); 609 uint32_t arg_count = (objects != nullptr) ? objects->GetLength() : 0; 610 if (arg_count != classes_size) { 611 ThrowIllegalArgumentException(StringPrintf("Wrong number of arguments; expected %d, got %d", 612 classes_size, arg_count).c_str()); 613 return nullptr; 614 } 615 616 // If method is not set to be accessible, verify it can be accessed by the caller. 617 mirror::Class* calling_class = nullptr; 618 if (!accessible && !VerifyAccess(soa.Self(), receiver, declaring_class, m->GetAccessFlags(), 619 &calling_class, num_frames)) { 620 ThrowIllegalAccessException( 621 StringPrintf("Class %s cannot access %s method %s of class %s", 622 calling_class == nullptr ? "null" : PrettyClass(calling_class).c_str(), 623 PrettyJavaAccessFlags(m->GetAccessFlags()).c_str(), 624 PrettyMethod(m).c_str(), 625 m->GetDeclaringClass() == nullptr ? "null" : 626 PrettyClass(m->GetDeclaringClass()).c_str()).c_str()); 627 return nullptr; 628 } 629 630 // Invoke the method. 631 JValue result; 632 uint32_t shorty_len = 0; 633 const char* shorty = np_method->GetShorty(&shorty_len); 634 ArgArray arg_array(shorty, shorty_len); 635 if (!arg_array.BuildArgArrayFromObjectArray(receiver, objects, np_method)) { 636 CHECK(soa.Self()->IsExceptionPending()); 637 return nullptr; 638 } 639 640 InvokeWithArgArray(soa, m, &arg_array, &result, shorty); 641 642 // Wrap any exception with "Ljava/lang/reflect/InvocationTargetException;" and return early. 643 if (soa.Self()->IsExceptionPending()) { 644 // If we get another exception when we are trying to wrap, then just use that instead. 645 jthrowable th = soa.Env()->ExceptionOccurred(); 646 soa.Self()->ClearException(); 647 jclass exception_class = soa.Env()->FindClass("java/lang/reflect/InvocationTargetException"); 648 if (exception_class == nullptr) { 649 soa.Self()->AssertPendingOOMException(); 650 return nullptr; 651 } 652 jmethodID mid = soa.Env()->GetMethodID(exception_class, "<init>", "(Ljava/lang/Throwable;)V"); 653 CHECK(mid != nullptr); 654 jobject exception_instance = soa.Env()->NewObject(exception_class, mid, th); 655 if (exception_instance == nullptr) { 656 soa.Self()->AssertPendingOOMException(); 657 return nullptr; 658 } 659 soa.Env()->Throw(reinterpret_cast<jthrowable>(exception_instance)); 660 return nullptr; 661 } 662 663 // Box if necessary and return. 664 return soa.AddLocalReference<jobject>(BoxPrimitive(Primitive::GetType(shorty[0]), result)); 665} 666 667mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) { 668 if (src_class == Primitive::kPrimNot) { 669 return value.GetL(); 670 } 671 if (src_class == Primitive::kPrimVoid) { 672 // There's no such thing as a void field, and void methods invoked via reflection return null. 673 return nullptr; 674 } 675 676 jmethodID m = nullptr; 677 const char* shorty; 678 switch (src_class) { 679 case Primitive::kPrimBoolean: 680 m = WellKnownClasses::java_lang_Boolean_valueOf; 681 shorty = "LZ"; 682 break; 683 case Primitive::kPrimByte: 684 m = WellKnownClasses::java_lang_Byte_valueOf; 685 shorty = "LB"; 686 break; 687 case Primitive::kPrimChar: 688 m = WellKnownClasses::java_lang_Character_valueOf; 689 shorty = "LC"; 690 break; 691 case Primitive::kPrimDouble: 692 m = WellKnownClasses::java_lang_Double_valueOf; 693 shorty = "LD"; 694 break; 695 case Primitive::kPrimFloat: 696 m = WellKnownClasses::java_lang_Float_valueOf; 697 shorty = "LF"; 698 break; 699 case Primitive::kPrimInt: 700 m = WellKnownClasses::java_lang_Integer_valueOf; 701 shorty = "LI"; 702 break; 703 case Primitive::kPrimLong: 704 m = WellKnownClasses::java_lang_Long_valueOf; 705 shorty = "LJ"; 706 break; 707 case Primitive::kPrimShort: 708 m = WellKnownClasses::java_lang_Short_valueOf; 709 shorty = "LS"; 710 break; 711 default: 712 LOG(FATAL) << static_cast<int>(src_class); 713 shorty = nullptr; 714 } 715 716 ScopedObjectAccessUnchecked soa(Thread::Current()); 717 DCHECK_EQ(soa.Self()->GetState(), kRunnable); 718 719 ArgArray arg_array(shorty, 2); 720 JValue result; 721 if (src_class == Primitive::kPrimDouble || src_class == Primitive::kPrimLong) { 722 arg_array.AppendWide(value.GetJ()); 723 } else { 724 arg_array.Append(value.GetI()); 725 } 726 727 soa.DecodeMethod(m)->Invoke(soa.Self(), arg_array.GetArray(), arg_array.GetNumBytes(), 728 &result, shorty); 729 return result.GetL(); 730} 731 732static std::string UnboxingFailureKind(ArtField* f) 733 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 734 if (f != nullptr) { 735 return "field " + PrettyField(f, false); 736 } 737 return "result"; 738} 739 740static bool UnboxPrimitive(mirror::Object* o, 741 mirror::Class* dst_class, ArtField* f, 742 JValue* unboxed_value) 743 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 744 bool unbox_for_result = (f == nullptr); 745 if (!dst_class->IsPrimitive()) { 746 if (UNLIKELY(o != nullptr && !o->InstanceOf(dst_class))) { 747 if (!unbox_for_result) { 748 ThrowIllegalArgumentException(StringPrintf("%s has type %s, got %s", 749 UnboxingFailureKind(f).c_str(), 750 PrettyDescriptor(dst_class).c_str(), 751 PrettyTypeOf(o).c_str()).c_str()); 752 } else { 753 ThrowClassCastException(StringPrintf("Couldn't convert result of type %s to %s", 754 PrettyTypeOf(o).c_str(), 755 PrettyDescriptor(dst_class).c_str()).c_str()); 756 } 757 return false; 758 } 759 unboxed_value->SetL(o); 760 return true; 761 } 762 if (UNLIKELY(dst_class->GetPrimitiveType() == Primitive::kPrimVoid)) { 763 ThrowIllegalArgumentException(StringPrintf("Can't unbox %s to void", 764 UnboxingFailureKind(f).c_str()).c_str()); 765 return false; 766 } 767 if (UNLIKELY(o == nullptr)) { 768 if (!unbox_for_result) { 769 ThrowIllegalArgumentException(StringPrintf("%s has type %s, got null", 770 UnboxingFailureKind(f).c_str(), 771 PrettyDescriptor(dst_class).c_str()).c_str()); 772 } else { 773 ThrowNullPointerException(StringPrintf("Expected to unbox a '%s' primitive type but was returned null", 774 PrettyDescriptor(dst_class).c_str()).c_str()); 775 } 776 return false; 777 } 778 779 JValue boxed_value; 780 mirror::Class* klass = o->GetClass(); 781 mirror::Class* src_class = nullptr; 782 ClassLinker* const class_linker = Runtime::Current()->GetClassLinker(); 783 ArtField* primitive_field = &klass->GetIFields()[0]; 784 if (klass->DescriptorEquals("Ljava/lang/Boolean;")) { 785 src_class = class_linker->FindPrimitiveClass('Z'); 786 boxed_value.SetZ(primitive_field->GetBoolean(o)); 787 } else if (klass->DescriptorEquals("Ljava/lang/Byte;")) { 788 src_class = class_linker->FindPrimitiveClass('B'); 789 boxed_value.SetB(primitive_field->GetByte(o)); 790 } else if (klass->DescriptorEquals("Ljava/lang/Character;")) { 791 src_class = class_linker->FindPrimitiveClass('C'); 792 boxed_value.SetC(primitive_field->GetChar(o)); 793 } else if (klass->DescriptorEquals("Ljava/lang/Float;")) { 794 src_class = class_linker->FindPrimitiveClass('F'); 795 boxed_value.SetF(primitive_field->GetFloat(o)); 796 } else if (klass->DescriptorEquals("Ljava/lang/Double;")) { 797 src_class = class_linker->FindPrimitiveClass('D'); 798 boxed_value.SetD(primitive_field->GetDouble(o)); 799 } else if (klass->DescriptorEquals("Ljava/lang/Integer;")) { 800 src_class = class_linker->FindPrimitiveClass('I'); 801 boxed_value.SetI(primitive_field->GetInt(o)); 802 } else if (klass->DescriptorEquals("Ljava/lang/Long;")) { 803 src_class = class_linker->FindPrimitiveClass('J'); 804 boxed_value.SetJ(primitive_field->GetLong(o)); 805 } else if (klass->DescriptorEquals("Ljava/lang/Short;")) { 806 src_class = class_linker->FindPrimitiveClass('S'); 807 boxed_value.SetS(primitive_field->GetShort(o)); 808 } else { 809 std::string temp; 810 ThrowIllegalArgumentException( 811 StringPrintf("%s has type %s, got %s", UnboxingFailureKind(f).c_str(), 812 PrettyDescriptor(dst_class).c_str(), 813 PrettyDescriptor(o->GetClass()->GetDescriptor(&temp)).c_str()).c_str()); 814 return false; 815 } 816 817 return ConvertPrimitiveValue(unbox_for_result, 818 src_class->GetPrimitiveType(), dst_class->GetPrimitiveType(), 819 boxed_value, unboxed_value); 820} 821 822bool UnboxPrimitiveForField(mirror::Object* o, mirror::Class* dst_class, ArtField* f, 823 JValue* unboxed_value) { 824 DCHECK(f != nullptr); 825 return UnboxPrimitive(o, dst_class, f, unboxed_value); 826} 827 828bool UnboxPrimitiveForResult(mirror::Object* o, mirror::Class* dst_class, JValue* unboxed_value) { 829 return UnboxPrimitive(o, dst_class, nullptr, unboxed_value); 830} 831 832mirror::Class* GetCallingClass(Thread* self, size_t num_frames) { 833 NthCallerVisitor visitor(self, num_frames); 834 visitor.WalkStack(); 835 return visitor.caller != nullptr ? visitor.caller->GetDeclaringClass() : nullptr; 836} 837 838bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class, 839 uint32_t access_flags, mirror::Class** calling_class, size_t num_frames) { 840 if ((access_flags & kAccPublic) != 0) { 841 return true; 842 } 843 auto* klass = GetCallingClass(self, num_frames); 844 if (UNLIKELY(klass == nullptr)) { 845 // The caller is an attached native thread. 846 return false; 847 } 848 *calling_class = klass; 849 return VerifyAccess(self, obj, declaring_class, access_flags, klass); 850} 851 852bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class, 853 uint32_t access_flags, mirror::Class* calling_class) { 854 if (calling_class == declaring_class) { 855 return true; 856 } 857 ScopedAssertNoThreadSuspension sants(self, "verify-access"); 858 if ((access_flags & kAccPrivate) != 0) { 859 return false; 860 } 861 if ((access_flags & kAccProtected) != 0) { 862 if (obj != nullptr && !obj->InstanceOf(calling_class) && 863 !declaring_class->IsInSamePackage(calling_class)) { 864 return false; 865 } else if (declaring_class->IsAssignableFrom(calling_class)) { 866 return true; 867 } 868 } 869 return declaring_class->IsInSamePackage(calling_class); 870} 871 872void InvalidReceiverError(mirror::Object* o, mirror::Class* c) { 873 std::string expected_class_name(PrettyDescriptor(c)); 874 std::string actual_class_name(PrettyTypeOf(o)); 875 ThrowIllegalArgumentException(StringPrintf("Expected receiver of type %s, but got %s", 876 expected_class_name.c_str(), 877 actual_class_name.c_str()).c_str()); 878} 879 880// This only works if there's one reference which points to the object in obj. 881// Will need to be fixed if there's cases where it's not. 882void UpdateReference(Thread* self, jobject obj, mirror::Object* result) { 883 IndirectRef ref = reinterpret_cast<IndirectRef>(obj); 884 IndirectRefKind kind = GetIndirectRefKind(ref); 885 if (kind == kLocal) { 886 self->GetJniEnv()->locals.Update(obj, result); 887 } else if (kind == kHandleScopeOrInvalid) { 888 LOG(FATAL) << "Unsupported UpdateReference for kind kHandleScopeOrInvalid"; 889 } else if (kind == kGlobal) { 890 self->GetJniEnv()->vm->UpdateGlobal(self, ref, result); 891 } else { 892 DCHECK_EQ(kind, kWeakGlobal); 893 self->GetJniEnv()->vm->UpdateWeakGlobal(self, ref, result); 894 } 895} 896 897} // namespace art 898