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