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