1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *     http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */
17 /*
18  * Copyright (C) 2008 The Android Open Source Project
19  *
20  * Licensed under the Apache License, Version 2.0 (the "License");
21  * you may not use this file except in compliance with the License.
22  * You may obtain a copy of the License at
23  *
24  * http://www.apache.org/licenses/LICENSE-2.0
25  *
26  * Unless required by applicable law or agreed to in writing, software
27  * distributed under the License is distributed on an "AS IS" BASIS,
28  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
29  * See the License for the specific language governing permissions and
30  * limitations under the License.
31  */
32 
33 package java.lang;
34 
35 import dalvik.system.PathClassLoader;
36 import java.io.IOException;
37 import java.io.InputStream;
38 import java.net.URL;
39 import java.nio.ByteBuffer;
40 import java.security.ProtectionDomain;
41 import java.util.Collection;
42 import java.util.Collections;
43 import java.util.Enumeration;
44 import java.util.HashMap;
45 import java.util.List;
46 import java.util.Map;
47 
48 /**
49  * Loads classes and resources from a repository. One or more class loaders are
50  * installed at runtime. These are consulted whenever the runtime system needs a
51  * specific class that is not yet available in-memory. Typically, class loaders
52  * are grouped into a tree where child class loaders delegate all requests to
53  * parent class loaders. Only if the parent class loader cannot satisfy the
54  * request, the child class loader itself tries to handle it.
55  * <p>
56  * {@code ClassLoader} is an abstract class that implements the common
57  * infrastructure required by all class loaders. Android provides several
58  * concrete implementations of the class, with
59  * {@link dalvik.system.PathClassLoader} being the one typically used. Other
60  * applications may implement subclasses of {@code ClassLoader} to provide
61  * special ways for loading classes.
62  * </p>
63  * @see Class
64  */
65 public abstract class ClassLoader {
66 
67     /**
68      * The 'System' ClassLoader - the one that is responsible for loading
69      * classes from the classpath. It is not equal to the bootstrap class loader -
70      * that one handles the built-in classes.
71      *
72      * Because of a potential class initialization race between ClassLoader and
73      * java.lang.System, reproducible when using JDWP with "suspend=y", we defer
74      * creation of the system class loader until first use. We use a static
75      * inner class to get synchronization at init time without having to sync on
76      * every access.
77      *
78      * @see #getSystemClassLoader()
79      */
80     static private class SystemClassLoader {
81         public static ClassLoader loader = ClassLoader.createSystemClassLoader();
82     }
83 
84     /**
85      * The parent ClassLoader.
86      */
87     private ClassLoader parent;
88 
89     /**
90      * The packages known to the class loader.
91      */
92     private Map<String, Package> packages = new HashMap<String, Package>();
93 
94     /**
95      * To avoid unloading individual classes, {@link java.lang.reflect.Proxy}
96      * only generates one class for each set of interfaces. This maps sets of
97      * interfaces to the proxy class that implements all of them. It is declared
98      * here so that these generated classes can be unloaded with their class
99      * loader.
100      *
101      * @hide
102      */
103     public final Map<List<Class<?>>, Class<?>> proxyCache =
104             new HashMap<List<Class<?>>, Class<?>>();
105 
106     /**
107      * Create the system class loader. Note this is NOT the bootstrap class
108      * loader (which is managed by the VM). We use a null value for the parent
109      * to indicate that the bootstrap loader is our parent.
110      */
createSystemClassLoader()111     private static ClassLoader createSystemClassLoader() {
112         String classPath = System.getProperty("java.class.path", ".");
113 
114         // String[] paths = classPath.split(":");
115         // URL[] urls = new URL[paths.length];
116         // for (int i = 0; i < paths.length; i++) {
117         // try {
118         // urls[i] = new URL("file://" + paths[i]);
119         // }
120         // catch (Exception ex) {
121         // ex.printStackTrace();
122         // }
123         // }
124         //
125         // return new java.net.URLClassLoader(urls, null);
126 
127         // TODO Make this a java.net.URLClassLoader once we have those?
128         return new PathClassLoader(classPath, BootClassLoader.getInstance());
129     }
130 
131     /**
132      * Returns the system class loader. This is the parent for new
133      * {@code ClassLoader} instances and is typically the class loader used to
134      * start the application.
135      */
getSystemClassLoader()136     public static ClassLoader getSystemClassLoader() {
137         return SystemClassLoader.loader;
138     }
139 
140     /**
141      * Finds the URL of the resource with the specified name. The system class
142      * loader's resource lookup algorithm is used to find the resource.
143      *
144      * @return the {@code URL} object for the requested resource or {@code null}
145      *         if the resource can not be found.
146      * @param resName
147      *            the name of the resource to find.
148      * @see Class#getResource
149      */
getSystemResource(String resName)150     public static URL getSystemResource(String resName) {
151         return SystemClassLoader.loader.getResource(resName);
152     }
153 
154     /**
155      * Returns an enumeration of URLs for the resource with the specified name.
156      * The system class loader's resource lookup algorithm is used to find the
157      * resource.
158      *
159      * @return an enumeration of {@code URL} objects containing the requested
160      *         resources.
161      * @param resName
162      *            the name of the resource to find.
163      * @throws IOException
164      *             if an I/O error occurs.
165      */
getSystemResources(String resName)166     public static Enumeration<URL> getSystemResources(String resName) throws IOException {
167         return SystemClassLoader.loader.getResources(resName);
168     }
169 
170     /**
171      * Returns a stream for the resource with the specified name. The system
172      * class loader's resource lookup algorithm is used to find the resource.
173      * Basically, the contents of the java.class.path are searched in order,
174      * looking for a path which matches the specified resource.
175      *
176      * @return a stream for the resource or {@code null}.
177      * @param resName
178      *            the name of the resource to find.
179      * @see Class#getResourceAsStream
180      */
getSystemResourceAsStream(String resName)181     public static InputStream getSystemResourceAsStream(String resName) {
182         return SystemClassLoader.loader.getResourceAsStream(resName);
183     }
184 
185     /**
186      * Constructs a new instance of this class with the system class loader as
187      * its parent.
188      */
ClassLoader()189     protected ClassLoader() {
190         this(getSystemClassLoader(), false);
191     }
192 
193     /**
194      * Constructs a new instance of this class with the specified class loader
195      * as its parent.
196      *
197      * @param parentLoader
198      *            The {@code ClassLoader} to use as the new class loader's
199      *            parent.
200      */
ClassLoader(ClassLoader parentLoader)201     protected ClassLoader(ClassLoader parentLoader) {
202         this(parentLoader, false);
203     }
204 
205     /*
206      * constructor for the BootClassLoader which needs parent to be null.
207      */
ClassLoader(ClassLoader parentLoader, boolean nullAllowed)208     ClassLoader(ClassLoader parentLoader, boolean nullAllowed) {
209         if (parentLoader == null && !nullAllowed) {
210             throw new NullPointerException("parentLoader == null && !nullAllowed");
211         }
212         parent = parentLoader;
213     }
214 
215     /**
216      * Constructs a new class from an array of bytes containing a class
217      * definition in class file format.
218      *
219      * @param classRep
220      *            the memory image of a class file.
221      * @param offset
222      *            the offset into {@code classRep}.
223      * @param length
224      *            the length of the class file.
225      * @return the {@code Class} object created from the specified subset of
226      *         data in {@code classRep}.
227      * @throws ClassFormatError
228      *             if {@code classRep} does not contain a valid class.
229      * @throws IndexOutOfBoundsException
230      *             if {@code offset < 0}, {@code length < 0} or if
231      *             {@code offset + length} is greater than the length of
232      *             {@code classRep}.
233      * @deprecated Use {@link #defineClass(String, byte[], int, int)}
234      */
235     @Deprecated
defineClass(byte[] classRep, int offset, int length)236     protected final Class<?> defineClass(byte[] classRep, int offset, int length)
237             throws ClassFormatError {
238         throw new UnsupportedOperationException("can't load this type of class file");
239     }
240 
241     /**
242      * Constructs a new class from an array of bytes containing a class
243      * definition in class file format.
244      *
245      * @param className
246      *            the expected name of the new class, may be {@code null} if not
247      *            known.
248      * @param classRep
249      *            the memory image of a class file.
250      * @param offset
251      *            the offset into {@code classRep}.
252      * @param length
253      *            the length of the class file.
254      * @return the {@code Class} object created from the specified subset of
255      *         data in {@code classRep}.
256      * @throws ClassFormatError
257      *             if {@code classRep} does not contain a valid class.
258      * @throws IndexOutOfBoundsException
259      *             if {@code offset < 0}, {@code length < 0} or if
260      *             {@code offset + length} is greater than the length of
261      *             {@code classRep}.
262      */
defineClass(String className, byte[] classRep, int offset, int length)263     protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length)
264             throws ClassFormatError {
265         throw new UnsupportedOperationException("can't load this type of class file");
266     }
267 
268     /**
269      * Constructs a new class from an array of bytes containing a class
270      * definition in class file format and assigns the specified protection
271      * domain to the new class. If the provided protection domain is
272      * {@code null} then a default protection domain is assigned to the class.
273      *
274      * @param className
275      *            the expected name of the new class, may be {@code null} if not
276      *            known.
277      * @param classRep
278      *            the memory image of a class file.
279      * @param offset
280      *            the offset into {@code classRep}.
281      * @param length
282      *            the length of the class file.
283      * @param protectionDomain
284      *            the protection domain to assign to the loaded class, may be
285      *            {@code null}.
286      * @return the {@code Class} object created from the specified subset of
287      *         data in {@code classRep}.
288      * @throws ClassFormatError
289      *             if {@code classRep} does not contain a valid class.
290      * @throws IndexOutOfBoundsException
291      *             if {@code offset < 0}, {@code length < 0} or if
292      *             {@code offset + length} is greater than the length of
293      *             {@code classRep}.
294      * @throws NoClassDefFoundError
295      *             if {@code className} is not equal to the name of the class
296      *             contained in {@code classRep}.
297      */
defineClass(String className, byte[] classRep, int offset, int length, ProtectionDomain protectionDomain)298     protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length,
299             ProtectionDomain protectionDomain) throws java.lang.ClassFormatError {
300         throw new UnsupportedOperationException("can't load this type of class file");
301     }
302 
303     /**
304      * Defines a new class with the specified name, byte code from the byte
305      * buffer and the optional protection domain. If the provided protection
306      * domain is {@code null} then a default protection domain is assigned to
307      * the class.
308      *
309      * @param name
310      *            the expected name of the new class, may be {@code null} if not
311      *            known.
312      * @param b
313      *            the byte buffer containing the byte code of the new class.
314      * @param protectionDomain
315      *            the protection domain to assign to the loaded class, may be
316      *            {@code null}.
317      * @return the {@code Class} object created from the data in {@code b}.
318      * @throws ClassFormatError
319      *             if {@code b} does not contain a valid class.
320      * @throws NoClassDefFoundError
321      *             if {@code className} is not equal to the name of the class
322      *             contained in {@code b}.
323      */
defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain)324     protected final Class<?> defineClass(String name, ByteBuffer b,
325             ProtectionDomain protectionDomain) throws ClassFormatError {
326 
327         byte[] temp = new byte[b.remaining()];
328         b.get(temp);
329         return defineClass(name, temp, 0, temp.length, protectionDomain);
330     }
331 
332     /**
333      * Overridden by subclasses, throws a {@code ClassNotFoundException} by
334      * default. This method is called by {@code loadClass} after the parent
335      * {@code ClassLoader} has failed to find a loaded class of the same name.
336      *
337      * @param className
338      *            the name of the class to look for.
339      * @return the {@code Class} object that is found.
340      * @throws ClassNotFoundException
341      *             if the class cannot be found.
342      */
findClass(String className)343     protected Class<?> findClass(String className) throws ClassNotFoundException {
344         throw new ClassNotFoundException(className);
345     }
346 
347     /**
348      * Returns the class with the specified name if it has already been loaded
349      * by the VM or {@code null} if it has not yet been loaded.
350      *
351      * @param className
352      *            the name of the class to look for.
353      * @return the {@code Class} object or {@code null} if the requested class
354      *         has not been loaded.
355      */
findLoadedClass(String className)356     protected final Class<?> findLoadedClass(String className) {
357         ClassLoader loader;
358         if (this == BootClassLoader.getInstance())
359             loader = null;
360         else
361             loader = this;
362         return VMClassLoader.findLoadedClass(loader, className);
363     }
364 
365     /**
366      * Finds the class with the specified name, loading it using the system
367      * class loader if necessary.
368      *
369      * @param className
370      *            the name of the class to look for.
371      * @return the {@code Class} object with the requested {@code className}.
372      * @throws ClassNotFoundException
373      *             if the class can not be found.
374      */
findSystemClass(String className)375     protected final Class<?> findSystemClass(String className) throws ClassNotFoundException {
376         return Class.forName(className, false, getSystemClassLoader());
377     }
378 
379     /**
380      * Returns this class loader's parent.
381      *
382      * @return this class loader's parent or {@code null}.
383      */
getParent()384     public final ClassLoader getParent() {
385         return parent;
386     }
387 
388     /**
389      * Returns the URL of the resource with the specified name. This
390      * implementation first tries to use the parent class loader to find the
391      * resource; if this fails then {@link #findResource(String)} is called to
392      * find the requested resource.
393      *
394      * @param resName
395      *            the name of the resource to find.
396      * @return the {@code URL} object for the requested resource or {@code null}
397      *         if the resource can not be found
398      * @see Class#getResource
399      */
getResource(String resName)400     public URL getResource(String resName) {
401         URL resource = parent.getResource(resName);
402         if (resource == null) {
403             resource = findResource(resName);
404         }
405         return resource;
406     }
407 
408     /**
409      * Returns an enumeration of URLs for the resource with the specified name.
410      * This implementation first uses this class loader's parent to find the
411      * resource, then it calls {@link #findResources(String)} to get additional
412      * URLs. The returned enumeration contains the {@code URL} objects of both
413      * find operations.
414      *
415      * @return an enumeration of {@code URL} objects for the requested resource.
416      * @param resName
417      *            the name of the resource to find.
418      * @throws IOException
419      *             if an I/O error occurs.
420      */
421     @SuppressWarnings("unchecked")
getResources(String resName)422     public Enumeration<URL> getResources(String resName) throws IOException {
423 
424         Enumeration<URL> first = parent.getResources(resName);
425         Enumeration<URL> second = findResources(resName);
426 
427         return new TwoEnumerationsInOne(first, second);
428     }
429 
430     /**
431      * Returns a stream for the resource with the specified name. See
432      * {@link #getResource(String)} for a description of the lookup algorithm
433      * used to find the resource.
434      *
435      * @return a stream for the resource or {@code null} if the resource can not be found
436      * @param resName
437      *            the name of the resource to find.
438      * @see Class#getResourceAsStream
439      */
getResourceAsStream(String resName)440     public InputStream getResourceAsStream(String resName) {
441         try {
442             URL url = getResource(resName);
443             if (url != null) {
444                 return url.openStream();
445             }
446         } catch (IOException ex) {
447             // Don't want to see the exception.
448         }
449 
450         return null;
451     }
452 
453     /**
454      * Loads the class with the specified name. Invoking this method is
455      * equivalent to calling {@code loadClass(className, false)}.
456      * <p>
457      * <strong>Note:</strong> In the Android reference implementation, the
458      * second parameter of {@link #loadClass(String, boolean)} is ignored
459      * anyway.
460      * </p>
461      *
462      * @return the {@code Class} object.
463      * @param className
464      *            the name of the class to look for.
465      * @throws ClassNotFoundException
466      *             if the class can not be found.
467      */
loadClass(String className)468     public Class<?> loadClass(String className) throws ClassNotFoundException {
469         return loadClass(className, false);
470     }
471 
472     /**
473      * Loads the class with the specified name, optionally linking it after
474      * loading. The following steps are performed:
475      * <ol>
476      * <li> Call {@link #findLoadedClass(String)} to determine if the requested
477      * class has already been loaded.</li>
478      * <li>If the class has not yet been loaded: Invoke this method on the
479      * parent class loader.</li>
480      * <li>If the class has still not been loaded: Call
481      * {@link #findClass(String)} to find the class.</li>
482      * </ol>
483      * <p>
484      * <strong>Note:</strong> In the Android reference implementation, the
485      * {@code resolve} parameter is ignored; classes are never linked.
486      * </p>
487      *
488      * @return the {@code Class} object.
489      * @param className
490      *            the name of the class to look for.
491      * @param resolve
492      *            Indicates if the class should be resolved after loading. This
493      *            parameter is ignored on the Android reference implementation;
494      *            classes are not resolved.
495      * @throws ClassNotFoundException
496      *             if the class can not be found.
497      */
loadClass(String className, boolean resolve)498     protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
499         Class<?> clazz = findLoadedClass(className);
500 
501         if (clazz == null) {
502             ClassNotFoundException suppressed = null;
503             try {
504                 clazz = parent.loadClass(className, false);
505             } catch (ClassNotFoundException e) {
506                 suppressed = e;
507             }
508 
509             if (clazz == null) {
510                 try {
511                     clazz = findClass(className);
512                 } catch (ClassNotFoundException e) {
513                     e.addSuppressed(suppressed);
514                     throw e;
515                 }
516             }
517         }
518 
519         return clazz;
520     }
521 
522     /**
523      * Forces a class to be linked (initialized). If the class has already been
524      * linked this operation has no effect.
525      * <p>
526      * <strong>Note:</strong> In the Android reference implementation, this
527      * method has no effect.
528      * </p>
529      *
530      * @param clazz
531      *            the class to link.
532      */
resolveClass(Class<?> clazz)533     protected final void resolveClass(Class<?> clazz) {
534         // no-op, doesn't make sense on android.
535     }
536 
537     /**
538      * Finds the URL of the resource with the specified name. This
539      * implementation just returns {@code null}; it should be overridden in
540      * subclasses.
541      *
542      * @param resName
543      *            the name of the resource to find.
544      * @return the {@code URL} object for the requested resource.
545      */
findResource(String resName)546     protected URL findResource(String resName) {
547         return null;
548     }
549 
550     /**
551      * Finds an enumeration of URLs for the resource with the specified name.
552      * This implementation just returns an empty {@code Enumeration}; it should
553      * be overridden in subclasses.
554      *
555      * @param resName
556      *            the name of the resource to find.
557      * @return an enumeration of {@code URL} objects for the requested resource.
558      * @throws IOException
559      *             if an I/O error occurs.
560      */
561     @SuppressWarnings( {
562             "unchecked", "unused"
563     })
findResources(String resName)564     protected Enumeration<URL> findResources(String resName) throws IOException {
565         return Collections.emptyEnumeration();
566     }
567 
568     /**
569      * Returns the absolute path of the native library with the specified name,
570      * or {@code null}. If this method returns {@code null} then the virtual
571      * machine searches the directories specified by the system property
572      * "java.library.path".
573      * <p>
574      * This implementation always returns {@code null}.
575      * </p>
576      *
577      * @param libName
578      *            the name of the library to find.
579      * @return the absolute path of the library.
580      */
findLibrary(String libName)581     protected String findLibrary(String libName) {
582         return null;
583     }
584 
585     /**
586      * Returns the package with the specified name. Package information is
587      * searched in this class loader.
588      *
589      * @param name
590      *            the name of the package to find.
591      * @return the package with the requested name; {@code null} if the package
592      *         can not be found.
593      */
getPackage(String name)594     protected Package getPackage(String name) {
595         synchronized (packages) {
596             return packages.get(name);
597         }
598     }
599 
600     /**
601      * Returns all the packages known to this class loader.
602      *
603      * @return an array with all packages known to this class loader.
604      */
getPackages()605     protected Package[] getPackages() {
606         synchronized (packages) {
607             Collection<Package> col = packages.values();
608             Package[] result = new Package[col.size()];
609             col.toArray(result);
610             return result;
611         }
612     }
613 
614     /**
615      * Defines and returns a new {@code Package} using the specified
616      * information. If {@code sealBase} is {@code null}, the package is left
617      * unsealed. Otherwise, the package is sealed using this URL.
618      *
619      * @param name
620      *            the name of the package.
621      * @param specTitle
622      *            the title of the specification.
623      * @param specVersion
624      *            the version of the specification.
625      * @param specVendor
626      *            the vendor of the specification.
627      * @param implTitle
628      *            the implementation title.
629      * @param implVersion
630      *            the implementation version.
631      * @param implVendor
632      *            the specification vendor.
633      * @param sealBase
634      *            the URL used to seal this package or {@code null} to leave the
635      *            package unsealed.
636      * @return the {@code Package} object that has been created.
637      * @throws IllegalArgumentException
638      *             if a package with the specified name already exists.
639      */
definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)640     protected Package definePackage(String name, String specTitle, String specVersion,
641             String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)
642             throws IllegalArgumentException {
643 
644         synchronized (packages) {
645             if (packages.containsKey(name)) {
646                 throw new IllegalArgumentException("Package " + name + " already defined");
647             }
648 
649             Package newPackage = new Package(name, specTitle, specVersion, specVendor, implTitle,
650                     implVersion, implVendor, sealBase);
651 
652             packages.put(name, newPackage);
653 
654             return newPackage;
655         }
656     }
657 
658     /**
659      * Sets the signers of the specified class. This implementation does
660      * nothing.
661      *
662      * @param c
663      *            the {@code Class} object for which to set the signers.
664      * @param signers
665      *            the signers for {@code c}.
666      */
setSigners(Class<?> c, Object[] signers)667     protected final void setSigners(Class<?> c, Object[] signers) {
668     }
669 
670     /**
671      * Sets the assertion status of the class with the specified name.
672      * <p>
673      * <strong>Note: </strong>This method does nothing in the Android reference
674      * implementation.
675      * </p>
676      *
677      * @param cname
678      *            the name of the class for which to set the assertion status.
679      * @param enable
680      *            the new assertion status.
681      */
setClassAssertionStatus(String cname, boolean enable)682     public void setClassAssertionStatus(String cname, boolean enable) {
683     }
684 
685     /**
686      * Sets the assertion status of the package with the specified name.
687      * <p>
688      * <strong>Note: </strong>This method does nothing in the Android reference
689      * implementation.
690      * </p>
691      *
692      * @param pname
693      *            the name of the package for which to set the assertion status.
694      * @param enable
695      *            the new assertion status.
696      */
setPackageAssertionStatus(String pname, boolean enable)697     public void setPackageAssertionStatus(String pname, boolean enable) {
698     }
699 
700     /**
701      * Sets the default assertion status for this class loader.
702      * <p>
703      * <strong>Note: </strong>This method does nothing in the Android reference
704      * implementation.
705      * </p>
706      *
707      * @param enable
708      *            the new assertion status.
709      */
setDefaultAssertionStatus(boolean enable)710     public void setDefaultAssertionStatus(boolean enable) {
711     }
712 
713     /**
714      * Sets the default assertion status for this class loader to {@code false}
715      * and removes any package default and class assertion status settings.
716      * <p>
717      * <strong>Note:</strong> This method does nothing in the Android reference
718      * implementation.
719      * </p>
720      */
clearAssertionStatus()721     public void clearAssertionStatus() {
722     }
723 }
724 
725 /*
726  * Provides a helper class that combines two existing URL enumerations into one.
727  * It is required for the getResources() methods. Items are fetched from the
728  * first enumeration until it's empty, then from the second one.
729  */
730 class TwoEnumerationsInOne implements Enumeration<URL> {
731 
732     private final Enumeration<URL> first;
733 
734     private final Enumeration<URL> second;
735 
TwoEnumerationsInOne(Enumeration<URL> first, Enumeration<URL> second)736     public TwoEnumerationsInOne(Enumeration<URL> first, Enumeration<URL> second) {
737         this.first = first;
738         this.second = second;
739     }
740 
741     @Override
hasMoreElements()742     public boolean hasMoreElements() {
743         return first.hasMoreElements() || second.hasMoreElements();
744     }
745 
746     @Override
nextElement()747     public URL nextElement() {
748         if (first.hasMoreElements()) {
749             return first.nextElement();
750         } else {
751             return second.nextElement();
752         }
753     }
754 
755 }
756 
757 /**
758  * Provides an explicit representation of the boot class loader. It sits at the
759  * head of the class loader chain and delegates requests to the VM's internal
760  * class loading mechanism.
761  */
762 class BootClassLoader extends ClassLoader {
763 
764     private static BootClassLoader instance;
765 
766     @FindBugsSuppressWarnings("DP_CREATE_CLASSLOADER_INSIDE_DO_PRIVILEGED")
getInstance()767     public static synchronized BootClassLoader getInstance() {
768         if (instance == null) {
769             instance = new BootClassLoader();
770         }
771 
772         return instance;
773     }
774 
BootClassLoader()775     public BootClassLoader() {
776         super(null, true);
777     }
778 
779     @Override
findClass(String name)780     protected Class<?> findClass(String name) throws ClassNotFoundException {
781         return Class.classForName(name, false, null);
782     }
783 
784     @Override
findResource(String name)785     protected URL findResource(String name) {
786         return VMClassLoader.getResource(name);
787     }
788 
789     @SuppressWarnings("unused")
790     @Override
findResources(String resName)791     protected Enumeration<URL> findResources(String resName) throws IOException {
792         return Collections.enumeration(VMClassLoader.getResources(resName));
793     }
794 
795     /**
796      * Returns package information for the given package. Unfortunately, the
797      * Android BootClassLoader doesn't really have this information, and as a
798      * non-secure ClassLoader, it isn't even required to, according to the spec.
799      * Yet, we want to provide it, in order to make all those hopeful callers of
800      * {@code myClass.getPackage().getName()} happy. Thus we construct a Package
801      * object the first time it is being requested and fill most of the fields
802      * with dummy values. The Package object is then put into the ClassLoader's
803      * Package cache, so we see the same one next time. We don't create Package
804      * objects for null arguments or for the default package.
805      * <p>
806      * There a limited chance that we end up with multiple Package objects
807      * representing the same package: It can happen when when a package is
808      * scattered across different JAR files being loaded by different
809      * ClassLoaders. Rather unlikely, and given that this whole thing is more or
810      * less a workaround, probably not worth the effort.
811      */
812     @Override
getPackage(String name)813     protected Package getPackage(String name) {
814         if (name != null && !name.isEmpty()) {
815             synchronized (this) {
816                 Package pack = super.getPackage(name);
817 
818                 if (pack == null) {
819                     pack = definePackage(name, "Unknown", "0.0", "Unknown", "Unknown", "0.0",
820                             "Unknown", null);
821                 }
822 
823                 return pack;
824             }
825         }
826 
827         return null;
828     }
829 
830     @Override
getResource(String resName)831     public URL getResource(String resName) {
832         return findResource(resName);
833     }
834 
835     @Override
loadClass(String className, boolean resolve)836     protected Class<?> loadClass(String className, boolean resolve)
837            throws ClassNotFoundException {
838         Class<?> clazz = findLoadedClass(className);
839 
840         if (clazz == null) {
841             clazz = findClass(className);
842         }
843 
844         return clazz;
845     }
846 
847     @Override
getResources(String resName)848     public Enumeration<URL> getResources(String resName) throws IOException {
849         return findResources(resName);
850     }
851 }
852 
853 /**
854  * TODO Open issues - Missing / empty methods - Signer stuff - Protection
855  * domains - Assertions
856  */
857