12cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom/* 22cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Copyright (C) 2011 The Android Open Source Project 32cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 42cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Licensed under the Apache License, Version 2.0 (the "License"); 52cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * you may not use this file except in compliance with the License. 62cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * You may obtain a copy of the License at 72cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 82cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * http://www.apache.org/licenses/LICENSE-2.0 92cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 102cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Unless required by applicable law or agreed to in writing, software 112cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * distributed under the License is distributed on an "AS IS" BASIS, 122cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 132cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * See the License for the specific language governing permissions and 142cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * limitations under the License. 152cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 162cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 172cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrompackage dalvik.system; 182cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 192cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.io.File; 202cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.net.URL; 212cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.util.ArrayList; 222cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.util.Enumeration; 232cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstromimport java.util.List; 242cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 252cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom/** 262cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Base class for common functionality between various dex-based 272cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * {@link ClassLoader} implementations. 282cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 292cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrompublic class BaseDexClassLoader extends ClassLoader { 302cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom private final DexPathList pathList; 312cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 322cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 332cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Constructs an instance. 342cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 352cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param dexPath the list of jar/apk files containing classes and 362cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * resources, delimited by {@code File.pathSeparator}, which 372cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * defaults to {@code ":"} on Android 382cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param optimizedDirectory directory where optimized dex files 392cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * should be written; may be {@code null} 402cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param libraryPath the list of directories containing native 412cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * libraries, delimited by {@code File.pathSeparator}; may be 422cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * {@code null} 432cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param parent the parent class loader 442cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 452cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public BaseDexClassLoader(String dexPath, File optimizedDirectory, 462cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom String libraryPath, ClassLoader parent) { 472cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom super(parent); 482cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom this.pathList = new DexPathList(this, dexPath, libraryPath, optimizedDirectory); 492cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 502cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 512cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom @Override 522cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom protected Class<?> findClass(String name) throws ClassNotFoundException { 532cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom List<Throwable> suppressedExceptions = new ArrayList<Throwable>(); 542cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom Class c = pathList.findClass(name, suppressedExceptions); 552cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom if (c == null) { 562cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom ClassNotFoundException cnfe = new ClassNotFoundException("Didn't find class \"" + name + "\" on path: " + pathList); 572cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom for (Throwable t : suppressedExceptions) { 582cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom cnfe.addSuppressed(t); 592cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 602cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom throw cnfe; 612cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 622cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return c; 632cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 642cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 652cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom @Override 662cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom protected URL findResource(String name) { 672cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return pathList.findResource(name); 682cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 692cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 702cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom @Override 712cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom protected Enumeration<URL> findResources(String name) { 722cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return pathList.findResources(name); 732cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 742cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 752cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom @Override 762cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public String findLibrary(String name) { 772cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return pathList.findLibrary(name); 782cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 792cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 802cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 812cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Returns package information for the given package. 822cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Unfortunately, instances of this class don't really have this 832cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * information, and as a non-secure {@code ClassLoader}, it isn't 842cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * even required to, according to the spec. Yet, we want to 852cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * provide it, in order to make all those hopeful callers of 862cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * {@code myClass.getPackage().getName()} happy. Thus we construct 872cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * a {@code Package} object the first time it is being requested 882cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * and fill most of the fields with dummy values. The {@code 892cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * Package} object is then put into the {@code ClassLoader}'s 902cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * package cache, so we see the same one next time. We don't 912cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * create {@code Package} objects for {@code null} arguments or 922cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * for the default package. 932cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 942cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * <p>There is a limited chance that we end up with multiple 952cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * {@code Package} objects representing the same package: It can 962cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * happen when when a package is scattered across different JAR 972cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * files which were loaded by different {@code ClassLoader} 982cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * instances. This is rather unlikely, and given that this whole 992cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * thing is more or less a workaround, probably not worth the 1002cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * effort to address. 1012cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * 1022cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @param name the name of the class 1032cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @return the package information for the class, or {@code null} 1042cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * if there is no package information available for it 1052cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 1062cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom @Override 1072cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom protected synchronized Package getPackage(String name) { 1082cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom if (name != null && !name.isEmpty()) { 1092cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom Package pack = super.getPackage(name); 1102cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 1112cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom if (pack == null) { 1122cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom pack = definePackage(name, "Unknown", "0.0", "Unknown", 1132cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom "Unknown", "0.0", "Unknown", null); 1142cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1152cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 1162cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return pack; 1172cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1182cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 1192cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return null; 1202cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1212cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 1222cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom /** 1232cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom * @hide 1242cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom */ 1252cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom public String getLdLibraryPath() { 1262cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom StringBuilder result = new StringBuilder(); 1272cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom for (File directory : pathList.getNativeLibraryDirectories()) { 1282cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom if (result.length() > 0) { 1292cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom result.append(':'); 1302cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1312cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom result.append(directory); 1322cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1332cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom 134f38cae4f22e46c49f5fba94e6e0579dedd2d8fd1Dmitriy Ivanov return result.toString(); 1357694b783f48e2cc57928b61c84fd90311cb0c35aDmitriy Ivanov } 1367694b783f48e2cc57928b61c84fd90311cb0c35aDmitriy Ivanov 1372cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom @Override public String toString() { 1382cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom return getClass().getName() + "[" + pathList + "]"; 1392cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom } 1402cf03dc15c40b92634ff606694af5a6e9aa4db09Brian Carlstrom} 141