blob: b67735c2d26d863b0e4e9fd2dd66df4446fcd38e [file] [log] [blame]
/*
*******************************************************************************
* Copyright (C) 2015, International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.impl;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* This utility class is used for resolving a right ClassLoader from
* a given class. getClassLoader always returns a non-null ClassLoader
* even a class is loaded through the bootstrap class loader of JRE.
*/
public class ClassLoaderUtil {
private static class BootstrapClassLoader extends ClassLoader {
BootstrapClassLoader() {
// Object.class.getClassLoader() may return null.
//
// On Android, the behavior of super(null) is not guaranteed,
// but Object.class.getClassLoader() actually returns the
// bootstrap class loader. Note that we probably do not reach
// this constructor on Android, because ClassLoaderUtil.getClassLoader()
// should get non-null ClassLoader before calling
// ClassLoaderUtil.getBootstrapClassLoader().
//
// On other common JREs (such as Oracle, OpenJDK),
// Object.class.getClassLoader() returns null, but
// super(null) is commonly used for accessing the bootstrap
// class loader.
super(Object.class.getClassLoader());
}
}
private static volatile ClassLoader BOOTSTRAP_CLASSLOADER;
/**
* Lazily create a singleton BootstrapClassLoader.
* This class loader might be necessary when ICU4J classes are
* initialized by bootstrap class loader.
*
* @return The BootStrapClassLoader singleton instance
*/
private static ClassLoader getBootstrapClassLoader() {
if (BOOTSTRAP_CLASSLOADER == null) {
synchronized(ClassLoaderUtil.class) {
if (BOOTSTRAP_CLASSLOADER == null) {
ClassLoader cl = null;
if (System.getSecurityManager() != null) {
cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
public BootstrapClassLoader run() {
return new BootstrapClassLoader();
}
});
} else {
cl = new BootstrapClassLoader();
}
BOOTSTRAP_CLASSLOADER = cl;
}
}
}
return BOOTSTRAP_CLASSLOADER;
}
/**
* Returns the class loader used for loading the specified class.
* @param cls The class
* @return the class loader
*/
public static ClassLoader getClassLoader(Class<?> cls) {
ClassLoader cl = cls.getClassLoader();
if (cl == null) {
cl = getClassLoader();
}
return cl;
}
/**
* Returns a fallback class loader.
* @return A class loader
*/
public static ClassLoader getClassLoader() {
ClassLoader cl = Thread.currentThread().getContextClassLoader();
if (cl == null) {
cl = ClassLoader.getSystemClassLoader();
if (cl == null) {
// When this method is called for initializing a ICU4J class
// during bootstrap, cl might be still null (other than Android?).
// In this case, we want to use the bootstrap class loader.
cl = getBootstrapClassLoader();
}
}
return cl;
}
}