libcore\ojluni\src\main\java\java\lang\ClassLoader.java
protected Class<?> loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
// First, check if the class has already been loaded
Class<?> c = findLoadedClass(name);
if (c == null) {
try {
if (parent != null) {
c = parent.loadClass(name, false);
} else {
c = findBootstrapClassOrNull(name);
}
} catch (ClassNotFoundException e) {
// ClassNotFoundException thrown if class not found
// from the non-null parent class loader
}
if (c == null) {
// If still not found, then invoke findClass in order
// to find the class.
c = findClass(name);
}
}
return c;
}
/**
* Returns the class with the given binary name if this
* loader has been recorded by the Java virtual machine as an initiating
* loader of a class with that binary name. Otherwise
* null is returned.
*
* @param name
* The binary name of the class
*
* @return The Class object, or null if the class has
* not been loaded
*
* @since 1.1
*/
protected final Class<?> findLoadedClass(String name) {
ClassLoader loader;
if (this == BootClassLoader.getInstance())
loader = null;
else
loader = this;
return VMClassLoader.findLoadedClass(loader, name);
}
libcore\libart\src\main\java\java\lang\VMClassLoader.java
@FastNative
native static Class findLoadedClass(ClassLoader cl, String name);
art\runtime\native\java_lang_VMClassLoader.cc
static jclass VMClassLoader_findLoadedClass(JNIEnv* env, jclass, jobject javaLoader,
jstring javaName) {
// Hard-coded performance optimization: We know that all failed libcore calls to findLoadedClass
// are followed by a call to the the classloader to actually
// load the class.
if (loader != nullptr) {
// Try the common case.
StackHandleScope<1> hs(soa.Self());
c = VMClassLoader::FindClassInPathClassLoader(cl,
soa,
soa.Self(),
descriptor.c_str(),
descriptor_hash,
hs.NewHandle(loader));
if (c != nullptr) {
return soa.AddLocalReference<jclass>(c);
}
}
// The class wasn't loaded, yet, and our fast-path did not apply (e.g., we didn't understand the
// classloader chain).
return nullptr;
}
static ObjPtr<mirror::Class> FindClassInPathClassLoader(ClassLinker* cl,
ScopedObjectAccessAlreadyRunnable& soa,
Thread* self,
const char* descriptor,
size_t hash,
Handle<mirror::ClassLoader> class_loader)
REQUIRES_SHARED(Locks::mutator_lock_) {
ObjPtr<mirror::Class> result;
if (cl->FindClassInBaseDexClassLoader(soa, self, descriptor, hash, class_loader, &result)) {
DCHECK(!self->IsExceptionPending());
return result;
}
if (self->IsExceptionPending()) {
self->ClearException();
}
return nullptr;
}
art\runtime\class_linker.cc
bool ClassLinker::FindClassInBaseDexClassLoader(ScopedObjectAccessAlreadyRunnable& soa,
Thread* self,
const char* descriptor,
size_t hash,
Handle<mirror::ClassLoader> class_loader,
/*out*/ ObjPtr<mirror::Class>* result) {
// Termination case: boot class loader.
if (IsBootClassLoader(soa, class_loader.Get())) {
*result = FindClassInBootClassLoaderClassPath(self, descriptor, hash);
return true;
}
if (IsPathOrDexClassLoader(soa, class_loader) || IsInMemoryDexClassLoader(soa, class_loader)) {
// For regular path or dex class loader the search order is:
// - parent
// - shared libraries
// - class loader dex files
// Handles as RegisterDexFile may allocate dex caches (and cause thread suspension).
StackHandleScope<1> hs(self);
Handle<mirror::ClassLoader> h_parent(hs.NewHandle(class_loader->GetParent()));
if (!FindClassInBaseDexClassLoader(soa, self, descriptor, hash, h_parent, result)) {
return false; // One of the parents is not supported.
}
if (*result != nullptr) {
return true; // Found the class up the chain.
}
if (!FindClassInSharedLibraries(soa, self, descriptor, hash, class_loader, result)) {
return false; // One of the shared library loader is not supported.
}
if (*result != nullptr) {
return true; // Found the class in a shared library.
}
// Search the current class loader classpath.
*result = FindClassInBaseDexClassLoaderClassPath(soa, descriptor, hash, class_loader);
return !soa.Self()->IsExceptionPending();
}
if (IsDelegateLastClassLoader(soa, class_loader)) {
// For delegate last, the search order is:
// - boot class path
// - shared libraries
// - class loader dex files
// - parent
*result = FindClassInBootClassLoaderClassPath(self, descriptor, hash);
if (*result != nullptr) {
return true; // The class is part of the boot class path.
}
if (self->IsExceptionPending()) {
// Pending exception means there was an error other than ClassNotFound that must be returned
// to the caller.
return false;
}
if (!FindClassInSharedLibraries(soa, self, descriptor, hash, class_loader, result)) {
return false; // One of the shared library loader is not supported.
}
if (*result != nullptr) {
return true; // Found the class in a shared library.
}
*result = FindClassInBaseDexClassLoaderClassPath(soa, descriptor, hash, class_loader);
if (*result != nullptr) {
return true; // Found the class in the current class loader
}
if (self->IsExceptionPending()) {
// Pending exception means there was an error other than ClassNotFound that must be returned
// to the caller.
return false;
}
// Handles as RegisterDexFile may allocate dex caches (and cause thread suspension).
StackHandleScope<1> hs(self);
Handle<mirror::ClassLoader> h_parent(hs.NewHandle(class_loader->GetParent()));
return FindClassInBaseDexClassLoader(soa, self, descriptor, hash, h_parent, result);
}
// Unsupported class loader.
*result = nullptr;
return false;
}