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"
20b2ec9f5c128673c43f776cbe12c8eeb0a6884ebbDavid Sehr#include "dex/descriptors_names.h"
219e734c7ab4599d7747a05db0dc73c7b668cb6683David Sehr#include "dex/dex_file_loader.h"
2264bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes#include "jni_internal.h"
232dd0e2cea360bc9206eb88ecc40d259e796c239dIan Rogers#include "mirror/class_loader.h"
244f6ad8ab428038129b2d0d6c40b7fd625cca15e1Ian Rogers#include "mirror/object-inl.h"
2587583b3de6e811e141f8c97c1f796eb516e8a751Andreas Gampe#include "native_util.h"
26e431e2758d62cf56f7f347f5a8c9d79e41b6dcd7Steven Moreland#include "nativehelper/jni_macros.h"
27373a9b5c718a45ac484afcf4fe6ce84f4bb562b3Andreas Gampe#include "nativehelper/scoped_local_ref.h"
28373a9b5c718a45ac484afcf4fe6ce84f4bb562b3Andreas Gampe#include "nativehelper/scoped_utf_chars.h"
2934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe#include "obj_ptr.h"
300795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier#include "scoped_fast_native_object_access-inl.h"
31a1d2f957a21319d1110bebb9a52f46fd1c67ffafAndreas Gampe#include "well_known_classes.h"
3264bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes#include "zip_archive.h"
3364bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes
3464bf5a33d55aa779ef452552a466943002d39e4fElliott Hughesnamespace art {
3564bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes
3634ee6842a283afe107f0c1df941393f955323b52Andreas Gampe// A class so we can be friends with ClassLinker and access internal methods.
3734ee6842a283afe107f0c1df941393f955323b52Andreas Gampeclass VMClassLoader {
3834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe public:
3934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  static mirror::Class* LookupClass(ClassLinker* cl,
4034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                    Thread* self,
4134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                    const char* descriptor,
4234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                    size_t hash,
4334ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                    ObjPtr<mirror::ClassLoader> class_loader)
4434ee6842a283afe107f0c1df941393f955323b52Andreas Gampe      REQUIRES(!Locks::classlinker_classes_lock_)
4534ee6842a283afe107f0c1df941393f955323b52Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_) {
4634ee6842a283afe107f0c1df941393f955323b52Andreas Gampe    return cl->LookupClass(self, descriptor, hash, class_loader);
4734ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  }
4834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe
4934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  static ObjPtr<mirror::Class> FindClassInPathClassLoader(ClassLinker* cl,
5034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                          ScopedObjectAccessAlreadyRunnable& soa,
5134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                          Thread* self,
5234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                          const char* descriptor,
5334ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                          size_t hash,
5434ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                          Handle<mirror::ClassLoader> class_loader)
5534ee6842a283afe107f0c1df941393f955323b52Andreas Gampe      REQUIRES_SHARED(Locks::mutator_lock_) {
5634ee6842a283afe107f0c1df941393f955323b52Andreas Gampe    ObjPtr<mirror::Class> result;
577d8d8ff0727a7aa9d11c738f13a7e06d3c4c3d68Nicolas Geoffray    if (cl->FindClassInBaseDexClassLoader(soa, self, descriptor, hash, class_loader, &result)) {
5834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe      return result;
5934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe    }
6034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe    return nullptr;
6134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  }
6234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe};
6334ee6842a283afe107f0c1df941393f955323b52Andreas Gampe
647b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogersstatic jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader,
657b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers                                            jstring javaName) {
6653b8b09fc80329539585dcf43657bc5f4ecefdffIan Rogers  ScopedFastNativeObjectAccess soa(env);
670795f23920ee9aabf28e45c63cd592dcccf00216Mathieu Chartier  ObjPtr<mirror::ClassLoader> loader = soa.Decode<mirror::ClassLoader>(javaLoader);
6864bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes  ScopedUtfChars name(env, javaName);
697b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers  if (name.c_str() == nullptr) {
707b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers    return nullptr;
7164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes  }
72ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier  ClassLinker* cl = Runtime::Current()->GetClassLinker();
7334ee6842a283afe107f0c1df941393f955323b52Andreas Gampe
7434ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  // Compute hash once.
75f91c8c328c922ecd522e1d3508d2603e78de8a7bBrian Carlstrom  std::string descriptor(DotToDescriptor(name.c_str()));
76e7c9a8c2b8481aafbc6af4ce6229bd361ba24742Mathieu Chartier  const size_t descriptor_hash = ComputeModifiedUtf8Hash(descriptor.c_str());
7734ee6842a283afe107f0c1df941393f955323b52Andreas Gampe
7834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  ObjPtr<mirror::Class> c = VMClassLoader::LookupClass(cl,
7934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                       soa.Self(),
8034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                       descriptor.c_str(),
8134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                       descriptor_hash,
8234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                       loader);
837b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers  if (c != nullptr && c->IsResolved()) {
8400f7d0eaa6bd93d33bf0c1429bf4ba0b3f28abacIan Rogers    return soa.AddLocalReference<jclass>(c);
85be125a931c8cf7274345c69b2bf35fb6e66e4001Ian Rogers  }
867c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao  // If class is erroneous, throw the earlier failure, wrapped in certain cases. See b/28787733.
877c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao  if (c != nullptr && c->IsErroneous()) {
88bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier    cl->ThrowEarlierClassFailure(c.Ptr());
897c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao    Thread* self = soa.Self();
90bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier    ObjPtr<mirror::Class> iae_class =
917c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao        self->DecodeJObject(WellKnownClasses::java_lang_IllegalAccessError)->AsClass();
92bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier    ObjPtr<mirror::Class> ncdfe_class =
937c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao        self->DecodeJObject(WellKnownClasses::java_lang_NoClassDefFoundError)->AsClass();
94bc5a795c0d486c84913d987cad5846ded840cea6Mathieu Chartier    ObjPtr<mirror::Class> exception = self->GetException()->GetClass();
9572ab684871f870aead76b23cb67deb046107b380Vladimir Marko    if (exception == iae_class || exception == ncdfe_class) {
967c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao      self->ThrowNewWrappedException("Ljava/lang/ClassNotFoundException;",
97709b070044354d9f47641f273edacaeeb0240ab7David Sehr                                     c->PrettyDescriptor().c_str());
987c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao    }
997c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao    return nullptr;
1007c8aa8357196781c811a73d2eb66aaaa1681ce36Jeff Hao  }
10134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe
10234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  // Hard-coded performance optimization: We know that all failed libcore calls to findLoadedClass
10334ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  //                                      are followed by a call to the the classloader to actually
10434ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  //                                      load the class.
105ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier  if (loader != nullptr) {
106ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier    // Try the common case.
107ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier    StackHandleScope<1> hs(soa.Self());
10834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe    c = VMClassLoader::FindClassInPathClassLoader(cl,
10934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                  soa,
11034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                  soa.Self(),
11134ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                  descriptor.c_str(),
11234ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                  descriptor_hash,
11334ee6842a283afe107f0c1df941393f955323b52Andreas Gampe                                                  hs.NewHandle(loader));
114ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier    if (c != nullptr) {
115ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier      return soa.AddLocalReference<jclass>(c);
116ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier    }
117ab0ed82ff64ba5a751dcc0a38d0e0c41c53dc923Mathieu Chartier  }
11834ee6842a283afe107f0c1df941393f955323b52Andreas Gampe
11934ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  // The class wasn't loaded, yet, and our fast-path did not apply (e.g., we didn't understand the
12034ee6842a283afe107f0c1df941393f955323b52Andreas Gampe  // classloader chain).
1217b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers  return nullptr;
12264bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes}
12364bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes
12464bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes/*
125ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fuller * Returns an array of entries from the boot classpath that could contain resources.
12664bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes */
127ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fullerstatic jobjectArray VMClassLoader_getBootClassPathEntries(JNIEnv* env, jclass) {
1287b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers  const std::vector<const DexFile*>& path =
1297b078e8c04f3e1451dbdd18543c8b9692b5b067eIan Rogers      Runtime::Current()->GetClassLinker()->GetBootClassPath();
1304b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko  jobjectArray array =
1314b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko      env->NewObjectArray(path.size(), WellKnownClasses::java_lang_String, nullptr);
1324b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko  if (array == nullptr) {
1334b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko    DCHECK(env->ExceptionCheck());
1344b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko    return nullptr;
1354b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko  }
136ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fuller  for (size_t i = 0; i < path.size(); ++i) {
137ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fuller    const DexFile* dex_file = path[i];
138cb8f9e8a2941971c049b26745ea713c859342d9bAndreas Gampe
139a308a327884920cbb1e3e62964c4b5a01c29af8cCalin Juravle    // For multidex locations, e.g., x.jar!classes2.dex, we want to look into x.jar.
14079c87da9d4698ec58ece65af0065eebd55a1cfe0Mathieu Chartier    const std::string location(DexFileLoader::GetBaseLocation(dex_file->GetLocation()));
141cb8f9e8a2941971c049b26745ea713c859342d9bAndreas Gampe
1424b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko    ScopedLocalRef<jstring> javaPath(env, env->NewStringUTF(location.c_str()));
1434b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko    if (javaPath.get() == nullptr) {
1444b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko      DCHECK(env->ExceptionCheck());
1454b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko      return nullptr;
1464b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko    }
1474b3d690c37dbea09906acd4a05f59c7674f9a2d0Vladimir Marko    env->SetObjectArrayElement(array, i, javaPath.get());
14864bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes  }
149ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fuller  return array;
15064bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes}
15164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes
15264bf5a33d55aa779ef452552a466943002d39e4fElliott Hughesstatic JNINativeMethod gMethods[] = {
1533b6f440dbd066f03a737da6d292074f47b3fbc29Igor Murashkin  FAST_NATIVE_METHOD(VMClassLoader, findLoadedClass, "(Ljava/lang/ClassLoader;Ljava/lang/String;)Ljava/lang/Class;"),
154ef486052f89f088dfc3fe31f6dce974c8f4ce522Neil Fuller  NATIVE_METHOD(VMClassLoader, getBootClassPathEntries, "()[Ljava/lang/String;"),
15564bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes};
15664bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes
15764bf5a33d55aa779ef452552a466943002d39e4fElliott Hughesvoid register_java_lang_VMClassLoader(JNIEnv* env) {
158eac766769e3114a078c188ea26776a81f0edb3cfElliott Hughes  REGISTER_NATIVE_METHODS("java/lang/VMClassLoader");
15964bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes}
16064bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes
16164bf5a33d55aa779ef452552a466943002d39e4fElliott Hughes}  // namespace art
162