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