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