1 /* 2 ******************************************************************************* 3 * Copyright (C) 2015, International Business Machines Corporation and 4 * others. All Rights Reserved. 5 ******************************************************************************* 6 */ 7 package com.ibm.icu.impl; 8 9 import java.security.AccessController; 10 import java.security.PrivilegedAction; 11 12 13 /** 14 * This utility class is used for resolving a right ClassLoader from 15 * a given class. getClassLoader always returns a non-null ClassLoader 16 * even a class is loaded through the bootstrap class loader of JRE. 17 */ 18 public class ClassLoaderUtil { 19 20 private static class BootstrapClassLoader extends ClassLoader { BootstrapClassLoader()21 BootstrapClassLoader() { 22 // Object.class.getClassLoader() may return null. 23 // 24 // On Android, the behavior of super(null) is not guaranteed, 25 // but Object.class.getClassLoader() actually returns the 26 // bootstrap class loader. Note that we probably do not reach 27 // this constructor on Android, because ClassLoaderUtil.getClassLoader() 28 // should get non-null ClassLoader before calling 29 // ClassLoaderUtil.getBootstrapClassLoader(). 30 // 31 // On other common JREs (such as Oracle, OpenJDK), 32 // Object.class.getClassLoader() returns null, but 33 // super(null) is commonly used for accessing the bootstrap 34 // class loader. 35 super(Object.class.getClassLoader()); 36 } 37 } 38 39 private static volatile ClassLoader BOOTSTRAP_CLASSLOADER; 40 41 /** 42 * Lazily create a singleton BootstrapClassLoader. 43 * This class loader might be necessary when ICU4J classes are 44 * initialized by bootstrap class loader. 45 * 46 * @return The BootStrapClassLoader singleton instance 47 */ getBootstrapClassLoader()48 private static ClassLoader getBootstrapClassLoader() { 49 if (BOOTSTRAP_CLASSLOADER == null) { 50 synchronized(ClassLoaderUtil.class) { 51 if (BOOTSTRAP_CLASSLOADER == null) { 52 ClassLoader cl = null; 53 if (System.getSecurityManager() != null) { 54 cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { 55 public BootstrapClassLoader run() { 56 return new BootstrapClassLoader(); 57 } 58 }); 59 } else { 60 cl = new BootstrapClassLoader(); 61 } 62 BOOTSTRAP_CLASSLOADER = cl; 63 } 64 } 65 } 66 return BOOTSTRAP_CLASSLOADER; 67 } 68 69 70 /** 71 * Returns the class loader used for loading the specified class. 72 * @param cls The class 73 * @return the class loader 74 */ getClassLoader(Class<?> cls)75 public static ClassLoader getClassLoader(Class<?> cls) { 76 ClassLoader cl = cls.getClassLoader(); 77 if (cl == null) { 78 cl = getClassLoader(); 79 } 80 return cl; 81 } 82 83 /** 84 * Returns a fallback class loader. 85 * @return A class loader 86 */ getClassLoader()87 public static ClassLoader getClassLoader() { 88 ClassLoader cl = Thread.currentThread().getContextClassLoader(); 89 if (cl == null) { 90 cl = ClassLoader.getSystemClassLoader(); 91 if (cl == null) { 92 // When this method is called for initializing a ICU4J class 93 // during bootstrap, cl might be still null (other than Android?). 94 // In this case, we want to use the bootstrap class loader. 95 cl = getBootstrapClassLoader(); 96 } 97 } 98 return cl; 99 } 100 } 101