java_lang_VMClassLoader.cc revision 373a9b5c718a45ac484afcf4fe6ce84f4bb562b3
164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes/* 264bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * Copyright (C) 2008 The Android Open Source Project 364bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * 464bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * Licensed under the Apache License, Version 2.0 (the "License"); 564bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * you may not use this file except in compliance with the License. 664bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * You may obtain a copy of the License at 764bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * 864bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * http://www.apache.org/licenses/LICENSE-2.0 964bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * 1064bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * Unless required by applicable law or agreed to in writing, software 1164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * distributed under the License is distributed on an "AS IS" BASIS, 1264bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1364bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * See the License for the specific language governing permissions and 1464bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes * limitations under the License. 1564bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes */ 1664bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes 17277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe#include "java_lang_VMClassLoader.h" 18277ccbd200ea43590dfc06a93ae184a765327ad0Andreas Gampe 1964bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes#include "class_linker.h" 2079c87da9d4698ec58ece65af0065eebd55a1cfe0Mathieu Chartier#include "dex_file_loader.h" 2164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes#include "jni_internal.h" 222dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h" 234f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h" 2487583b3de6e811e141f8c97c1f796eb516e8a751Andreas Gampe#include "native_util.h" 25e431e2758d62cf56f7f347f5a8c9d79e41b6dcd7Steven Moreland#include "nativehelper/jni_macros.h" 26373a9b5c718a45ac484afcf4fe6ce84f4bb562b3Andreas Gampe#include "nativehelper/scoped_local_ref.h" 27373a9b5c718a45ac484afcf4fe6ce84f4bb562b3Andreas Gampe#include "nativehelper/scoped_utf_chars.h" 2834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe#include "obj_ptr.h" 290795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_fast_native_object_access-inl.h" 30a1d2f957a21319d1110bebb9a52f46fd1c67ffafAndreas Gampe#include "well_known_classes.h" 3164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes#include "zip_archive.h" 3264bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes 3364bf5a33d55aa779ef452552a466943002d39e4fElliott Hughesnamespace art { 3464bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes 3534ee6842a283afe107f0c1df941393f955323b52Andreas Gampe// A class so we can be friends with ClassLinker and access internal methods. 3634ee6842a283afe107f0c1df941393f955323b52Andreas Gampeclass VMClassLoader { 3734ee6842a283afe107f0c1df941393f955323b52Andreas Gampe public: 3834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe static mirror::Class* LookupClass(ClassLinker* cl, 3934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe Thread* self, 4034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe const char* descriptor, 4134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe size_t hash, 4234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe ObjPtr<mirror::ClassLoader> class_loader) 4334ee6842a283afe107f0c1df941393f955323b52Andreas Gampe REQUIRES(!Locks::classlinker_classes_lock_) 4434ee6842a283afe107f0c1df941393f955323b52Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 4534ee6842a283afe107f0c1df941393f955323b52Andreas Gampe return cl->LookupClass(self, descriptor, hash, class_loader); 4634ee6842a283afe107f0c1df941393f955323b52Andreas Gampe } 4734ee6842a283afe107f0c1df941393f955323b52Andreas Gampe 4834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe static ObjPtr<mirror::Class> FindClassInPathClassLoader(ClassLinker* cl, 4934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe ScopedObjectAccessAlreadyRunnable& soa, 5034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe Thread* self, 5134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe const char* descriptor, 5234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe size_t hash, 5334ee6842a283afe107f0c1df941393f955323b52Andreas Gampe Handle<mirror::ClassLoader> class_loader) 5434ee6842a283afe107f0c1df941393f955323b52Andreas Gampe REQUIRES_SHARED(Locks::mutator_lock_) { 5534ee6842a283afe107f0c1df941393f955323b52Andreas Gampe ObjPtr<mirror::Class> result; 567d8d8ff0727a7aa9d11c738f13a7e06d3c4c3d68Nicolas Geoffray if (cl->FindClassInBaseDexClassLoader(soa, self, descriptor, hash, class_loader, &result)) { 5734ee6842a283afe107f0c1df941393f955323b52Andreas Gampe return result; 5834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe } 5934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe return nullptr; 6034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe } 6134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe}; 6234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe 637b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogersstatic jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader, 647b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers jstring javaName) { 6553b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers ScopedFastNativeObjectAccess soa(env); 660795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier ObjPtr<mirror::ClassLoader> loader = soa.Decode<mirror::ClassLoader>(javaLoader); 6764bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes ScopedUtfChars name(env, javaName); 687b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers if (name.c_str() == nullptr) { 697b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers return nullptr; 7064bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes } 71ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier ClassLinker* cl = Runtime::Current()->GetClassLinker(); 7234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe 7334ee6842a283afe107f0c1df941393f955323b52Andreas Gampe // Compute hash once. 74f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom std::string descriptor(DotToDescriptor(name.c_str())); 75e7c9a8c2b8481aafbc6af4ce6229bd361ba24742Mathieu Chartier const size_t descriptor_hash = ComputeModifiedUtf8Hash(descriptor.c_str()); 7634ee6842a283afe107f0c1df941393f955323b52Andreas Gampe 7734ee6842a283afe107f0c1df941393f955323b52Andreas Gampe ObjPtr<mirror::Class> c = VMClassLoader::LookupClass(cl, 7834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe soa.Self(), 7934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe descriptor.c_str(), 8034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe descriptor_hash, 8134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe loader); 827b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers if (c != nullptr && c->IsResolved()) { 8300f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers return soa.AddLocalReference<jclass>(c); 84be125a931c8cf7274345c69b2bf35fb6e66e4001Ian Rogers } 857c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao // If class is erroneous, throw the earlier failure, wrapped in certain cases. See b/28787733. 867c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao if (c != nullptr && c->IsErroneous()) { 87bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier cl->ThrowEarlierClassFailure(c.Ptr()); 887c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao Thread* self = soa.Self(); 89bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier ObjPtr<mirror::Class> iae_class = 907c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao self->DecodeJObject(WellKnownClasses::java_lang_IllegalAccessError)->AsClass(); 91bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier ObjPtr<mirror::Class> ncdfe_class = 927c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao self->DecodeJObject(WellKnownClasses::java_lang_NoClassDefFoundError)->AsClass(); 93bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier ObjPtr<mirror::Class> exception = self->GetException()->GetClass(); 9472ab684871f870aead76b23cb67deb046107b380Vladimir Marko if (exception == iae_class || exception == ncdfe_class) { 957c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao self->ThrowNewWrappedException("Ljava/lang/ClassNotFoundException;", 96709b070044354d9f47641f273edacaeeb0240ab7David Sehr c->PrettyDescriptor().c_str()); 977c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao } 987c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao return nullptr; 997c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao } 10034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe 10134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe // Hard-coded performance optimization: We know that all failed libcore calls to findLoadedClass 10234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe // are followed by a call to the the classloader to actually 10334ee6842a283afe107f0c1df941393f955323b52Andreas Gampe // load the class. 104ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier if (loader != nullptr) { 105ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier // Try the common case. 106ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier StackHandleScope<1> hs(soa.Self()); 10734ee6842a283afe107f0c1df941393f955323b52Andreas Gampe c = VMClassLoader::FindClassInPathClassLoader(cl, 10834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe soa, 10934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe soa.Self(), 11034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe descriptor.c_str(), 11134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe descriptor_hash, 11234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe hs.NewHandle(loader)); 113ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier if (c != nullptr) { 114ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier return soa.AddLocalReference<jclass>(c); 115ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier } 116ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier } 11734ee6842a283afe107f0c1df941393f955323b52Andreas Gampe 11834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe // The class wasn't loaded, yet, and our fast-path did not apply (e.g., we didn't understand the 11934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe // classloader chain). 1207b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers return nullptr; 12164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes} 12264bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes 12364bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes/* 124ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fuller * Returns an array of entries from the boot classpath that could contain resources. 12564bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes */ 126ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fullerstatic jobjectArray VMClassLoader_getBootClassPathEntries(JNIEnv* env, jclass) { 1277b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers const std::vector<const DexFile*>& path = 1287b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers Runtime::Current()->GetClassLinker()->GetBootClassPath(); 1294b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko jobjectArray array = 1304b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko env->NewObjectArray(path.size(), WellKnownClasses::java_lang_String, nullptr); 1314b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko if (array == nullptr) { 1324b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko DCHECK(env->ExceptionCheck()); 1334b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko return nullptr; 1344b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko } 135ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fuller for (size_t i = 0; i < path.size(); ++i) { 136ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fuller const DexFile* dex_file = path[i]; 137cb8f9e8a2941971c049b26745ea713c859342d9bAndreas Gampe 138a308a327884920cbb1e3e62964c4b5a01c29af8cCalin Juravle // For multidex locations, e.g., x.jar!classes2.dex, we want to look into x.jar. 13979c87da9d4698ec58ece65af0065eebd55a1cfe0Mathieu Chartier const std::string location(DexFileLoader::GetBaseLocation(dex_file->GetLocation())); 140cb8f9e8a2941971c049b26745ea713c859342d9bAndreas Gampe 1414b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko ScopedLocalRef<jstring> javaPath(env, env->NewStringUTF(location.c_str())); 1424b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko if (javaPath.get() == nullptr) { 1434b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko DCHECK(env->ExceptionCheck()); 1444b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko return nullptr; 1454b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko } 1464b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko env->SetObjectArrayElement(array, i, javaPath.get()); 14764bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes } 148ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fuller return array; 14964bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes} 15064bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes 15164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughesstatic JNINativeMethod gMethods[] = { 1523b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin FAST_NATIVE_METHOD(VMClassLoader, findLoadedClass, "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;"), 153ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fuller NATIVE_METHOD(VMClassLoader, getBootClassPathEntries, "()[Ljava/lang/String;"), 15464bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes}; 15564bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes 15664bf5a33d55aa779ef452552a466943002d39e4fElliott Hughesvoid register_java_lang_VMClassLoader(JNIEnv* env) { 157eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes REGISTER_NATIVE_METHODS("java/lang/VMClassLoader"); 15864bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes} 15964bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes 16064bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes} // namespace art 161