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