Main.java revision 89c1feb0a69a7707b271086e749975b3f7acacf7
1/*
2 * Copyright (C) 2008 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17/**
18 * Class loader test.
19 */
20public class Main {
21    /**
22     * Main entry point.
23     */
24    public static void main(String[] args) {
25        FancyLoader loader;
26
27        loader = new FancyLoader(ClassLoader.getSystemClassLoader());
28
29        /*
30         * This statement has no effect on this program, but it can
31         * change the point where a LinkageException is thrown in
32         * testImplement().  When this is present the "reference
33         * implementation" throws an exception from Class.newInstance(),
34         * when it's absent the exception is deferred until the first time
35         * we call a method that isn't actually implemented.
36         *
37         * This isn't the class that fails -- it's a class with the same
38         * name in the "fancy" class loader --  but the VM thinks it has a
39         * reference to one of these; presumably the difference is that
40         * without this the VM finds itself holding a reference to an
41         * instance of an uninitialized class.
42         */
43        System.out.println("base: " + DoubledImplement.class);
44        System.out.println("base2: " + DoubledImplement2.class);
45
46        /*
47         * Run tests.
48         */
49        testAccess1(loader);
50        testAccess2(loader);
51        testAccess3(loader);
52
53        testExtend(loader);
54        testImplement(loader);
55        testIfaceImplement(loader);
56    }
57
58    /**
59     * See if we can load a class that isn't public to us.  We should be
60     * able to load it but not instantiate it.
61     */
62    static void testAccess1(ClassLoader loader) {
63        Class altClass;
64
65        try {
66            altClass = loader.loadClass("Inaccessible1");
67        } catch (ClassNotFoundException cnfe) {
68            System.err.println("loadClass failed");
69            cnfe.printStackTrace();
70            return;
71        }
72
73        /* instantiate */
74        Object obj;
75        try {
76            obj = altClass.newInstance();
77            System.err.println("ERROR: Inaccessible1 was accessible");
78        } catch (InstantiationException ie) {
79            System.err.println("newInstance failed: " + ie);
80            return;
81        } catch (IllegalAccessException iae) {
82            System.out.println("Got expected access exception #1");
83            //System.out.println("+++ " + iae);
84            return;
85        }
86    }
87
88    /**
89     * See if we can load a class whose base class is not accessible to it
90     * (though the base *is* accessible to us).
91     */
92    static void testAccess2(ClassLoader loader) {
93        Class altClass;
94
95        try {
96            altClass = loader.loadClass("Inaccessible2");
97            System.err.println("ERROR: Inaccessible2 was accessible");
98        } catch (ClassNotFoundException cnfe) {
99            Throwable cause = cnfe.getCause();
100            if (cause instanceof IllegalAccessError) {
101                System.out.println("Got expected CNFE/IAE #2");
102            } else {
103                System.err.println("Got unexpected CNFE/IAE #2");
104                cnfe.printStackTrace();
105            }
106        }
107    }
108
109    /**
110     * See if we can load a class with an inaccessible interface.
111     */
112    static void testAccess3(ClassLoader loader) {
113        Class altClass;
114
115        try {
116            altClass = loader.loadClass("Inaccessible3");
117            System.err.println("ERROR: Inaccessible3 was accessible");
118        } catch (ClassNotFoundException cnfe) {
119            Throwable cause = cnfe.getCause();
120            if (cause instanceof IllegalAccessError) {
121                System.out.println("Got expected CNFE/IAE #3");
122            } else {
123                System.err.println("Got unexpected CNFE/IAE #3");
124                cnfe.printStackTrace();
125            }
126        }
127    }
128
129    /**
130     * Test a doubled class that extends the base class.
131     */
132    static void testExtend(ClassLoader loader) {
133        Class doubledExtendClass;
134        Object obj;
135
136        /* get the "alternate" version of DoubledExtend */
137        try {
138            doubledExtendClass = loader.loadClass("DoubledExtend");
139            //System.out.println("+++ DoubledExtend is " + doubledExtendClass
140            //    + " in " + doubledExtendClass.getClassLoader());
141        } catch (ClassNotFoundException cnfe) {
142            System.err.println("loadClass failed: " + cnfe);
143            return;
144        }
145
146        /* instantiate */
147        try {
148            obj = doubledExtendClass.newInstance();
149        } catch (InstantiationException ie) {
150            System.err.println("newInstance failed: " + ie);
151            return;
152        } catch (IllegalAccessException iae) {
153            System.err.println("newInstance failed: " + iae);
154            return;
155        } catch (LinkageError le) {
156            System.out.println("Got expected LinkageError on DE");
157            return;
158        }
159
160        /* use the base class reference to get a CL-specific instance */
161        Base baseRef = (Base) obj;
162        DoubledExtend de = baseRef.getExtended();
163
164        /* try to call through it */
165        try {
166            String result;
167
168            result = Base.doStuff(de);
169            System.err.println("ERROR: did not get LinkageError on DE");
170            System.err.println("(result=" + result + ")");
171        } catch (LinkageError le) {
172            System.out.println("Got expected LinkageError on DE");
173            return;
174        }
175    }
176
177    /**
178     * Test a doubled class that implements a common interface.
179     */
180    static void testImplement(ClassLoader loader) {
181        Class doubledImplementClass;
182        Object obj;
183
184        useImplement(new DoubledImplement(), true);
185
186        /* get the "alternate" version of DoubledImplement */
187        try {
188            doubledImplementClass = loader.loadClass("DoubledImplement");
189        } catch (ClassNotFoundException cnfe) {
190            System.err.println("loadClass failed: " + cnfe);
191            return;
192        }
193
194        /* instantiate */
195        try {
196            obj = doubledImplementClass.newInstance();
197        } catch (InstantiationException ie) {
198            System.err.println("newInstance failed: " + ie);
199            return;
200        } catch (IllegalAccessException iae) {
201            System.err.println("newInstance failed: " + iae);
202            return;
203        } catch (LinkageError le) {
204            System.out.println("Got LinkageError on DI (early)");
205            return;
206        }
207
208        /* if we lived this long, try to do something with it */
209        ICommon icommon = (ICommon) obj;
210        useImplement(icommon.getDoubledInstance(), false);
211    }
212
213    /**
214     * Do something with a DoubledImplement instance.
215     */
216    static void useImplement(DoubledImplement di, boolean isOne) {
217        //System.out.println("useObject: " + di.toString() + " -- "
218        //    + di.getClass().getClassLoader());
219        try {
220            di.one();
221            if (!isOne) {
222                System.err.println("ERROR: did not get LinkageError on DI");
223            }
224        } catch (LinkageError le) {
225            if (!isOne) {
226                System.out.println("Got LinkageError on DI (late)");
227            } else {
228                throw le;
229            }
230        }
231    }
232
233
234    /**
235     * Test a class that implements an interface with a super-interface
236     * that refers to a doubled class.
237     */
238    static void testIfaceImplement(ClassLoader loader) {
239        Class ifaceImplClass;
240        Object obj;
241
242        /*
243         * Create an instance of IfaceImpl.  We also pull in
244         * DoubledImplement2 from the other class loader; without this
245         * we don't fail in some implementations.
246         */
247        try {
248            ifaceImplClass = loader.loadClass("IfaceImpl");
249            ifaceImplClass = loader.loadClass("DoubledImplement2");
250        } catch (ClassNotFoundException cnfe) {
251            System.err.println("loadClass failed: " + cnfe);
252            return;
253        }
254
255        /* instantiate */
256        try {
257            obj = ifaceImplClass.newInstance();
258        } catch (InstantiationException ie) {
259            System.err.println("newInstance failed: " + ie);
260            return;
261        } catch (IllegalAccessException iae) {
262            System.err.println("newInstance failed: " + iae);
263            return;
264        } catch (LinkageError le) {
265            System.out.println("Got LinkageError on IDI (early)");
266            //System.out.println(le);
267            return;
268        }
269
270        /*
271         * Without the pre-load of FancyLoader->DoubledImplement2, some
272         * implementations will happily execute through this part.  "obj"
273         * comes from FancyLoader, but the di2 returned from ifaceSuper
274         * comes from the application class loader.
275         */
276        IfaceSuper ifaceSuper = (IfaceSuper) obj;
277        DoubledImplement2 di2 = ifaceSuper.getDoubledInstance2();
278        di2.one();
279    }
280}
281
282