java_lang_Class.cc revision c785344b87221f5e4e6473e5b762e4e61fe65dcf
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/object-inl.h"
29#include "mirror/object_array-inl.h"
30#include "mirror/string-inl.h"
31#include "scoped_thread_state_change.h"
32#include "scoped_fast_native_object_access.h"
33#include "ScopedLocalRef.h"
34#include "ScopedUtfChars.h"
35#include "utf.h"
36#include "well_known_classes.h"
37
38namespace art {
39
40ALWAYS_INLINE static inline mirror::Class* DecodeClass(
41    const ScopedFastNativeObjectAccess& soa, jobject java_class)
42    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
43  mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
44  DCHECK(c != NULL);
45  DCHECK(c->IsClass());
46  // TODO: we could EnsureInitialized here, rather than on every reflective get/set or invoke .
47  // For now, we conservatively preserve the old dalvik behavior. A quick "IsInitialized" check
48  // every time probably doesn't make much difference to reflection performance anyway.
49  return c;
50}
51
52// "name" is in "binary name" format, e.g. "dalvik.system.Debug$1".
53static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean initialize,
54                                 jobject javaLoader) {
55  ScopedFastNativeObjectAccess soa(env);
56  ScopedUtfChars name(env, javaName);
57  if (name.c_str() == nullptr) {
58    return nullptr;
59  }
60
61  // We need to validate and convert the name (from x.y.z to x/y/z).  This
62  // is especially handy for array types, since we want to avoid
63  // auto-generating bogus array classes.
64  if (!IsValidBinaryClassName(name.c_str())) {
65    soa.Self()->ThrowNewExceptionF("Ljava/lang/ClassNotFoundException;",
66                                   "Invalid name: %s", name.c_str());
67    return nullptr;
68  }
69
70  std::string descriptor(DotToDescriptor(name.c_str()));
71  StackHandleScope<2> hs(soa.Self());
72  Handle<mirror::ClassLoader> class_loader(hs.NewHandle(soa.Decode<mirror::ClassLoader*>(javaLoader)));
73  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
74  Handle<mirror::Class> c(
75      hs.NewHandle(class_linker->FindClass(soa.Self(), descriptor.c_str(), class_loader)));
76  if (c.Get() == nullptr) {
77    ScopedLocalRef<jthrowable> cause(env, env->ExceptionOccurred());
78    env->ExceptionClear();
79    jthrowable cnfe = reinterpret_cast<jthrowable>(env->NewObject(WellKnownClasses::java_lang_ClassNotFoundException,
80                                                                  WellKnownClasses::java_lang_ClassNotFoundException_init,
81                                                                  javaName, cause.get()));
82    if (cnfe != nullptr) {
83      // Make sure allocation didn't fail with an OOME.
84      env->Throw(cnfe);
85    }
86    return nullptr;
87  }
88  if (initialize) {
89    class_linker->EnsureInitialized(soa.Self(), c, true, true);
90  }
91  return soa.AddLocalReference<jclass>(c.Get());
92}
93
94static jobject Class_findOverriddenMethodIfProxy(JNIEnv* env, jclass, jobject art_method) {
95  ScopedFastNativeObjectAccess soa(env);
96  mirror::ArtMethod* method = soa.Decode<mirror::ArtMethod*>(art_method);
97  mirror::Class* declaring_klass = method->GetDeclaringClass();
98  if (!declaring_klass->IsProxyClass()) {
99    return art_method;
100  }
101  uint32_t dex_method_index = method->GetDexMethodIndex();
102  mirror::ArtMethod* overriden_method = method->GetDexCacheResolvedMethods()->Get(dex_method_index);
103  return soa.AddLocalReference<jobject>(overriden_method);
104}
105
106static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) {
107  ScopedFastNativeObjectAccess soa(env);
108  StackHandleScope<1> hs(soa.Self());
109  mirror::Class* const c = DecodeClass(soa, javaThis);
110  return soa.AddLocalReference<jstring>(mirror::Class::ComputeName(hs.NewHandle(c)));
111}
112
113static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) {
114  ScopedFastNativeObjectAccess soa(env);
115  mirror::Class* c = DecodeClass(soa, javaThis);
116  return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self()));
117}
118
119static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
120    Thread* self, mirror::Class* klass, bool public_only, bool force_resolve)
121      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
122  StackHandleScope<1> hs(self);
123  auto* ifields = klass->GetIFields();
124  auto* sfields = klass->GetSFields();
125  const auto num_ifields = klass->NumInstanceFields();
126  const auto num_sfields = klass->NumStaticFields();
127  size_t array_size = num_ifields + num_sfields;
128  if (public_only) {
129    // Lets go subtract all the non public fields.
130    for (size_t i = 0; i < num_ifields; ++i) {
131      if (!ifields[i].IsPublic()) {
132        --array_size;
133      }
134    }
135    for (size_t i = 0; i < num_sfields; ++i) {
136      if (!sfields[i].IsPublic()) {
137        --array_size;
138      }
139    }
140  }
141  size_t array_idx = 0;
142  auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc(
143      self, mirror::Field::ArrayClass(), array_size));
144  if (object_array.Get() == nullptr) {
145    return nullptr;
146  }
147  for (size_t i = 0; i < num_ifields; ++i) {
148    auto* art_field = &ifields[i];
149    if (!public_only || art_field->IsPublic()) {
150      auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
151      if (field == nullptr) {
152        if (kIsDebugBuild) {
153          self->AssertPendingException();
154        }
155        // Maybe null due to OOME or type resolving exception.
156        return nullptr;
157      }
158      object_array->SetWithoutChecks<false>(array_idx++, field);
159    }
160  }
161  for (size_t i = 0; i < num_sfields; ++i) {
162    auto* art_field = &sfields[i];
163    if (!public_only || art_field->IsPublic()) {
164      auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
165      if (field == nullptr) {
166        if (kIsDebugBuild) {
167          self->AssertPendingException();
168        }
169        return nullptr;
170      }
171      object_array->SetWithoutChecks<false>(array_idx++, field);
172    }
173  }
174  CHECK_EQ(array_idx, array_size);
175  return object_array.Get();
176}
177
178static jobjectArray Class_getDeclaredFieldsUnchecked(JNIEnv* env, jobject javaThis,
179                                                     jboolean publicOnly) {
180  ScopedFastNativeObjectAccess soa(env);
181  return soa.AddLocalReference<jobjectArray>(
182      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), publicOnly != JNI_FALSE, false));
183}
184
185static jobjectArray Class_getDeclaredFields(JNIEnv* env, jobject javaThis) {
186  ScopedFastNativeObjectAccess soa(env);
187  return soa.AddLocalReference<jobjectArray>(
188      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), false, true));
189}
190
191static jobjectArray Class_getPublicDeclaredFields(JNIEnv* env, jobject javaThis) {
192  ScopedFastNativeObjectAccess soa(env);
193  return soa.AddLocalReference<jobjectArray>(
194      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), true, true));
195}
196
197// Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use
198// the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly
199// fast.
200ALWAYS_INLINE static inline ArtField* FindFieldByName(
201    Thread* self ATTRIBUTE_UNUSED, mirror::String* name, ArtField* fields, size_t num_fields)
202    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
203  size_t low = 0;
204  size_t high = num_fields;
205  const uint16_t* const data = name->GetCharArray()->GetData() + name->GetOffset();
206  const size_t length = name->GetLength();
207  while (low < high) {
208    auto mid = (low + high) / 2;
209    ArtField* const field = &fields[mid];
210    int result = CompareModifiedUtf8ToUtf16AsCodePointValues(field->GetName(), data, length);
211    // Alternate approach, only a few % faster at the cost of more allocations.
212    // int result = field->GetStringName(self, true)->CompareTo(name);
213    if (result < 0) {
214      low = mid + 1;
215    } else if (result > 0) {
216      high = mid;
217    } else {
218      return field;
219    }
220  }
221  if (kIsDebugBuild) {
222    for (size_t i = 0; i < num_fields; ++i) {
223      CHECK_NE(fields[i].GetName(), name->ToModifiedUtf8());
224    }
225  }
226  return nullptr;
227}
228
229ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(
230    Thread* self, mirror::Class* c, mirror::String* name)
231    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
232  auto* instance_fields = c->GetIFields();
233  auto* art_field = FindFieldByName(self, name, instance_fields, c->NumInstanceFields());
234  if (art_field != nullptr) {
235    return mirror::Field::CreateFromArtField(self, art_field, true);
236  }
237  auto* static_fields = c->GetSFields();
238  art_field = FindFieldByName(self, name, static_fields, c->NumStaticFields());
239  if (art_field != nullptr) {
240    return mirror::Field::CreateFromArtField(self, art_field, true);
241  }
242  return nullptr;
243}
244
245static jobject Class_getDeclaredFieldInternal(JNIEnv* env, jobject javaThis, jstring name) {
246  ScopedFastNativeObjectAccess soa(env);
247  auto* name_string = soa.Decode<mirror::String*>(name);
248  return soa.AddLocalReference<jobject>(
249      GetDeclaredField(soa.Self(), DecodeClass(soa, javaThis), name_string));
250}
251
252static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) {
253  ScopedFastNativeObjectAccess soa(env);
254  auto* name_string = soa.Decode<mirror::String*>(name);
255  if (name == nullptr) {
256    ThrowNullPointerException("name == null");
257    return nullptr;
258  }
259  auto* klass = DecodeClass(soa, javaThis);
260  mirror::Field* result = GetDeclaredField(soa.Self(), klass, name_string);
261  if (result == nullptr) {
262    std::string name_str = name_string->ToModifiedUtf8();
263    // We may have a pending exception if we failed to resolve.
264    if (!soa.Self()->IsExceptionPending()) {
265      soa.Self()->ThrowNewException("Ljava/lang/NoSuchFieldException;", name_str.c_str());
266    }
267    return nullptr;
268  }
269  return soa.AddLocalReference<jobject>(result);
270}
271
272static JNINativeMethod gMethods[] = {
273  NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
274  NATIVE_METHOD(Class, findOverriddenMethodIfProxy,
275                "!(Ljava/lang/reflect/ArtMethod;)Ljava/lang/reflect/ArtMethod;"),
276  NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
277  NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
278  NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
279  NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
280  NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"),
281  NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
282  NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
283};
284
285void register_java_lang_Class(JNIEnv* env) {
286  REGISTER_NATIVE_METHODS("java/lang/Class");
287}
288
289}  // namespace art
290