java_lang_Class.cc revision 02d2f290380c6aeff5f5a089ee38fa5d55e46130
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 "class_linker.h" 20#include "common_throws.h" 21#include "dex_file-inl.h" 22#include "jni_internal.h" 23#include "nth_caller_visitor.h" 24#include "mirror/art_field-inl.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 jstring Class_getNameNative(JNIEnv* env, jobject javaThis) { 95 ScopedFastNativeObjectAccess soa(env); 96 StackHandleScope<1> hs(soa.Self()); 97 mirror::Class* const c = DecodeClass(soa, javaThis); 98 return soa.AddLocalReference<jstring>(mirror::Class::ComputeName(hs.NewHandle(c))); 99} 100 101static jobjectArray Class_getProxyInterfaces(JNIEnv* env, jobject javaThis) { 102 ScopedFastNativeObjectAccess soa(env); 103 mirror::Class* c = DecodeClass(soa, javaThis); 104 return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self())); 105} 106 107static mirror::ObjectArray<mirror::Field>* GetDeclaredFields( 108 Thread* self, mirror::Class* klass, bool public_only, bool force_resolve) 109 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 110 StackHandleScope<3> hs(self); 111 auto h_ifields = hs.NewHandle(klass->GetIFields()); 112 auto h_sfields = hs.NewHandle(klass->GetSFields()); 113 const int32_t num_ifields = h_ifields.Get() != nullptr ? h_ifields->GetLength() : 0; 114 const int32_t num_sfields = h_sfields.Get() != nullptr ? h_sfields->GetLength() : 0; 115 int32_t array_size = num_ifields + num_sfields; 116 if (public_only) { 117 // Lets go subtract all the non public fields. 118 for (int32_t i = 0; i < num_ifields; ++i) { 119 if (!h_ifields->GetWithoutChecks(i)->IsPublic()) { 120 --array_size; 121 } 122 } 123 for (int32_t i = 0; i < num_sfields; ++i) { 124 if (!h_sfields->GetWithoutChecks(i)->IsPublic()) { 125 --array_size; 126 } 127 } 128 } 129 int32_t array_idx = 0; 130 auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc( 131 self, mirror::Field::ArrayClass(), array_size)); 132 if (object_array.Get() == nullptr) { 133 return nullptr; 134 } 135 for (int32_t i = 0; i < num_ifields; ++i) { 136 auto* art_field = h_ifields->GetWithoutChecks(i); 137 if (!public_only || art_field->IsPublic()) { 138 auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve); 139 if (field == nullptr) { 140 if (kIsDebugBuild) { 141 self->AssertPendingException(); 142 } 143 // Maybe null due to OOME or type resolving exception. 144 return nullptr; 145 } 146 object_array->SetWithoutChecks<false>(array_idx++, field); 147 } 148 } 149 for (int32_t i = 0; i < num_sfields; ++i) { 150 auto* art_field = h_sfields->GetWithoutChecks(i); 151 if (!public_only || art_field->IsPublic()) { 152 auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve); 153 if (field == nullptr) { 154 if (kIsDebugBuild) { 155 self->AssertPendingException(); 156 } 157 return nullptr; 158 } 159 object_array->SetWithoutChecks<false>(array_idx++, field); 160 } 161 } 162 CHECK_EQ(array_idx, array_size); 163 return object_array.Get(); 164} 165 166static jobjectArray Class_getDeclaredFieldsUnchecked(JNIEnv* env, jobject javaThis, 167 jboolean publicOnly) { 168 ScopedFastNativeObjectAccess soa(env); 169 return soa.AddLocalReference<jobjectArray>( 170 GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), publicOnly != JNI_FALSE, false)); 171} 172 173static jobjectArray Class_getDeclaredFields(JNIEnv* env, jobject javaThis) { 174 ScopedFastNativeObjectAccess soa(env); 175 return soa.AddLocalReference<jobjectArray>( 176 GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), false, true)); 177} 178 179static jobjectArray Class_getPublicDeclaredFields(JNIEnv* env, jobject javaThis) { 180 ScopedFastNativeObjectAccess soa(env); 181 return soa.AddLocalReference<jobjectArray>( 182 GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), true, true)); 183} 184 185// Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use 186// the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly 187// fast. 188ALWAYS_INLINE static inline mirror::ArtField* FindFieldByName( 189 Thread* self ATTRIBUTE_UNUSED, mirror::String* name, 190 mirror::ObjectArray<mirror::ArtField>* fields) 191 SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { 192 uint32_t low = 0; 193 uint32_t high = fields->GetLength(); 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 mirror::ArtField* const field = fields->GetWithoutChecks(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 (int32_t i = 0; i < fields->GetLength(); ++i) { 212 CHECK_NE(fields->GetWithoutChecks(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 if (instance_fields != nullptr) { 223 auto* art_field = FindFieldByName(self, name, instance_fields); 224 if (art_field != nullptr) { 225 return mirror::Field::CreateFromArtField(self, art_field, true); 226 } 227 } 228 auto* static_fields = c->GetSFields(); 229 if (static_fields != nullptr) { 230 auto* art_field = FindFieldByName(self, name, static_fields); 231 if (art_field != nullptr) { 232 return mirror::Field::CreateFromArtField(self, art_field, true); 233 } 234 } 235 return nullptr; 236} 237 238static jobject Class_getDeclaredFieldInternal(JNIEnv* env, jobject javaThis, jstring name) { 239 ScopedFastNativeObjectAccess soa(env); 240 auto* name_string = soa.Decode<mirror::String*>(name); 241 return soa.AddLocalReference<jobject>( 242 GetDeclaredField(soa.Self(), DecodeClass(soa, javaThis), name_string)); 243} 244 245static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) { 246 ScopedFastNativeObjectAccess soa(env); 247 auto* name_string = soa.Decode<mirror::String*>(name); 248 if (name == nullptr) { 249 ThrowNullPointerException("name == null"); 250 return nullptr; 251 } 252 auto* klass = DecodeClass(soa, javaThis); 253 mirror::Field* result = GetDeclaredField(soa.Self(), klass, name_string); 254 if (result == nullptr) { 255 std::string name_str = name_string->ToModifiedUtf8(); 256 // We may have a pending exception if we failed to resolve. 257 if (!soa.Self()->IsExceptionPending()) { 258 soa.Self()->ThrowNewException("Ljava/lang/NoSuchFieldException;", name_str.c_str()); 259 } 260 return nullptr; 261 } 262 return soa.AddLocalReference<jobject>(result); 263} 264 265static JNINativeMethod gMethods[] = { 266 NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"), 267 NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"), 268 NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"), 269 NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"), 270 NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"), 271 NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"), 272 NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"), 273 NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"), 274}; 275 276void register_java_lang_Class(JNIEnv* env) { 277 REGISTER_NATIVE_METHODS("java/lang/Class"); 278} 279 280} // namespace art 281