• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 java.io.IOException;
36 import java.io.InputStream;
37 import java.net.URL;
38 import java.nio.ByteBuffer;
39 import java.security.ProtectionDomain;
40 import java.util.Collection;
41 import java.util.Enumeration;
42 import java.util.Map;
43 import java.util.HashMap;
44 
45 import dalvik.system.PathClassLoader;
46 import dalvik.system.VMStack;
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  *
64  * @since Android 1.0
65  * @see Class
66  */
67 public abstract class ClassLoader {
68 
69     // BEGIN android-note
70     /*
71      * Because of a potential class initialization race between ClassLoader and
72      * java.lang.System, reproducible when using JDWP with "suspend=y", we defer
73      * creation of the system class loader until first use. We use a static
74      * inner class to get synchronization at init time without having to sync on
75      * every access.
76      */
77     // END android-note
78     /**
79      * The 'System' ClassLoader - the one that is responsible for loading
80      * classes from the classpath. It is not equal to the bootstrap class loader -
81      * that one handles the built-in classes.
82      *
83      * @see #getSystemClassLoader()
84      */
85     static private class SystemClassLoader {
86         public static ClassLoader loader = ClassLoader.createSystemClassLoader();
87     }
88 
89     /**
90      * The parent ClassLoader.
91      */
92     private ClassLoader parent;
93 
94     /**
95      * The packages known to the class loader.
96      */
97     private Map<String, Package> packages = new HashMap<String, Package>();
98 
99     /**
100      * Create the system class loader. Note this is NOT the bootstrap class
101      * loader (which is managed by the VM). We use a null value for the parent
102      * to indicate that the bootstrap loader is our parent.
103      */
createSystemClassLoader()104     private static ClassLoader createSystemClassLoader() {
105         String classPath = System.getProperty("java.class.path", ".");
106 
107         // String[] paths = classPath.split(":");
108         // URL[] urls = new URL[paths.length];
109         // for (int i = 0; i < paths.length; i++) {
110         // try {
111         // urls[i] = new URL("file://" + paths[i]);
112         // }
113         // catch (Exception ex) {
114         // ex.printStackTrace();
115         // }
116         // }
117         //
118         // return new java.net.URLClassLoader(urls, null);
119 
120         // TODO Make this a java.net.URLClassLoader once we have those?
121         return new PathClassLoader(classPath, BootClassLoader.getInstance());
122     }
123 
124     /**
125      * Returns the system class loader. This is the parent for new
126      * {@code ClassLoader} instances and is typically the class loader used to
127      * start the application. If a security manager is present and the caller's
128      * class loader is neither {@code null} nor the same as or an ancestor of
129      * the system class loader, then this method calls the security manager's
130      * checkPermission method with a RuntimePermission("getClassLoader")
131      * permission to ensure that it is ok to access the system class loader. If
132      * not, a {@code SecurityException} is thrown.
133      *
134      * @return the system class loader.
135      * @throws SecurityException
136      *             if a security manager exists and it does not allow access to
137      *             the system class loader.
138      * @since Android 1.0
139      */
getSystemClassLoader()140     public static ClassLoader getSystemClassLoader() {
141         SecurityManager smgr = System.getSecurityManager();
142         if (smgr != null) {
143             ClassLoader caller = VMStack.getCallingClassLoader();
144             if (caller != null && !caller.isAncestorOf(SystemClassLoader.loader)) {
145                 smgr.checkPermission(new RuntimePermission("getClassLoader"));
146             }
147         }
148 
149         return SystemClassLoader.loader;
150     }
151 
152     /**
153      * Finds the URL of the resource with the specified name. The system class
154      * loader's resource lookup algorithm is used to find the resource.
155      *
156      * @return the {@code URL} object for the requested resource or {@code null}
157      *         if the resource can not be found.
158      * @param resName
159      *            the name of the resource to find.
160      * @see Class#getResource
161      * @since Android 1.0
162      */
getSystemResource(String resName)163     public static URL getSystemResource(String resName) {
164         return SystemClassLoader.loader.getResource(resName);
165     }
166 
167     /**
168      * Returns an enumeration of URLs for the resource with the specified name.
169      * The system class loader's resource lookup algorithm is used to find the
170      * resource.
171      *
172      * @return an enumeration of {@code URL} objects containing the requested
173      *         resources.
174      * @param resName
175      *            the name of the resource to find.
176      * @throws IOException
177      *             if an I/O error occurs.
178      * @since Android 1.0
179      */
getSystemResources(String resName)180     public static Enumeration<URL> getSystemResources(String resName) throws IOException {
181         return SystemClassLoader.loader.getResources(resName);
182     }
183 
184     /**
185      * Returns a stream for the resource with the specified name. The system
186      * class loader's resource lookup algorithm is used to find the resource.
187      * Basically, the contents of the java.class.path are searched in order,
188      * looking for a path which matches the specified resource.
189      *
190      * @return a stream for the resource or {@code null}.
191      * @param resName
192      *            the name of the resource to find.
193      * @see Class#getResourceAsStream
194      * @since Android 1.0
195      */
getSystemResourceAsStream(String resName)196     public static InputStream getSystemResourceAsStream(String resName) {
197         return SystemClassLoader.loader.getResourceAsStream(resName);
198     }
199 
200     /**
201      * Constructs a new instance of this class with the system class loader as
202      * its parent.
203      *
204      * @throws SecurityException
205      *             if a security manager exists and it does not allow the
206      *             creation of a new {@code ClassLoader}.
207      * @since Android 1.0
208      */
ClassLoader()209     protected ClassLoader() {
210         this(getSystemClassLoader(), false);
211     }
212 
213     /**
214      * Constructs a new instance of this class with the specified class loader
215      * as its parent.
216      *
217      * @param parentLoader
218      *            The {@code ClassLoader} to use as the new class loader's
219      *            parent.
220      * @throws SecurityException
221      *             if a security manager exists and it does not allow the
222      *             creation of new a new {@code ClassLoader}.
223      * @since Android 1.0
224      */
ClassLoader(ClassLoader parentLoader)225     protected ClassLoader(ClassLoader parentLoader) {
226         this(parentLoader, false);
227     }
228 
229     /*
230      * constructor for the BootClassLoader which needs parent to be null.
231      */
ClassLoader(ClassLoader parentLoader, boolean nullAllowed)232     ClassLoader(ClassLoader parentLoader, boolean nullAllowed) {
233         SecurityManager smgr = System.getSecurityManager();
234         if (smgr != null) {
235             smgr.checkCreateClassLoader();
236         }
237 
238         if (parentLoader == null && !nullAllowed) {
239             throw new NullPointerException(
240                     "Parent ClassLoader may not be null");
241         }
242 
243         parent = parentLoader;
244     }
245 
246     /**
247      * Constructs a new class from an array of bytes containing a class
248      * definition in class file format.
249      *
250      * @param classRep
251      *            the memory image of a class file.
252      * @param offset
253      *            the offset into {@code classRep}.
254      * @param length
255      *            the length of the class file.
256      * @return the {@code Class} object created from the specified subset of
257      *         data in {@code classRep}.
258      * @throws ClassFormatError
259      *             if {@code classRep} does not contain a valid class.
260      * @throws IndexOutOfBoundsException
261      *             if {@code offset < 0}, {@code length < 0} or if
262      *             {@code offset + length} is greater than the length of
263      *             {@code classRep}.
264      * @deprecated Use {@link #defineClass(String, byte[], int, int)}
265      * @since Android 1.0
266      */
267     @Deprecated
defineClass(byte[] classRep, int offset, int length)268     protected final Class<?> defineClass(byte[] classRep, int offset, int length)
269             throws ClassFormatError {
270 
271         return VMClassLoader.defineClass(this, classRep, offset, length, null);
272     }
273 
274     /**
275      * Constructs a new class from an array of bytes containing a class
276      * definition in class file format.
277      *
278      * @param className
279      *            the expected name of the new class, may be {@code null} if not
280      *            known.
281      * @param classRep
282      *            the memory image of a class file.
283      * @param offset
284      *            the offset into {@code classRep}.
285      * @param length
286      *            the length of the class file.
287      * @return the {@code Class} object created from the specified subset of
288      *         data in {@code classRep}.
289      * @throws ClassFormatError
290      *             if {@code classRep} does not contain a valid class.
291      * @throws IndexOutOfBoundsException
292      *             if {@code offset < 0}, {@code length < 0} or if
293      *             {@code offset + length} is greater than the length of
294      *             {@code classRep}.
295      * @since Android 1.0
296      */
defineClass(String className, byte[] classRep, int offset, int length)297     protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length)
298             throws ClassFormatError {
299 
300         // TODO Define a default ProtectionDomain on first use
301         return defineClass(className, classRep, offset, length, null);
302     }
303 
304     /**
305      * Constructs a new class from an array of bytes containing a class
306      * definition in class file format and assigns the specified protection
307      * domain to the new class. If the provided protection domain is
308      * {@code null} then a default protection domain is assigned to the class.
309      *
310      * @param className
311      *            the expected name of the new class, may be {@code null} if not
312      *            known.
313      * @param classRep
314      *            the memory image of a class file.
315      * @param offset
316      *            the offset into {@code classRep}.
317      * @param length
318      *            the length of the class file.
319      * @param protectionDomain
320      *            the protection domain to assign to the loaded class, may be
321      *            {@code null}.
322      * @return the {@code Class} object created from the specified subset of
323      *         data in {@code classRep}.
324      * @throws ClassFormatError
325      *             if {@code classRep} does not contain a valid class.
326      * @throws IndexOutOfBoundsException
327      *             if {@code offset < 0}, {@code length < 0} or if
328      *             {@code offset + length} is greater than the length of
329      *             {@code classRep}.
330      * @throws NoClassDefFoundError
331      *             if {@code className} is not equal to the name of the class
332      *             contained in {@code classRep}.
333      * @since Android 1.0
334      */
defineClass(String className, byte[] classRep, int offset, int length, ProtectionDomain protectionDomain)335     protected final Class<?> defineClass(String className, byte[] classRep, int offset, int length,
336             ProtectionDomain protectionDomain) throws java.lang.ClassFormatError {
337 
338         return VMClassLoader.defineClass(this, className, classRep, offset, length,
339                 protectionDomain);
340     }
341 
342     /**
343      * Defines a new class with the specified name, byte code from the byte
344      * buffer and the optional protection domain. If the provided protection
345      * domain is {@code null} then a default protection domain is assigned to
346      * the class.
347      *
348      * @param name
349      *            the expected name of the new class, may be {@code null} if not
350      *            known.
351      * @param b
352      *            the byte buffer containing the byte code of the new class.
353      * @param protectionDomain
354      *            the protection domain to assign to the loaded class, may be
355      *            {@code null}.
356      * @return the {@code Class} object created from the data in {@code b}.
357      * @throws ClassFormatError
358      *             if {@code b} does not contain a valid class.
359      * @throws NoClassDefFoundError
360      *             if {@code className} is not equal to the name of the class
361      *             contained in {@code b}.
362      * @since Android 1.0
363      */
defineClass(String name, ByteBuffer b, ProtectionDomain protectionDomain)364     protected final Class<?> defineClass(String name, ByteBuffer b,
365             ProtectionDomain protectionDomain) throws ClassFormatError {
366 
367         byte[] temp = new byte[b.remaining()];
368         b.get(temp);
369         return defineClass(name, temp, 0, temp.length, protectionDomain);
370     }
371 
372     /**
373      * Overridden by subclasses, throws a {@code ClassNotFoundException} by
374      * default. This method is called by {@code loadClass} after the parent
375      * {@code ClassLoader} has failed to find a loaded class of the same name.
376      *
377      * @param className
378      *            the name of the class to look for.
379      * @return the {@code Class} object that is found.
380      * @throws ClassNotFoundException
381      *             if the class cannot be found.
382      * @since Android 1.0
383      */
findClass(String className)384     protected Class<?> findClass(String className) throws ClassNotFoundException {
385         throw new ClassNotFoundException(className);
386     }
387 
388     /**
389      * Returns the class with the specified name if it has already been loaded
390      * by the virtual machine or {@code null} if it has not yet been loaded.
391      *
392      * @param className
393      *            the name of the class to look for.
394      * @return the {@code Class} object or {@code null} if the requested class
395      *         has not been loaded.
396      * @since Android 1.0
397      */
findLoadedClass(String className)398     protected final Class<?> findLoadedClass(String className) {
399         ClassLoader loader;
400         if (this == BootClassLoader.getInstance())
401             loader = null;
402         else
403             loader = this;
404         return VMClassLoader.findLoadedClass(loader, className);
405     }
406 
407     /**
408      * Finds the class with the specified name, loading it using the system
409      * class loader if necessary.
410      *
411      * @param className
412      *            the name of the class to look for.
413      * @return the {@code Class} object with the requested {@code className}.
414      * @throws ClassNotFoundException
415      *             if the class can not be found.
416      * @since Android 1.0
417      */
findSystemClass(String className)418     protected final Class<?> findSystemClass(String className) throws ClassNotFoundException {
419         return Class.forName(className, false, getSystemClassLoader());
420     }
421 
422     /**
423      * Returns this class loader's parent.
424      *
425      * @return this class loader's parent or {@code null}.
426      * @throws SecurityException
427      *             if a security manager exists and it does not allow to
428      *             retrieve the parent class loader.
429      * @since Android 1.0
430      */
getParent()431     public final ClassLoader getParent() {
432         SecurityManager smgr = System.getSecurityManager();
433         if (smgr != null) {
434             smgr.checkPermission(new RuntimePermission("getClassLoader"));
435         }
436 
437         return parent;
438     }
439 
440     /**
441      * Returns the URL of the resource with the specified name. This
442      * implementation first tries to use the parent class loader to find the
443      * resource; if this fails then {@link #findResource(String)} is called to
444      * find the requested resource.
445      *
446      * @param resName
447      *            the name of the resource to find.
448      * @return the {@code URL} object for the requested resource or {@code null}
449      *         if either the resource can not be found or a security manager
450      *         does not allow to access the resource.
451      * @see Class#getResource
452      * @since Android 1.0
453      */
getResource(String resName)454     public URL getResource(String resName) {
455         URL resource = null;
456 
457         resource = parent.getResource(resName);
458 
459         if (resource == null) {
460             resource = findResource(resName);
461         }
462 
463         return resource;
464     }
465 
466     /**
467      * Returns an enumeration of URLs for the resource with the specified name.
468      * This implementation first uses this class loader's parent to find the
469      * resource, then it calls {@link #findResources(String)} to get additional
470      * URLs. The returned enumeration contains the {@code URL} objects of both
471      * find operations.
472      *
473      * @return an enumeration of {@code URL} objects for the requested resource.
474      * @param resName
475      *            the name of the resource to find.
476      * @throws IOException
477      *             if an I/O error occurs.
478      * @since Android 1.0
479      */
480     @SuppressWarnings("unchecked")
getResources(String resName)481     public Enumeration<URL> getResources(String resName) throws IOException {
482 
483         Enumeration first = parent.getResources(resName);
484         Enumeration second = findResources(resName);
485 
486         return new TwoEnumerationsInOne(first, second);
487     }
488 
489     /**
490      * Returns a stream for the resource with the specified name. See
491      * {@link #getResource(String)} for a description of the lookup algorithm
492      * used to find the resource.
493      *
494      * @return a stream for the resource or {@code null} if either the resource
495      *         can not be found or a security manager does not allow to access
496      *         the resource.
497      * @param resName
498      *            the name of the resource to find.
499      * @see Class#getResourceAsStream
500      * @since Android 1.0
501      */
getResourceAsStream(String resName)502     public InputStream getResourceAsStream(String resName) {
503         try {
504             URL url = getResource(resName);
505             if (url != null) {
506                 return url.openStream();
507             }
508         } catch (IOException ex) {
509             // Don't want to see the exception.
510         }
511 
512         return null;
513     }
514 
515     /**
516      * Loads the class with the specified name. Invoking this method is
517      * equivalent to calling {@code loadClass(className, false)}.
518      * <p>
519      * <strong>Note:</strong> In the Android reference implementation, the
520      * second parameter of {@link #loadClass(String, boolean)} is ignored
521      * anyway.
522      * </p>
523      *
524      * @return the {@code Class} object.
525      * @param className
526      *            the name of the class to look for.
527      * @throws ClassNotFoundException
528      *             if the class can not be found.
529      * @since Android 1.0
530      */
loadClass(String className)531     public Class<?> loadClass(String className) throws ClassNotFoundException {
532         return loadClass(className, false);
533     }
534 
535     /**
536      * Loads the class with the specified name, optionally linking it after
537      * loading. The following steps are performed:
538      * <ol>
539      * <li> Call {@link #findLoadedClass(String)} to determine if the requested
540      * class has already been loaded.</li>
541      * <li>If the class has not yet been loaded: Invoke this method on the
542      * parent class loader.</li>
543      * <li>If the class has still not been loaded: Call
544      * {@link #findClass(String)} to find the class.</li>
545      * </ol>
546      * <p>
547      * <strong>Note:</strong> In the Android reference implementation, the
548      * {@code resolve} parameter is ignored; classes are never linked.
549      * </p>
550      *
551      * @return the {@code Class} object.
552      * @param className
553      *            the name of the class to look for.
554      * @param resolve
555      *            Indicates if the class should be resolved after loading. This
556      *            parameter is ignored on the Android reference implementation;
557      *            classes are not resolved.
558      * @throws ClassNotFoundException
559      *             if the class can not be found.
560      * @since Android 1.0
561      */
loadClass(String className, boolean resolve)562     protected Class<?> loadClass(String className, boolean resolve) throws ClassNotFoundException {
563         Class<?> clazz = findLoadedClass(className);
564 
565         if (clazz == null) {
566             try {
567                 clazz = parent.loadClass(className, false);
568             } catch (ClassNotFoundException e) {
569                 // Don't want to see this.
570             }
571 
572             if (clazz == null) {
573                 clazz = findClass(className);
574             }
575         }
576 
577         return clazz;
578     }
579 
580     /**
581      * Forces a class to be linked (initialized). If the class has already been
582      * linked this operation has no effect.
583      * <p>
584      * <strong>Note:</strong> In the Android reference implementation, this
585      * method has no effect.
586      * </p>
587      *
588      * @param clazz
589      *            the class to link.
590      * @since Android 1.0
591      */
resolveClass(Class<?> clazz)592     protected final void resolveClass(Class<?> clazz) {
593         // no-op, doesn't make sense on android.
594     }
595 
596     /**
597      * Indicates whether this class loader is the system class loader. This
598      * method must be provided by the virtual machine vendor, as it is used by
599      * other provided class implementations in this package. A sample
600      * implementation of this method is provided by the reference
601      * implementation. This method is used by
602      * SecurityManager.classLoaderDepth(), currentClassLoader() and
603      * currentLoadedClass(). Returns true if the receiver is a system class
604      * loader.
605      * <p>
606      * Note that this method has package visibility only. It is defined here to
607      * avoid the security manager check in getSystemClassLoader, which would be
608      * required to implement this method anywhere else.
609      * </p>
610      *
611      * @return {@code true} if the receiver is a system class loader
612      * @see Class#getClassLoaderImpl()
613      */
isSystemClassLoader()614     final boolean isSystemClassLoader() {
615         return false;
616     }
617 
618     /**
619      * <p>
620      * Returns true if the receiver is ancestor of another class loader. It also
621      * returns true if the two class loader are equal.
622      * </p>
623      * <p>
624      * Note that this method has package visibility only. It is defined here to
625      * avoid the security manager check in getParent, which would be required to
626      * implement this method anywhere else. The method is also required in other
627      * places where class loaders are accesses.
628      * </p>
629      *
630      * @param child
631      *            A child candidate
632      * @return {@code true} if the receiver is ancestor of, or equal to,
633      *         the parameter
634      */
isAncestorOf(ClassLoader child)635     final boolean isAncestorOf(ClassLoader child) {
636         for (ClassLoader current = child; current != null;
637                 current = current.parent) {
638             if (current == this) {
639                 return true;
640             }
641         }
642         return false;
643     }
644 
645     /**
646      * Finds the URL of the resource with the specified name. This
647      * implementation just returns {@code null}; it should be overridden in
648      * subclasses.
649      *
650      * @param resName
651      *            the name of the resource to find.
652      * @return the {@code URL} object for the requested resource.
653      * @since Android 1.0
654      */
findResource(String resName)655     protected URL findResource(String resName) {
656         return null;
657     }
658 
659     /**
660      * Finds an enumeration of URLs for the resource with the specified name.
661      * This implementation just returns an empty {@code Enumeration}; it should
662      * be overridden in subclasses.
663      *
664      * @param resName
665      *            the name of the resource to find.
666      * @return an enumeration of {@code URL} objects for the requested resource.
667      * @throws IOException
668      *             if an I/O error occurs.
669      * @since Android 1.0
670      */
671     @SuppressWarnings( {
672             "unchecked", "unused"
673     })
findResources(String resName)674     protected Enumeration<URL> findResources(String resName) throws IOException {
675         return EmptyEnumeration.getInstance();
676     }
677 
678     /**
679      * Returns the absolute path of the native library with the specified name,
680      * or {@code null}. If this method returns {@code null} then the virtual
681      * machine searches the directories specified by the system property
682      * "java.library.path".
683      * <p>
684      * This implementation always returns {@code null}.
685      * </p>
686      *
687      * @param libName
688      *            the name of the library to find.
689      * @return the absolute path of the library.
690      * @since Android 1.0
691      */
findLibrary(String libName)692     protected String findLibrary(String libName) {
693         return null;
694     }
695 
696     /**
697      * Returns the package with the specified name. Package information is
698      * searched in this class loader.
699      *
700      * @param name
701      *            the name of the package to find.
702      * @return the package with the requested name; {@code null} if the package
703      *         can not be found.
704      * @since Android 1.0
705      */
getPackage(String name)706     protected Package getPackage(String name) {
707         synchronized (packages) {
708             Package p = packages.get(name);
709             return p;
710         }
711     }
712 
713     /**
714      * Gets the package with the specified name, searching it in the specified
715      * class loader.
716      *
717      * @param loader
718      *            the class loader to search the package in.
719      * @param name
720      *            the name of the package to find.
721      * @return the package with the requested name; {@code null} if the package
722      *         can not be found.
723      * @since Android 1.0
724      */
getPackage(ClassLoader loader, String name)725     static Package getPackage(ClassLoader loader, String name) {
726         return loader.getPackage(name);
727     }
728 
729     /**
730      * Returns all the packages known to this class loader.
731      *
732      * @return an array with all packages known to this class loader.
733      * @since Android 1.0
734      */
getPackages()735     protected Package[] getPackages() {
736         synchronized (packages) {
737             Collection<Package> col = packages.values();
738             Package[] result = new Package[col.size()];
739             col.toArray(result);
740             return result;
741         }
742     }
743 
744     /**
745      * Defines and returns a new {@code Package} using the specified
746      * information. If {@code sealBase} is {@code null}, the package is left
747      * unsealed. Otherwise, the package is sealed using this URL.
748      *
749      * @param name
750      *            the name of the package.
751      * @param specTitle
752      *            the title of the specification.
753      * @param specVersion
754      *            the version of the specification.
755      * @param specVendor
756      *            the vendor of the specification.
757      * @param implTitle
758      *            the implementation title.
759      * @param implVersion
760      *            the implementation version.
761      * @param implVendor
762      *            the specification vendor.
763      * @param sealBase
764      *            the URL used to seal this package or {@code null} to leave the
765      *            package unsealed.
766      * @return the {@code Package} object that has been created.
767      * @throws IllegalArgumentException
768      *             if a package with the specified name already exists.
769      * @since Android 1.0
770      */
definePackage(String name, String specTitle, String specVersion, String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)771     protected Package definePackage(String name, String specTitle, String specVersion,
772             String specVendor, String implTitle, String implVersion, String implVendor, URL sealBase)
773             throws IllegalArgumentException {
774 
775         synchronized (packages) {
776             if (packages.containsKey(name)) {
777                 throw new IllegalArgumentException("Package " + name + " already defined");
778             }
779 
780             Package newPackage = new Package(name, specTitle, specVersion, specVendor, implTitle,
781                     implVersion, implVendor, sealBase);
782 
783             packages.put(name, newPackage);
784 
785             return newPackage;
786         }
787     }
788 
789     /**
790      * Gets the signers of the specified class. This implementation returns
791      * {@code null}.
792      *
793      * @param c
794      *            the {@code Class} object for which to get the signers.
795      * @return signers the signers of {@code c}.
796      * @since Android 1.0
797      */
getSigners(Class<?> c)798     final Object[] getSigners(Class<?> c) {
799         return null;
800     }
801 
802     /**
803      * Sets the signers of the specified class. This implementation does
804      * nothing.
805      *
806      * @param c
807      *            the {@code Class} object for which to set the signers.
808      * @param signers
809      *            the signers for {@code c}.
810      * @since Android 1.0
811      */
setSigners(Class<?> c, Object[] signers)812     protected final void setSigners(Class<?> c, Object[] signers) {
813         return;
814     }
815 
816     /**
817      * <p>
818      * This must be provided by the VM vendor. It is used by
819      * SecurityManager.checkMemberAccess() with depth = 3. Note that
820      * checkMemberAccess() assumes the following stack when called:<br>
821      * </p>
822      *
823      * <pre>
824      *          &lt; user code &amp;gt; &lt;- want this class
825      *          Class.getDeclared*();
826      *          Class.checkMemberAccess();
827      *          SecurityManager.checkMemberAccess(); &lt;- current frame
828      * </pre>
829      *
830      * <p>
831      * Returns the ClassLoader of the method (including natives) at the
832      * specified depth on the stack of the calling thread. Frames representing
833      * the VM implementation of java.lang.reflect are not included in the list.
834      * </p>
835      * Notes:
836      * <ul>
837      * <li>This method operates on the defining classes of methods on stack.
838      * NOT the classes of receivers.</li>
839      * <li>The item at depth zero is the caller of this method</li>
840      * </ul>
841      *
842      * @param depth
843      *            the stack depth of the requested ClassLoader
844      * @return the ClassLoader at the specified depth
845      */
getStackClassLoader(int depth)846     static final ClassLoader getStackClassLoader(int depth) {
847         Class<?>[] stack = VMStack.getClasses(depth + 1, false);
848         if(stack.length < depth + 1) {
849             return null;
850         }
851         return stack[depth].getClassLoader();
852     }
853 
854     /**
855      * This method must be provided by the VM vendor, as it is called by
856      * java.lang.System.loadLibrary(). System.loadLibrary() cannot call
857      * Runtime.loadLibrary() because this method loads the library using the
858      * ClassLoader of the calling method. Loads and links the library specified
859      * by the argument.
860      *
861      * @param libName
862      *            the name of the library to load
863      * @param loader
864      *            the classloader in which to load the library
865      * @throws UnsatisfiedLinkError
866      *             if the library could not be loaded
867      * @throws SecurityException
868      *             if the library was not allowed to be loaded
869      * <p>
870      * <strong>Note: </strong>This method does nothing in the Android reference
871      * implementation.
872      * </p>
873      */
loadLibraryWithClassLoader(String libName, ClassLoader loader)874     static void loadLibraryWithClassLoader(String libName, ClassLoader loader) {
875         return;
876     }
877 
878     /**
879      * This method must be provided by the VM vendor, as it is called by
880      * java.lang.System.load(). System.load() cannot call Runtime.load() because
881      * the library is loaded using the ClassLoader of the calling method. Loads
882      * and links the library specified by the argument. No security check is
883      * done.
884      * <p>
885      * <strong>Note: </strong>This method does nothing in the Android reference
886      * implementation.
887      * </p>
888      *
889      * @param libName
890      *            the name of the library to load
891      * @param loader
892      *            the classloader in which to load the library
893      * @param libraryPath
894      *            the library path to search, or null
895      * @throws UnsatisfiedLinkError
896      *             if the library could not be loaded
897      */
loadLibraryWithPath(String libName, ClassLoader loader, String libraryPath)898     static void loadLibraryWithPath(String libName, ClassLoader loader, String libraryPath) {
899         return;
900     }
901 
902     /**
903      * Sets the assertion status of the class with the specified name.
904      * <p>
905      * <strong>Note: </strong>This method does nothing in the Android reference
906      * implementation.
907      * </p>
908      *
909      * @param cname
910      *            the name of the class for which to set the assertion status.
911      * @param enable
912      *            the new assertion status.
913      * @since Android 1.0
914      */
setClassAssertionStatus(String cname, boolean enable)915     public void setClassAssertionStatus(String cname, boolean enable) {
916         return;
917     }
918 
919     /**
920      * Sets the assertion status of the package with the specified name.
921      * <p>
922      * <strong>Note: </strong>This method does nothing in the Android reference
923      * implementation.
924      * </p>
925      *
926      * @param pname
927      *            the name of the package for which to set the assertion status.
928      * @param enable
929      *            the new assertion status.
930      * @since Android 1.0
931      */
setPackageAssertionStatus(String pname, boolean enable)932     public void setPackageAssertionStatus(String pname, boolean enable) {
933         return;
934     }
935 
936     /**
937      * Sets the default assertion status for this class loader.
938      * <p>
939      * <strong>Note: </strong>This method does nothing in the Android reference
940      * implementation.
941      * </p>
942      *
943      * @param enable
944      *            the new assertion status.
945      * @since Android 1.0
946      */
setDefaultAssertionStatus(boolean enable)947     public void setDefaultAssertionStatus(boolean enable) {
948         return;
949     }
950 
951     /**
952      * Sets the default assertion status for this class loader to {@code false}
953      * and removes any package default and class assertion status settings.
954      * <p>
955      * <strong>Note:</strong> This method does nothing in the Android reference
956      * implementation.
957      * </p>
958      *
959      * @since Android 1.0
960      */
clearAssertionStatus()961     public void clearAssertionStatus() {
962         return;
963     }
964 
965     /**
966      * Returns the assertion status of the named class Returns the assertion
967      * status of the class or nested class if it has been set. Otherwise returns
968      * the assertion status of its package or superpackage if that has been set.
969      * Otherwise returns the default assertion status. Returns 1 for enabled and
970      * 0 for disabled.
971      *
972      * @return the assertion status.
973      * @param cname
974      *            the name of class.
975      */
getClassAssertionStatus(String cname)976     boolean getClassAssertionStatus(String cname) {
977         return false;
978     }
979 
980     /**
981      * Returns the assertion status of the named package Returns the assertion
982      * status of the named package or superpackage if that has been set.
983      * Otherwise returns the default assertion status. Returns 1 for enabled and
984      * 0 for disabled.
985      *
986      * @return the assertion status.
987      * @param pname
988      *            the name of package.
989      */
getPackageAssertionStatus(String pname)990     boolean getPackageAssertionStatus(String pname) {
991         return false;
992     }
993 
994     /**
995      * Returns the default assertion status
996      *
997      * @return the default assertion status.
998      */
getDefaultAssertionStatus()999     boolean getDefaultAssertionStatus() {
1000         return false;
1001     }
1002 }
1003 
1004 /*
1005  * Provides a helper class that combines two existing URL enumerations into one.
1006  * It is required for the getResources() methods. Items are fetched from the
1007  * first enumeration until it's empty, then from the second one.
1008  */
1009 class TwoEnumerationsInOne implements Enumeration<URL> {
1010 
1011     private Enumeration<URL> first;
1012 
1013     private Enumeration<URL> second;
1014 
TwoEnumerationsInOne(Enumeration<URL> first, Enumeration<URL> second)1015     public TwoEnumerationsInOne(Enumeration<URL> first, Enumeration<URL> second) {
1016         this.first = first;
1017         this.second = second;
1018     }
1019 
hasMoreElements()1020     public boolean hasMoreElements() {
1021         return first.hasMoreElements() || second.hasMoreElements();
1022     }
1023 
nextElement()1024     public URL nextElement() {
1025         if (first.hasMoreElements()) {
1026             return first.nextElement();
1027         } else {
1028             return second.nextElement();
1029         }
1030     }
1031 
1032 }
1033 
1034 /**
1035  * Provides an explicit representation of the boot class loader. It sits at the
1036  * head of the class loader chain and delegates requests to the VM's internal
1037  * class loading mechanism.
1038  */
1039 class BootClassLoader extends ClassLoader {
1040 
1041     static BootClassLoader instance;
1042 
getInstance()1043     public static BootClassLoader getInstance() {
1044         if (instance == null) {
1045             instance = new BootClassLoader();
1046         }
1047 
1048         return instance;
1049     }
1050 
BootClassLoader()1051     public BootClassLoader() {
1052         super(null, true);
1053     }
1054 
1055     @Override
findClass(String name)1056     protected Class<?> findClass(String name) throws ClassNotFoundException {
1057         return VMClassLoader.loadClass(name, false);
1058     }
1059 
1060     @Override
findResource(String name)1061     protected URL findResource(String name) {
1062         return VMClassLoader.getResource(name);
1063     }
1064 
1065     @SuppressWarnings("unused")
1066     @Override
findResources(String resName)1067     protected Enumeration<URL> findResources(String resName) throws IOException {
1068         Enumeration<URL> result = VMClassLoader.getResources(resName);
1069 
1070         // VMClassLoader doesn't keep the contract for getResources()
1071         if (result == null) {
1072             result = EmptyEnumeration.getInstance();
1073         }
1074 
1075         return result;
1076     }
1077 
1078     /**
1079      * Returns package information for the given package. Unfortunately, the
1080      * Android BootClassLoader doesn't really have this information, and as a
1081      * non-secure ClassLoader, it isn't even required to, according to the spec.
1082      * Yet, we want to provide it, in order to make all those hopeful callers of
1083      * {@code myClass.getPackage().getName()} happy. Thus we construct a Package
1084      * object the first time it is being requested and fill most of the fields
1085      * with dummy values. The Package object is then put into the ClassLoader's
1086      * Package cache, so we see the same one next time. We don't create Package
1087      * objects for null arguments or for the default package.
1088      * <p>
1089      * There a limited chance that we end up with multiple Package objects
1090      * representing the same package: It can happen when when a package is
1091      * scattered across different JAR files being loaded by different
1092      * ClassLoaders. Rather unlikely, and given that this whole thing is more or
1093      * less a workaround, probably not worth the effort.
1094      */
1095     @Override
getPackage(String name)1096     protected Package getPackage(String name) {
1097         if (name != null && !"".equals(name)) {
1098             synchronized (this) {
1099                 Package pack = super.getPackage(name);
1100 
1101                 if (pack == null) {
1102                     pack = definePackage(name, "Unknown", "0.0", "Unknown", "Unknown", "0.0",
1103                             "Unknown", null);
1104                 }
1105 
1106                 return pack;
1107             }
1108         }
1109 
1110         return null;
1111     }
1112 
1113     @Override
getResource(String resName)1114     public URL getResource(String resName) {
1115         return findResource(resName);
1116     }
1117 
1118     @Override
loadClass(String className, boolean resolve)1119     protected Class<?> loadClass(String className, boolean resolve)
1120            throws ClassNotFoundException {
1121         Class<?> clazz = findLoadedClass(className);
1122 
1123         if (clazz == null) {
1124             clazz = findClass(className);
1125         }
1126 
1127         return clazz;
1128     }
1129 
1130     @Override
getResources(String resName)1131     public Enumeration<URL> getResources(String resName) throws IOException {
1132         return findResources(resName);
1133     }
1134 }
1135 
1136 /**
1137  * TODO Open issues - Missing / empty methods - Signer stuff - Protection
1138  * domains - Assertions
1139  */
1140