java_lang_Class.cc revision fc58af45e342ba9e18bbdf597f205a58ec731658
1/*
2 * Copyright (C) 2008 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 "java_lang_Class.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 "jni_internal.h"
24#include "nth_caller_visitor.h"
25#include "mirror/class-inl.h"
26#include "mirror/class_loader.h"
27#include "mirror/field-inl.h"
28#include "mirror/method.h"
29#include "mirror/object-inl.h"
30#include "mirror/object_array-inl.h"
31#include "mirror/string-inl.h"
32#include "scoped_thread_state_change.h"
33#include "scoped_fast_native_object_access.h"
34#include "ScopedLocalRef.h"
35#include "ScopedUtfChars.h"
36#include "utf.h"
37#include "well_known_classes.h"
38
39namespace art {
40
41ALWAYS_INLINE static inline mirror::Class* DecodeClass(
42    const ScopedFastNativeObjectAccess& soa, jobject java_class)
43    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
44  mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
45  DCHECK(c != NULL);
46  DCHECK(c->IsClass());
47  // TODO: we could EnsureInitialized here, rather than on every reflective get/set or invoke .
48  // For now, we conservatively preserve the old dalvik behavior. A quick "IsInitialized" check
49  // every time probably doesn't make much difference to reflection performance anyway.
50  return c;
51}
52
53// "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
54static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize,
55                                 jobject javaLoader) {
56  ScopedFastNativeObjectAccess soa(env);
57  ScopedUtfChars name(env, javaName);
58  if (name.c_str() == nullptr) {
59    return nullptr;
60  }
61
62  // We need to validate and convert the name (from x.y.z to x/y/z).  This
63  // is especially handy for array types, since we want to avoid
64  // auto-generating bogus array classes.
65  if (!IsValidBinaryClassName(name.c_str())) {
66    soa.Self()->ThrowNewExceptionF("Ljava/lang/ClassNotFoundException;",
67                                   "Invalid name: %s", name.c_str());
68    return nullptr;
69  }
70
71  std::string descriptor(DotToDescriptor(name.c_str()));
72  StackHandleScope<2> hs(soa.Self());
73  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(javaLoader)));
74  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
75  Handle<mirror::Class> c(
76      hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader)));
77  if (c.Get() == nullptr) {
78    ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
79    env->ExceptionClear();
80    jthrowable cnfe = reinterpret_cast<jthrowable>(env->NewObject(WellKnownClasses::java_lang_ClassNotFoundException,
81                                                                  WellKnownClasses::java_lang_ClassNotFoundException_init,
82                                                                  javaName, cause.get()));
83    if (cnfe != nullptr) {
84      // Make sure allocation didn't fail with an OOME.
85      env->Throw(cnfe);
86    }
87    return nullptr;
88  }
89  if (initialize) {
90    class_linker->EnsureInitialized(soa.Self(), c, true, true);
91  }
92  return soa.AddLocalReference<jclass>(c.Get());
93}
94
95static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
96  ScopedFastNativeObjectAccess soa(env);
97  StackHandleScope<1> hs(soa.Self());
98  mirror::Class* const c = DecodeClass(soa, javaThis);
99  return soa.AddLocalReference<jstring>(mirror::Class::ComputeName(hs.NewHandle(c)));
100}
101
102static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) {
103  ScopedFastNativeObjectAccess soa(env);
104  mirror::Class* c = DecodeClass(soa, javaThis);
105  return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self()));
106}
107
108static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
109    Thread* self, mirror::Class* klass, bool public_only, bool force_resolve)
110      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
111  StackHandleScope<1> hs(self);
112  auto* ifields = klass->GetIFields();
113  auto* sfields = klass->GetSFields();
114  const auto num_ifields = klass->NumInstanceFields();
115  const auto num_sfields = klass->NumStaticFields();
116  size_t array_size = num_ifields + num_sfields;
117  if (public_only) {
118    // Lets go subtract all the non public fields.
119    for (size_t i = 0; i < num_ifields; ++i) {
120      if (!ifields[i].IsPublic()) {
121        --array_size;
122      }
123    }
124    for (size_t i = 0; i < num_sfields; ++i) {
125      if (!sfields[i].IsPublic()) {
126        --array_size;
127      }
128    }
129  }
130  size_t array_idx = 0;
131  auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc(
132      self, mirror::Field::ArrayClass(), array_size));
133  if (object_array.Get() == nullptr) {
134    return nullptr;
135  }
136  for (size_t i = 0; i < num_ifields; ++i) {
137    auto* art_field = &ifields[i];
138    if (!public_only || art_field->IsPublic()) {
139      auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
140      if (field == nullptr) {
141        if (kIsDebugBuild) {
142          self->AssertPendingException();
143        }
144        // Maybe null due to OOME or type resolving exception.
145        return nullptr;
146      }
147      object_array->SetWithoutChecks<false>(array_idx++, field);
148    }
149  }
150  for (size_t i = 0; i < num_sfields; ++i) {
151    auto* art_field = &sfields[i];
152    if (!public_only || art_field->IsPublic()) {
153      auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
154      if (field == nullptr) {
155        if (kIsDebugBuild) {
156          self->AssertPendingException();
157        }
158        return nullptr;
159      }
160      object_array->SetWithoutChecks<false>(array_idx++, field);
161    }
162  }
163  CHECK_EQ(array_idx, array_size);
164  return object_array.Get();
165}
166
167static jobjectArray Class_getDeclaredFieldsUnchecked(JNIEnv* env, jobject javaThis,
168                                                     jboolean publicOnly) {
169  ScopedFastNativeObjectAccess soa(env);
170  return soa.AddLocalReference<jobjectArray>(
171      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), publicOnly != JNI_FALSE, false));
172}
173
174static jobjectArray Class_getDeclaredFields(JNIEnv* env, jobject javaThis) {
175  ScopedFastNativeObjectAccess soa(env);
176  return soa.AddLocalReference<jobjectArray>(
177      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), false, true));
178}
179
180static jobjectArray Class_getPublicDeclaredFields(JNIEnv* env, jobject javaThis) {
181  ScopedFastNativeObjectAccess soa(env);
182  return soa.AddLocalReference<jobjectArray>(
183      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), true, true));
184}
185
186// Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use
187// the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly
188// fast.
189ALWAYS_INLINE static inline ArtField* FindFieldByName(
190    Thread* self ATTRIBUTE_UNUSED, mirror::String* name, ArtField* fields, size_t num_fields)
191    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
192  size_t low = 0;
193  size_t high = num_fields;
194  const uint16_t* const data = name->GetCharArray()->GetData() + name->GetOffset();
195  const size_t length = name->GetLength();
196  while (low < high) {
197    auto mid = (low + high) / 2;
198    ArtField* const field = &fields[mid];
199    int result = CompareModifiedUtf8ToUtf16AsCodePointValues(field->GetName(), data, length);
200    // Alternate approach, only a few % faster at the cost of more allocations.
201    // int result = field->GetStringName(self, true)->CompareTo(name);
202    if (result < 0) {
203      low = mid + 1;
204    } else if (result > 0) {
205      high = mid;
206    } else {
207      return field;
208    }
209  }
210  if (kIsDebugBuild) {
211    for (size_t i = 0; i < num_fields; ++i) {
212      CHECK_NE(fields[i].GetName(), name->ToModifiedUtf8());
213    }
214  }
215  return nullptr;
216}
217
218ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(
219    Thread* self, mirror::Class* c, mirror::String* name)
220    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
221  auto* instance_fields = c->GetIFields();
222  auto* art_field = FindFieldByName(self, name, instance_fields, c->NumInstanceFields());
223  if (art_field != nullptr) {
224    return mirror::Field::CreateFromArtField(self, art_field, true);
225  }
226  auto* static_fields = c->GetSFields();
227  art_field = FindFieldByName(self, name, static_fields, c->NumStaticFields());
228  if (art_field != nullptr) {
229    return mirror::Field::CreateFromArtField(self, art_field, true);
230  }
231  return nullptr;
232}
233
234static jobject Class_getDeclaredFieldInternal(JNIEnv* env, jobject javaThis, jstring name) {
235  ScopedFastNativeObjectAccess soa(env);
236  auto* name_string = soa.Decode<mirror::String*>(name);
237  return soa.AddLocalReference<jobject>(
238      GetDeclaredField(soa.Self(), DecodeClass(soa, javaThis), name_string));
239}
240
241static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) {
242  ScopedFastNativeObjectAccess soa(env);
243  auto* name_string = soa.Decode<mirror::String*>(name);
244  if (name_string == nullptr) {
245    ThrowNullPointerException("name == null");
246    return nullptr;
247  }
248  auto* klass = DecodeClass(soa, javaThis);
249  mirror::Field* result = GetDeclaredField(soa.Self(), klass, name_string);
250  if (result == nullptr) {
251    std::string name_str = name_string->ToModifiedUtf8();
252    // We may have a pending exception if we failed to resolve.
253    if (!soa.Self()->IsExceptionPending()) {
254      soa.Self()->ThrowNewException("Ljava/lang/NoSuchFieldException;", name_str.c_str());
255    }
256    return nullptr;
257  }
258  return soa.AddLocalReference<jobject>(result);
259}
260
261static jobject Class_getDeclaredConstructorInternal(
262    JNIEnv* env, jobject javaThis, jobjectArray args) {
263  ScopedFastNativeObjectAccess soa(env);
264  auto* klass = DecodeClass(soa, javaThis);
265  auto* params = soa.Decode<mirror::ObjectArray<mirror::Class>*>(args);
266  StackHandleScope<1> hs(soa.Self());
267  auto* declared_constructor = klass->GetDeclaredConstructor(soa.Self(), hs.NewHandle(params));
268  if (declared_constructor != nullptr) {
269    return soa.AddLocalReference<jobject>(
270        mirror::Constructor::CreateFromArtMethod(soa.Self(), declared_constructor));
271  }
272  return nullptr;
273}
274
275static ALWAYS_INLINE inline bool MethodMatchesConstructor(mirror::ArtMethod* m, bool public_only)
276    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
277  DCHECK(m != nullptr);
278  return (!public_only || m->IsPublic()) && !m->IsStatic() && m->IsConstructor();
279}
280
281static jobjectArray Class_getDeclaredConstructorsInternal(
282    JNIEnv* env, jobject javaThis, jboolean publicOnly) {
283  ScopedFastNativeObjectAccess soa(env);
284  auto* klass = DecodeClass(soa, javaThis);
285  StackHandleScope<2> hs(soa.Self());
286  auto h_direct_methods = hs.NewHandle(klass->GetDirectMethods());
287  size_t constructor_count = 0;
288  auto count = h_direct_methods.Get() != nullptr ? h_direct_methods->GetLength() : 0u;
289  // Two pass approach for speed.
290  for (size_t i = 0; i < count; ++i) {
291    constructor_count += MethodMatchesConstructor(h_direct_methods->GetWithoutChecks(i),
292                                                  publicOnly != JNI_FALSE) ? 1u : 0u;
293  }
294  auto h_constructors = hs.NewHandle(mirror::ObjectArray<mirror::Constructor>::Alloc(
295      soa.Self(), mirror::Constructor::ArrayClass(), constructor_count));
296  if (UNLIKELY(h_constructors.Get() == nullptr)) {
297    soa.Self()->AssertPendingException();
298    return nullptr;
299  }
300  constructor_count = 0;
301  for (size_t i = 0; i < count; ++i) {
302    auto* method = h_direct_methods->GetWithoutChecks(i);
303    if (MethodMatchesConstructor(method, publicOnly != JNI_FALSE)) {
304      auto* constructor = mirror::Constructor::CreateFromArtMethod(soa.Self(), method);
305      if (UNLIKELY(constructor == nullptr)) {
306        soa.Self()->AssertPendingException();
307        return nullptr;
308      }
309      h_constructors->SetWithoutChecks<false>(constructor_count++, constructor);
310    }
311  }
312  return soa.AddLocalReference<jobjectArray>(h_constructors.Get());
313}
314
315static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis,
316                                               jobject name, jobjectArray args) {
317  // Covariant return types permit the class to define multiple
318  // methods with the same name and parameter types. Prefer to
319  // return a non-synthetic method in such situations. We may
320  // still return a synthetic method to handle situations like
321  // escalated visibility. We never return miranda methods that
322  // were synthesized by the runtime.
323  constexpr uint32_t kSkipModifiers = kAccMiranda | kAccSynthetic;
324  ScopedFastNativeObjectAccess soa(env);
325  StackHandleScope<5> hs(soa.Self());
326  auto h_method_name = hs.NewHandle(soa.Decode<mirror::String*>(name));
327  if (UNLIKELY(h_method_name.Get() == nullptr)) {
328    ThrowNullPointerException("name == null");
329    return nullptr;
330  }
331  auto h_args = hs.NewHandle(soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
332  auto* klass = DecodeClass(soa, javaThis);
333  mirror::ArtMethod* result = nullptr;
334  auto* virtual_methods = klass->GetVirtualMethods();
335  if (virtual_methods != nullptr) {
336    auto h_virtual_methods = hs.NewHandle(virtual_methods);
337    for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
338      auto* m = h_virtual_methods->GetWithoutChecks(i);
339      auto* np_method = m->GetInterfaceMethodIfProxy();
340      // May cause thread suspension.
341      mirror::String* np_name = np_method->GetNameAsString(soa.Self());
342      if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
343        if (UNLIKELY(soa.Self()->IsExceptionPending())) {
344          return nullptr;
345        }
346        continue;
347      }
348      auto modifiers = m->GetAccessFlags();
349      if ((modifiers & kSkipModifiers) == 0) {
350        return soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(soa.Self(), m));
351      }
352      if ((modifiers & kAccMiranda) == 0) {
353        result = m;  // Remember as potential result if it's not a miranda method.
354      }
355    }
356  }
357  if (result == nullptr) {
358    auto* direct_methods = klass->GetDirectMethods();
359    if (direct_methods != nullptr) {
360      auto h_direct_methods = hs.NewHandle(direct_methods);
361      for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
362        auto* m = h_direct_methods->GetWithoutChecks(i);
363        auto modifiers = m->GetAccessFlags();
364        if ((modifiers & kAccConstructor) != 0) {
365          continue;
366        }
367        auto* np_method = m->GetInterfaceMethodIfProxy();
368        // May cause thread suspension.
369        mirror::String* np_name = np_method ->GetNameAsString(soa.Self());
370        if (np_name == nullptr) {
371          soa.Self()->AssertPendingException();
372          return nullptr;
373        }
374        if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
375          if (UNLIKELY(soa.Self()->IsExceptionPending())) {
376            return nullptr;
377          }
378          continue;
379        }
380        if ((modifiers & kSkipModifiers) == 0) {
381          return soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(
382              soa.Self(), m));
383        }
384        // Direct methods cannot be miranda methods, so this potential result must be synthetic.
385        result = m;
386      }
387    }
388  }
389  return result != nullptr ?
390      soa.AddLocalReference<jobject>(mirror::Method::CreateFromArtMethod(soa.Self(), result)) :
391      nullptr;
392}
393
394jobjectArray Class_getDeclaredMethodsUnchecked(JNIEnv* env, jobject javaThis,
395                                               jboolean publicOnly) {
396  ScopedFastNativeObjectAccess soa(env);
397  StackHandleScope<5> hs(soa.Self());
398  auto* klass = DecodeClass(soa, javaThis);
399  auto virtual_methods = hs.NewHandle(klass->GetVirtualMethods());
400  auto direct_methods = hs.NewHandle(klass->GetDirectMethods());
401  size_t num_methods = 0;
402  if (virtual_methods.Get() != nullptr) {
403    for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
404      auto* m = virtual_methods->GetWithoutChecks(i);
405      auto modifiers = m->GetAccessFlags();
406      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
407          (modifiers & kAccMiranda) == 0) {
408        ++num_methods;
409      }
410    }
411  }
412  if (direct_methods.Get() != nullptr) {
413    for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
414      auto* m = direct_methods->GetWithoutChecks(i);
415      auto modifiers = m->GetAccessFlags();
416      // Add non-constructor direct/static methods.
417      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
418          (modifiers & kAccConstructor) == 0) {
419        ++num_methods;
420      }
421    }
422  }
423  auto ret = hs.NewHandle(mirror::ObjectArray<mirror::Method>::Alloc(
424      soa.Self(), mirror::Method::ArrayClass(), num_methods));
425  num_methods = 0;
426  if (virtual_methods.Get() != nullptr) {
427    for (size_t i = 0, count = virtual_methods->GetLength(); i < count; ++i) {
428      auto* m = virtual_methods->GetWithoutChecks(i);
429      auto modifiers = m->GetAccessFlags();
430      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
431          (modifiers & kAccMiranda) == 0) {
432        auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
433        if (method == nullptr) {
434          soa.Self()->AssertPendingException();
435          return nullptr;
436        }
437        ret->SetWithoutChecks<false>(num_methods++, method);
438      }
439    }
440  }
441  if (direct_methods.Get() != nullptr) {
442    for (size_t i = 0, count = direct_methods->GetLength(); i < count; ++i) {
443      auto* m = direct_methods->GetWithoutChecks(i);
444      auto modifiers = m->GetAccessFlags();
445      // Add non-constructor direct/static methods.
446      if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
447          (modifiers & kAccConstructor) == 0) {
448        auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
449        if (method == nullptr) {
450          soa.Self()->AssertPendingException();
451          return nullptr;
452        }
453        ret->SetWithoutChecks<false>(num_methods++, method);
454      }
455    }
456  }
457  return soa.AddLocalReference<jobjectArray>(ret.Get());
458}
459
460static JNINativeMethod gMethods[] = {
461  NATIVE_METHOD(Class, classForName,
462                "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
463  NATIVE_METHOD(Class, getDeclaredConstructorInternal,
464                "!([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;"),
465  NATIVE_METHOD(Class, getDeclaredConstructorsInternal, "!(Z)[Ljava/lang/reflect/Constructor;"),
466  NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
467  NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
468  NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
469  NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"),
470  NATIVE_METHOD(Class, getDeclaredMethodInternal,
471                "!(Ljava/lang/String;[Ljava/lang/Class;)Ljava/lang/reflect/Method;"),
472  NATIVE_METHOD(Class, getDeclaredMethodsUnchecked,
473                  "!(Z)[Ljava/lang/reflect/Method;"),
474  NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
475  NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
476  NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
477};
478
479void register_java_lang_Class(JNIEnv* env) {
480  REGISTER_NATIVE_METHODS("java/lang/Class");
481}
482
483}  // namespace art
484