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