Home | History | Annotate | Download | only in runtime
      1 /*
      2  * Copyright (C) 2011 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 #ifndef ART_RUNTIME_CLASS_LINKER_INL_H_
     18 #define ART_RUNTIME_CLASS_LINKER_INL_H_
     19 
     20 #include "art_field.h"
     21 #include "class_linker.h"
     22 #include "gc/heap-inl.h"
     23 #include "gc_root-inl.h"
     24 #include "handle_scope-inl.h"
     25 #include "mirror/class_loader.h"
     26 #include "mirror/dex_cache-inl.h"
     27 #include "mirror/iftable.h"
     28 #include "mirror/object_array-inl.h"
     29 #include "obj_ptr-inl.h"
     30 #include "scoped_thread_state_change-inl.h"
     31 
     32 #include <atomic>
     33 
     34 namespace art {
     35 
     36 inline mirror::Class* ClassLinker::FindArrayClass(Thread* self,
     37                                                   ObjPtr<mirror::Class>* element_class) {
     38   for (size_t i = 0; i < kFindArrayCacheSize; ++i) {
     39     // Read the cached array class once to avoid races with other threads setting it.
     40     ObjPtr<mirror::Class> array_class = find_array_class_cache_[i].Read();
     41     if (array_class != nullptr && array_class->GetComponentType() == *element_class) {
     42       return array_class.Ptr();
     43     }
     44   }
     45   std::string descriptor = "[";
     46   std::string temp;
     47   descriptor += (*element_class)->GetDescriptor(&temp);
     48   StackHandleScope<2> hs(Thread::Current());
     49   Handle<mirror::ClassLoader> class_loader(hs.NewHandle((*element_class)->GetClassLoader()));
     50   HandleWrapperObjPtr<mirror::Class> h_element_class(hs.NewHandleWrapper(element_class));
     51   ObjPtr<mirror::Class> array_class = FindClass(self, descriptor.c_str(), class_loader);
     52   if (array_class != nullptr) {
     53     // Benign races in storing array class and incrementing index.
     54     size_t victim_index = find_array_class_cache_next_victim_;
     55     find_array_class_cache_[victim_index] = GcRoot<mirror::Class>(array_class);
     56     find_array_class_cache_next_victim_ = (victim_index + 1) % kFindArrayCacheSize;
     57   } else {
     58     // We should have a NoClassDefFoundError.
     59     self->AssertPendingException();
     60   }
     61   return array_class.Ptr();
     62 }
     63 
     64 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
     65                                                       ObjPtr<mirror::Class> referrer) {
     66   if (kObjPtrPoisoning) {
     67     StackHandleScope<1> hs(Thread::Current());
     68     HandleWrapperObjPtr<mirror::Class> referrer_wrapper = hs.NewHandleWrapper(&referrer);
     69     Thread::Current()->PoisonObjectPointers();
     70   }
     71   if (kIsDebugBuild) {
     72     Thread::Current()->AssertNoPendingException();
     73   }
     74   // We do not need the read barrier for getting the DexCache for the initial resolved type
     75   // lookup as both from-space and to-space copies point to the same native resolved types array.
     76   ObjPtr<mirror::Class> resolved_type =
     77       referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
     78   if (resolved_type == nullptr) {
     79     StackHandleScope<2> hs(Thread::Current());
     80     Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
     81     Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referrer->GetClassLoader()));
     82     resolved_type = DoResolveType(type_idx, h_dex_cache, class_loader);
     83   }
     84   return resolved_type;
     85 }
     86 
     87 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
     88                                                       ArtMethod* referrer) {
     89   Thread::PoisonObjectPointersIfDebug();
     90   if (kIsDebugBuild) {
     91     Thread::Current()->AssertNoPendingException();
     92   }
     93   // We do not need the read barrier for getting the DexCache for the initial resolved type
     94   // lookup as both from-space and to-space copies point to the same native resolved types array.
     95   ObjPtr<mirror::Class> resolved_type =
     96       referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
     97   if (UNLIKELY(resolved_type == nullptr)) {
     98     StackHandleScope<2> hs(Thread::Current());
     99     ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
    100     Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
    101     Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
    102     resolved_type = DoResolveType(type_idx, dex_cache, class_loader);
    103   }
    104   return resolved_type;
    105 }
    106 
    107 inline ObjPtr<mirror::Class> ClassLinker::ResolveType(dex::TypeIndex type_idx,
    108                                                       Handle<mirror::DexCache> dex_cache,
    109                                                       Handle<mirror::ClassLoader> class_loader) {
    110   DCHECK(dex_cache != nullptr);
    111   Thread::PoisonObjectPointersIfDebug();
    112   ObjPtr<mirror::Class> resolved = dex_cache->GetResolvedType(type_idx);
    113   if (resolved == nullptr) {
    114     resolved = DoResolveType(type_idx, dex_cache, class_loader);
    115   }
    116   return resolved;
    117 }
    118 
    119 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
    120                                                              ObjPtr<mirror::Class> referrer) {
    121   // We do not need the read barrier for getting the DexCache for the initial resolved type
    122   // lookup as both from-space and to-space copies point to the same native resolved types array.
    123   ObjPtr<mirror::Class> type =
    124       referrer->GetDexCache<kDefaultVerifyFlags, kWithoutReadBarrier>()->GetResolvedType(type_idx);
    125   if (type == nullptr) {
    126     type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
    127   }
    128   return type;
    129 }
    130 
    131 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(dex::TypeIndex type_idx,
    132                                                              ArtMethod* referrer) {
    133   // We do not need the read barrier for getting the DexCache for the initial resolved type
    134   // lookup as both from-space and to-space copies point to the same native resolved types array.
    135   ObjPtr<mirror::Class> type =
    136       referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedType(type_idx);
    137   if (type == nullptr) {
    138     type = DoLookupResolvedType(type_idx, referrer->GetDexCache(), referrer->GetClassLoader());
    139   }
    140   return type;
    141 }
    142 
    143 inline ObjPtr<mirror::Class> ClassLinker::LookupResolvedType(
    144     dex::TypeIndex type_idx,
    145     ObjPtr<mirror::DexCache> dex_cache,
    146     ObjPtr<mirror::ClassLoader> class_loader) {
    147   ObjPtr<mirror::Class> type = dex_cache->GetResolvedType(type_idx);
    148   if (type == nullptr) {
    149     type = DoLookupResolvedType(type_idx, dex_cache, class_loader);
    150   }
    151   return type;
    152 }
    153 
    154 template <bool kThrowOnError, typename ClassGetter>
    155 inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
    156                                                   InvokeType type,
    157                                                   ClassGetter class_getter) {
    158   switch (type) {
    159     case kStatic:
    160     case kSuper:
    161       break;
    162     case kInterface: {
    163       // We have to check whether the method id really belongs to an interface (dex static bytecode
    164       // constraints A15, A16). Otherwise you must not invoke-interface on it.
    165       ObjPtr<mirror::Class> klass = class_getter();
    166       if (UNLIKELY(!klass->IsInterface())) {
    167         if (kThrowOnError) {
    168           ThrowIncompatibleClassChangeError(klass,
    169                                             "Found class %s, but interface was expected",
    170                                             klass->PrettyDescriptor().c_str());
    171         }
    172         return true;
    173       }
    174       break;
    175     }
    176     case kDirect:
    177       if (dex_cache->GetDexFile()->SupportsDefaultMethods()) {
    178         break;
    179       }
    180       FALLTHROUGH_INTENDED;
    181     case kVirtual: {
    182       // Similarly, invoke-virtual (and invoke-direct without default methods) must reference
    183       // a non-interface class (dex static bytecode constraint A24, A25).
    184       ObjPtr<mirror::Class> klass = class_getter();
    185       if (UNLIKELY(klass->IsInterface())) {
    186         if (kThrowOnError) {
    187           ThrowIncompatibleClassChangeError(klass,
    188                                             "Found interface %s, but class was expected",
    189                                             klass->PrettyDescriptor().c_str());
    190         }
    191         return true;
    192       }
    193       break;
    194     }
    195     default:
    196       LOG(FATAL) << "Unreachable - invocation type: " << type;
    197       UNREACHABLE();
    198   }
    199   return false;
    200 }
    201 
    202 template <bool kThrow>
    203 inline bool ClassLinker::CheckInvokeClassMismatch(ObjPtr<mirror::DexCache> dex_cache,
    204                                                   InvokeType type,
    205                                                   uint32_t method_idx,
    206                                                   ObjPtr<mirror::ClassLoader> class_loader) {
    207   return CheckInvokeClassMismatch<kThrow>(
    208       dex_cache,
    209       type,
    210       [this, dex_cache, method_idx, class_loader]() REQUIRES_SHARED(Locks::mutator_lock_) {
    211         const DexFile::MethodId& method_id = dex_cache->GetDexFile()->GetMethodId(method_idx);
    212         ObjPtr<mirror::Class> klass =
    213             LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
    214         DCHECK(klass != nullptr);
    215         return klass;
    216       });
    217 }
    218 
    219 inline ArtMethod* ClassLinker::LookupResolvedMethod(uint32_t method_idx,
    220                                                     ObjPtr<mirror::DexCache> dex_cache,
    221                                                     ObjPtr<mirror::ClassLoader> class_loader) {
    222   PointerSize pointer_size = image_pointer_size_;
    223   ArtMethod* resolved = dex_cache->GetResolvedMethod(method_idx, pointer_size);
    224   if (resolved == nullptr) {
    225     const DexFile& dex_file = *dex_cache->GetDexFile();
    226     const DexFile::MethodId& method_id = dex_file.GetMethodId(method_idx);
    227     ObjPtr<mirror::Class> klass = LookupResolvedType(method_id.class_idx_, dex_cache, class_loader);
    228     if (klass != nullptr) {
    229       resolved = FindResolvedMethod(klass, dex_cache, class_loader, method_idx);
    230     }
    231   }
    232   return resolved;
    233 }
    234 
    235 template <InvokeType type, ClassLinker::ResolveMode kResolveMode>
    236 inline ArtMethod* ClassLinker::GetResolvedMethod(uint32_t method_idx, ArtMethod* referrer) {
    237   DCHECK(referrer != nullptr);
    238   // Note: The referrer can be a Proxy constructor. In that case, we need to do the
    239   // lookup in the context of the original method from where it steals the code.
    240   // However, we delay the GetInterfaceMethodIfProxy() until needed.
    241   DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
    242   // We do not need the read barrier for getting the DexCache for the initial resolved method
    243   // lookup as both from-space and to-space copies point to the same native resolved methods array.
    244   ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
    245       method_idx, image_pointer_size_);
    246   if (resolved_method == nullptr) {
    247     return nullptr;
    248   }
    249   DCHECK(!resolved_method->IsRuntimeMethod());
    250   if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
    251     referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
    252     // Check if the invoke type matches the class type.
    253     ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
    254     ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
    255     if (CheckInvokeClassMismatch</* kThrow */ false>(dex_cache, type, method_idx, class_loader)) {
    256       return nullptr;
    257     }
    258     // Check access.
    259     ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
    260     if (!referring_class->CanAccessResolvedMethod(resolved_method->GetDeclaringClass(),
    261                                                   resolved_method,
    262                                                   dex_cache,
    263                                                   method_idx)) {
    264       return nullptr;
    265     }
    266     // Check if the invoke type matches the method type.
    267     if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
    268       return nullptr;
    269     }
    270   }
    271   return resolved_method;
    272 }
    273 
    274 template <ClassLinker::ResolveMode kResolveMode>
    275 inline ArtMethod* ClassLinker::ResolveMethod(Thread* self,
    276                                              uint32_t method_idx,
    277                                              ArtMethod* referrer,
    278                                              InvokeType type) {
    279   DCHECK(referrer != nullptr);
    280   // Note: The referrer can be a Proxy constructor. In that case, we need to do the
    281   // lookup in the context of the original method from where it steals the code.
    282   // However, we delay the GetInterfaceMethodIfProxy() until needed.
    283   DCHECK(!referrer->IsProxyMethod() || referrer->IsConstructor());
    284   Thread::PoisonObjectPointersIfDebug();
    285   // We do not need the read barrier for getting the DexCache for the initial resolved method
    286   // lookup as both from-space and to-space copies point to the same native resolved methods array.
    287   ArtMethod* resolved_method = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedMethod(
    288       method_idx, image_pointer_size_);
    289   DCHECK(resolved_method == nullptr || !resolved_method->IsRuntimeMethod());
    290   if (UNLIKELY(resolved_method == nullptr)) {
    291     referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
    292     ObjPtr<mirror::Class> declaring_class = referrer->GetDeclaringClass();
    293     StackHandleScope<2> hs(self);
    294     Handle<mirror::DexCache> h_dex_cache(hs.NewHandle(referrer->GetDexCache()));
    295     Handle<mirror::ClassLoader> h_class_loader(hs.NewHandle(declaring_class->GetClassLoader()));
    296     resolved_method = ResolveMethod<kResolveMode>(method_idx,
    297                                                   h_dex_cache,
    298                                                   h_class_loader,
    299                                                   referrer,
    300                                                   type);
    301   } else if (kResolveMode == ResolveMode::kCheckICCEAndIAE) {
    302     referrer = referrer->GetInterfaceMethodIfProxy(image_pointer_size_);
    303     // Check if the invoke type matches the class type.
    304     ObjPtr<mirror::DexCache> dex_cache = referrer->GetDexCache();
    305     ObjPtr<mirror::ClassLoader> class_loader = referrer->GetClassLoader();
    306     if (CheckInvokeClassMismatch</* kThrow */ true>(dex_cache, type, method_idx, class_loader)) {
    307       DCHECK(Thread::Current()->IsExceptionPending());
    308       return nullptr;
    309     }
    310     // Check access.
    311     ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
    312     if (!referring_class->CheckResolvedMethodAccess(resolved_method->GetDeclaringClass(),
    313                                                     resolved_method,
    314                                                     dex_cache,
    315                                                     method_idx,
    316                                                     type)) {
    317       DCHECK(Thread::Current()->IsExceptionPending());
    318       return nullptr;
    319     }
    320     // Check if the invoke type matches the method type.
    321     if (UNLIKELY(resolved_method->CheckIncompatibleClassChange(type))) {
    322       ThrowIncompatibleClassChangeError(type,
    323                                         resolved_method->GetInvokeType(),
    324                                         resolved_method,
    325                                         referrer);
    326       return nullptr;
    327     }
    328   }
    329   // Note: We cannot check here to see whether we added the method to the cache. It
    330   //       might be an erroneous class, which results in it being hidden from us.
    331   return resolved_method;
    332 }
    333 
    334 inline ArtField* ClassLinker::LookupResolvedField(uint32_t field_idx,
    335                                                   ArtMethod* referrer,
    336                                                   bool is_static) {
    337   // We do not need the read barrier for getting the DexCache for the initial resolved field
    338   // lookup as both from-space and to-space copies point to the same native resolved fields array.
    339   ArtField* field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
    340       field_idx, image_pointer_size_);
    341   if (field == nullptr) {
    342     ObjPtr<mirror::ClassLoader> class_loader = referrer->GetDeclaringClass()->GetClassLoader();
    343     field = LookupResolvedField(field_idx, referrer->GetDexCache(), class_loader, is_static);
    344   }
    345   return field;
    346 }
    347 
    348 inline ArtField* ClassLinker::ResolveField(uint32_t field_idx,
    349                                            ArtMethod* referrer,
    350                                            bool is_static) {
    351   Thread::PoisonObjectPointersIfDebug();
    352   // We do not need the read barrier for getting the DexCache for the initial resolved field
    353   // lookup as both from-space and to-space copies point to the same native resolved fields array.
    354   ArtField* resolved_field = referrer->GetDexCache<kWithoutReadBarrier>()->GetResolvedField(
    355       field_idx, image_pointer_size_);
    356   if (UNLIKELY(resolved_field == nullptr)) {
    357     StackHandleScope<2> hs(Thread::Current());
    358     ObjPtr<mirror::Class> referring_class = referrer->GetDeclaringClass();
    359     Handle<mirror::DexCache> dex_cache(hs.NewHandle(referrer->GetDexCache()));
    360     Handle<mirror::ClassLoader> class_loader(hs.NewHandle(referring_class->GetClassLoader()));
    361     resolved_field = ResolveField(field_idx, dex_cache, class_loader, is_static);
    362     // Note: We cannot check here to see whether we added the field to the cache. The type
    363     //       might be an erroneous class, which results in it being hidden from us.
    364   }
    365   return resolved_field;
    366 }
    367 
    368 inline mirror::Class* ClassLinker::GetClassRoot(ClassRoot class_root) {
    369   DCHECK(!class_roots_.IsNull());
    370   mirror::ObjectArray<mirror::Class>* class_roots = class_roots_.Read();
    371   ObjPtr<mirror::Class> klass = class_roots->Get(class_root);
    372   DCHECK(klass != nullptr);
    373   return klass.Ptr();
    374 }
    375 
    376 template <class Visitor>
    377 inline void ClassLinker::VisitClassTables(const Visitor& visitor) {
    378   Thread* const self = Thread::Current();
    379   WriterMutexLock mu(self, *Locks::classlinker_classes_lock_);
    380   for (const ClassLoaderData& data : class_loaders_) {
    381     if (data.class_table != nullptr) {
    382       visitor(data.class_table);
    383     }
    384   }
    385 }
    386 
    387 }  // namespace art
    388 
    389 #endif  // ART_RUNTIME_CLASS_LINKER_INL_H_
    390