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