1 /* 2 * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara, 20 * CA 95054 USA or visit www.sun.com if you need additional information or 21 * have any questions. 22 * 23 */ 24 25 package sun.jvm.hotspot.jdi; 26 27 import java.io.*; 28 import java.net.*; 29 30 /* 31 * This class loader is used for two different reasons: 32 * 33 * 1) To support multiple simultaneous debuggees. 34 * 35 * SA's architecture does not allow us to use multiple simultaneous 36 * debuggees. This is because of lots of static fields caching 37 * vmStruct fields and singleton assumption in classes such as 38 * 'sun.jvm.hotspot.runtime.VM'. Hence, we use instances of this 39 * class loader to create a separate namespace for each debuggee VM. 40 * 41 * 2) To support cross VM version debugging. 42 * 43 * SA has very close dependency on VM data structures. Due to this, a 44 * version of SA can only support debuggees running a same dot-dot release and 45 * update releases only. For eg. this version of SA supports only 1.4.2 and 46 * 1.4.2_xx releases only. But, users may want to debug debuggees running 47 * a different version of VM. To support this, we use an instance of this 48 * class loader to load classes from corresponding sa-jdi.jar. 49 * 50 * Note that JDI classes would still be loaded from the debugger's tools.jar 51 * and not from debuggee's tools.jar. This means that if JDI interface evolved 52 * b/w debuggee and debugger VM versions, user may still get problems. This is 53 * the case when debugger runs on 1.5.0 and debuggee runs on 1.4.2. Because JDI 54 * evolved b/w these versions (generics, enum, varargs etc.), 1.4.2 sa-jdi.jar 55 * won't implement 1.5.0 JDI properly and user would get verifier errors. This 56 * class loader solution is suited for different dot-dot release where JDI will 57 * not evolve but VM data structures might change and SA implementation might 58 * have to change. For example, a debuggee running 1.5.1 VM can be debugged 59 * with debugger running on 1.5.0 VM. Here, JDI is same but VM data structures 60 * could still change. 61 */ 62 63 class SAJDIClassLoader extends URLClassLoader { 64 private static final boolean DEBUG; 65 static { 66 DEBUG = System.getProperty("sun.jvm.hotspot.jdi.SAJDIClassLoader.DEBUG") != null; 67 } 68 69 private ClassLoader parent; 70 private boolean classPathSet; 71 72 SAJDIClassLoader(ClassLoader parent) { 73 super(new URL[0], parent); 74 this.parent = parent; 75 } 76 77 SAJDIClassLoader(ClassLoader parent, String classPath) { 78 this(parent); 79 this.classPathSet = true; 80 try { 81 addURL(new File(classPath).toURI().toURL()); 82 } catch(MalformedURLException mue) { 83 throw new RuntimeException(mue); 84 } 85 } 86 87 public synchronized Class loadClass(String name) 88 throws ClassNotFoundException { 89 // First, check if the class has already been loaded 90 Class c = findLoadedClass(name); 91 if (c == null) { 92 /* If we are loading any class in 'sun.jvm.hotspot.' or any of the 93 * sub-packages (except for 'debugger' sub-pkg. please refer below), 94 * we load it by 'this' loader. Or else, we forward the request to 95 * 'parent' loader, system loader etc. (rest of the code follows 96 * the patten in java.lang.ClassLoader.loadClass). 97 * 98 * 'sun.jvm.hotspot.debugger.' and sub-package classes are 99 * also loaded by parent loader. This is done for two reasons: 100 * 101 * 1. to avoid code bloat by too many classes. 102 * 2. to avoid loading same native library multiple times 103 * from multiple class loaders (which results in getting a 104 * UnsatisifiedLinkageError from System.loadLibrary). 105 */ 106 107 if (name.startsWith("sun.jvm.hotspot.") && 108 !name.startsWith("sun.jvm.hotspot.debugger.")) { 109 return findClass(name); 110 } 111 if (parent != null) { 112 c = parent.loadClass(name); 113 } else { 114 c = findSystemClass(name); 115 } 116 } 117 return c; 118 } 119 120 protected Class findClass(String name) throws ClassNotFoundException { 121 if (DEBUG) { 122 System.out.println("SA/JDI loader: about to load " + name); 123 } 124 if (classPathSet) { 125 return super.findClass(name); 126 } else { 127 byte[] b = null; 128 try { 129 InputStream in = getResourceAsStream(name.replace('.', '/') + ".class"); 130 // Read until end of stream is reached 131 b = new byte[1024]; 132 int total = 0; 133 int len = 0; 134 while ((len = in.read(b, total, b.length - total)) != -1) { 135 total += len; 136 if (total >= b.length) { 137 byte[] tmp = new byte[total * 2]; 138 System.arraycopy(b, 0, tmp, 0, total); 139 b = tmp; 140 } 141 } 142 // Trim array to correct size, if necessary 143 if (total != b.length) { 144 byte[] tmp = new byte[total]; 145 System.arraycopy(b, 0, tmp, 0, total); 146 b = tmp; 147 } 148 } catch (Exception exp) { 149 throw (ClassNotFoundException) new ClassNotFoundException().initCause(exp); 150 } 151 return defineClass(name, b, 0, b.length); 152 } 153 } 154 }