Main.java revision fbb80d7f726e551161fccbf0e347624459aefedf
1fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes/*
2fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Copyright (C) 2010 The Android Open Source Project
3fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes *
4fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Licensed under the Apache License, Version 2.0 (the "License");
5fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * you may not use this file except in compliance with the License.
6fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * You may obtain a copy of the License at
7fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes *
8fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes *      http://www.apache.org/licenses/LICENSE-2.0
9fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes *
10fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Unless required by applicable law or agreed to in writing, software
11fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * distributed under the License is distributed on an "AS IS" BASIS,
12fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * See the License for the specific language governing permissions and
14fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * limitations under the License.
15fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */
16fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
17fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayesimport java.lang.reflect.Constructor;
18fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayesimport java.lang.reflect.Method;
19fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayesimport java.lang.reflect.InvocationTargetException;
20fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
21fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes/**
22fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes * Class loader test.
23fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes */
24fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayespublic class Main {
25fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
26fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes    /**
27fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * A class loader which loads classes from the dex file
28fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * "test.jar". However, it will return null when asked to load the
29fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * class InaccessibleSuper.
30fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     *
31fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * When testing code calls BrokenDexLoader's findBrokenClass(),
32fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * a BrokenDexLoader will be the defining loader for the class
33fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * Inaccessible.  The VM will call the defining loader for
34fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * "InaccessibleSuper", which will return null, which the VM
35fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * should be able to deal with gracefully.
36fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     *
37fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * Note that this depends heavily on the Dalvik test harness.
38fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     */
39fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes    static class BrokenDexLoader extends ClassLoader {
40fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
41fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        /** We return null when asked to load InaccessibleSuper. */
42fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        private static class InaccessibleSuper {}
43fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        private static class Inaccessible extends InaccessibleSuper {}
44fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
45fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        private static final String SUPERCLASS_NAME =
46fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                "Main$BrokenDexLoader$InaccessibleSuper";
47fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        private static final String CLASS_NAME =
48fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                "Main$BrokenDexLoader$Inaccessible";
49fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
50fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        private static final String DEX_FILE = "test.jar";
51fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
52fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        public BrokenDexLoader(ClassLoader parent) {
53fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            super(parent);
54fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        }
55fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
56fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        /**
57fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         * Finds the class with the specified binary name, from DEX_FILE.
58fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         *
59fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         * If we don't find a match, we throw an exception.
60fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         */
61fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        private Class<?> findDexClass(String name) throws ClassNotFoundException
62fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        {
63fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            Class mDexClass;
64fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            Object mDexFile;
65fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
66fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            /*
67fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes             * Find the DexFile class, and construct a DexFile object
68fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes             * through reflection.
69fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes             */
70fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
71fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            mDexClass = ClassLoader.getSystemClassLoader().
72fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                    loadClass("dalvik/system/DexFile");
73fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
74fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            Constructor ctor;
75fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            try {
76fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                ctor = mDexClass.getConstructor(new Class[] {String.class});
77fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            } catch (NoSuchMethodException nsme) {
78fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                throw new ClassNotFoundException("getConstructor failed",
79fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                                                 nsme);
80fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            }
81fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
82fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            try {
83fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                mDexFile = ctor.newInstance(DEX_FILE);
84fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            } catch (InstantiationException ie) {
85fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                throw new ClassNotFoundException("newInstance failed", ie);
86fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            } catch (IllegalAccessException iae) {
87fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                throw new ClassNotFoundException("newInstance failed", iae);
88fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            } catch (InvocationTargetException ite) {
89fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                throw new ClassNotFoundException("newInstance failed", ite);
90fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            }
91fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
92fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            /*
93fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes             * Call DexFile.loadClass(String, ClassLoader).
94fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes             */
95fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            Method meth;
96fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
97fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            try {
98fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                meth = mDexClass.getMethod("loadClass",
99fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                           new Class[] { String.class, ClassLoader.class });
100fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            } catch (NoSuchMethodException nsme) {
101fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                throw new ClassNotFoundException("getMethod failed", nsme);
102fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            }
103fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
104fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            try {
105fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                meth.invoke(mDexFile, name, this);
106fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            } catch (IllegalAccessException iae) {
107fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                throw new ClassNotFoundException("loadClass failed", iae);
108fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            } catch (InvocationTargetException ite) {
109fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                throw new ClassNotFoundException("loadClass failed",
110fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                                                 ite.getCause());
111fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            }
112fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
113fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            return null;
114fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        }
115fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
116fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        /**
117fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         * Load a class.
118fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         *
119fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         * Return null if the class's name is SUPERCLASS_NAME;
120fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         * otherwise invoke the super's loadClass method.
121fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         */
122fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        public Class<?> loadClass(String name, boolean resolve)
123fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                throws ClassNotFoundException
124fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        {
125fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            if (SUPERCLASS_NAME.equals(name)) {
126fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                return null;
127fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            }
128fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
129fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            return super.loadClass(name, resolve);
130fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        }
131fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
132fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        /**
133fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         * Attempt to find the class with the superclass we refuse to
134fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         * load.
135fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         */
136fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        public void findBrokenClass() throws ClassNotFoundException
137fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        {
138fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            findDexClass(CLASS_NAME);
139fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        }
140fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes    }
141fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
142fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes    /**
143fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * Main entry point.
144fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     */
145fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes    public static void main(String[] args) throws ClassNotFoundException {
146fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        /*
147fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         * Run tests.
148fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes         */
149fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        testAccess();
150fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes    }
151fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
152fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes    /**
153fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * See if we can load a class when the loader returns null for the
154fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     * superclass.
155fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes     */
156fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes    static void testAccess() {
157fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        try {
158fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            BrokenDexLoader loader;
159fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes
160fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            loader = new BrokenDexLoader(ClassLoader.getSystemClassLoader());
161fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            loader.findBrokenClass();
162fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            System.err.println("ERROR: Inaccessible was accessible");
163fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        } catch (ClassNotFoundException cnfe) {
164fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            Throwable cause = cnfe.getCause();
165fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            if (cause instanceof NullPointerException) {
166fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                System.out.println("Got expected CNFE/NPE");
167fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            } else {
168fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                System.err.println("Got unexpected CNFE");
169fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes                cnfe.printStackTrace();
170fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes            }
171fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes        }
172fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes    }
173fbb80d7f726e551161fccbf0e347624459aefedfBarry Hayes}
174