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