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