1 /* VMClassLoader.java -- Reference implementation of native interface 2 required by ClassLoader 3 Copyright (C) 1998, 2001, 2002, 2003, 2004, 2005 Free Software Foundation 4 5 This file is part of GNU Classpath. 6 7 GNU Classpath is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 2, or (at your option) 10 any later version. 11 12 GNU Classpath is distributed in the hope that it will be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with GNU Classpath; see the file COPYING. If not, write to the 19 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 02110-1301 USA. 21 22 Linking this library statically or dynamically with other modules is 23 making a combined work based on this library. Thus, the terms and 24 conditions of the GNU General Public License cover the whole 25 combination. 26 27 As a special exception, the copyright holders of this library give you 28 permission to link this library with independent modules to produce an 29 executable, regardless of the license terms of these independent 30 modules, and to copy and distribute the resulting executable under 31 terms of your choice, provided that you also meet, for each linked 32 independent module, the terms and conditions of the license of that 33 module. An independent module is a module which is not derived from 34 or based on this library. If you modify this library, you may extend 35 this exception to your version of the library, but you are not 36 obligated to do so. If you do not wish to do so, delete this 37 exception statement from your version. */ 38 39 package java.lang; 40 41 import gnu.java.util.EmptyEnumeration; 42 import java.lang.reflect.Constructor; 43 import java.io.File; 44 import java.io.IOException; 45 import java.net.URL; 46 import java.net.URLClassLoader; 47 import java.security.AllPermission; 48 import java.security.Permission; 49 import java.security.Permissions; 50 import java.security.ProtectionDomain; 51 import java.util.ArrayList; 52 import java.util.Enumeration; 53 import java.util.HashMap; 54 import java.util.HashSet; 55 import java.util.Map; 56 import java.util.StringTokenizer; 57 import gnu.gcj.runtime.BootClassLoader; 58 59 /** 60 * java.lang.VMClassLoader is a package-private helper for VMs to implement 61 * on behalf of java.lang.ClassLoader. 62 * 63 * @author John Keiser 64 * @author Mark Wielaard <mark@klomp.org> 65 * @author Eric Blake <ebb9@email.byu.edu> 66 */ 67 final class VMClassLoader 68 { 69 // Protection Domain definitions 70 // FIXME: should there be a special protection domain used for native code? 71 72 // The permission required to check what a classes protection domain is. 73 static final Permission protectionDomainPermission 74 = new RuntimePermission("getProtectionDomain"); 75 // The protection domain returned if we cannot determine it. 76 static ProtectionDomain unknownProtectionDomain; 77 78 static 79 { 80 Permissions permissions = new Permissions(); permissions.add(new AllPermission())81 permissions.add(new AllPermission()); 82 unknownProtectionDomain = new ProtectionDomain(null, permissions); 83 } 84 85 static final HashMap definedPackages = new HashMap(); 86 87 // This is a helper for handling java.endorsed.dirs. It is null 88 // until we've initialized the system, at which point it is created. 89 static BootClassLoader bootLoader; 90 91 // This keeps track of shared libraries we've already tried to load. 92 private static HashSet tried_libraries; 93 94 // Holds one of the LIB_* constants; used to determine how shared 95 // library loads are done. 96 private static int lib_control; 97 98 private static final int LIB_FULL = 0; 99 private static final int LIB_CACHE = 1; 100 private static final int LIB_NEVER = 2; 101 102 /** 103 * Helper to define a class using a string of bytes. This assumes that 104 * the security checks have already been performed, if necessary. 105 * 106 * <strong>For backward compatibility, this just ignores the protection 107 * domain; that is the wrong behavior, and you should directly implement 108 * this method natively if you can.</strong> 109 * 110 * @param name the name to give the class, or null if unknown 111 * @param data the data representing the classfile, in classfile format 112 * @param offset the offset into the data where the classfile starts 113 * @param len the length of the classfile data in the array 114 * @param pd the protection domain 115 * @return the class that was defined 116 * @throws ClassFormatError if data is not in proper classfile format 117 */ defineClass(ClassLoader cl, String name, byte[] data, int offset, int len, ProtectionDomain pd)118 static final native Class defineClass(ClassLoader cl, String name, 119 byte[] data, int offset, int len, 120 ProtectionDomain pd) 121 throws ClassFormatError; 122 123 /** 124 * Helper to resolve all references to other classes from this class. 125 * 126 * @param c the class to resolve 127 */ resolveClass(Class clazz)128 static final void resolveClass(Class clazz) 129 { 130 // There doesn't seem to be a need for this to do anything. 131 // Testing reveals that the JDK doesn't seem to do anything here, 132 // either. 133 } 134 135 /** 136 * Helper to load a class from the bootstrap class loader. 137 * 138 * @param name the class name to load 139 * @param resolve whether to resolve it 140 * @return the class, loaded by the bootstrap classloader or null 141 * if the class wasn't found. Returning null is equivalent to throwing 142 * a ClassNotFoundException (but a possible performance optimization). 143 */ loadClass(String name, boolean resolve)144 static final native Class loadClass(String name, boolean resolve) 145 throws ClassNotFoundException; 146 147 /** 148 * Helper to load a resource from the bootstrap class loader. 149 * 150 * In libgcj, this does nothing, as the default system loader knows 151 * how to find resources that have been linked in. 152 * 153 * @param name the resource to find 154 * @return the URL to the resource 155 */ getResource(String name)156 static URL getResource(String name) 157 { 158 if (bootLoader != null) 159 return bootLoader.bootGetResource(name); 160 return null; 161 } 162 163 /** 164 * Helper to get a list of resources from the bootstrap class loader. 165 * 166 * In libgcj, this does nothing, as the default system loader knows 167 * how to find resources that have been linked in. 168 * 169 * @param name the resource to find 170 * @return an enumeration of resources 171 * @throws IOException if one occurs 172 */ getResources(String name)173 static Enumeration getResources(String name) throws IOException 174 { 175 if (bootLoader != null) 176 return bootLoader.bootGetResources(name); 177 return EmptyEnumeration.getInstance(); 178 } 179 180 /** 181 * Helper to get a package from the bootstrap class loader. The default 182 * implementation of returning null may be adequate, or you may decide 183 * that this needs some native help. 184 * 185 * @param name the name to find 186 * @return the named package, if it exists 187 */ getPackage(String name)188 static synchronized Package getPackage(String name) 189 { 190 return (Package) definedPackages.get(name); 191 } 192 193 /** 194 * Helper to get all packages from the bootstrap class loader. The default 195 * implementation of returning an empty array may be adequate, or you may 196 * decide that this needs some native help. 197 * 198 * @return all named packages, if any exist 199 */ getPackages()200 static synchronized Package[] getPackages() 201 { 202 Package[] packages = new Package[definedPackages.size()]; 203 return (Package[]) definedPackages.values().toArray(packages); 204 } 205 206 // Define a package for something loaded natively. definePackageForNative(String className)207 static synchronized void definePackageForNative(String className) 208 { 209 int lastDot = className.lastIndexOf('.'); 210 if (lastDot != -1) 211 { 212 String packageName = className.substring(0, lastDot); 213 if (getPackage(packageName) == null) 214 { 215 // FIXME: this assumes we're defining the core, which 216 // isn't necessarily so. We could detect this and set up 217 // appropriately. We could also look at a manifest file 218 // compiled into the .so. 219 Package p = new Package(packageName, 220 "Java Platform API Specification", 221 "GNU", "1.4", "gcj", "GNU", 222 null, // FIXME: gcj version. 223 null); 224 definedPackages.put(packageName, p); 225 } 226 } 227 } 228 229 /** 230 * Helper for java.lang.Integer, Byte, etc to get the TYPE class 231 * at initialization time. The type code is one of the chars that 232 * represents the primitive type as in JNI. 233 * 234 * <ul> 235 * <li>'Z' - boolean</li> 236 * <li>'B' - byte</li> 237 * <li>'C' - char</li> 238 * <li>'D' - double</li> 239 * <li>'F' - float</li> 240 * <li>'I' - int</li> 241 * <li>'J' - long</li> 242 * <li>'S' - short</li> 243 * <li>'V' - void</li> 244 * </ul> 245 * 246 * @param type the primitive type 247 * @return a "bogus" class representing the primitive type 248 */ getPrimitiveClass(char type)249 static final native Class getPrimitiveClass(char type); 250 251 /** 252 * The system default for assertion status. This is used for all system 253 * classes (those with a null ClassLoader), as well as the initial value for 254 * every ClassLoader's default assertion status. 255 * 256 * XXX - Not implemented yet; this requires native help. 257 * 258 * @return the system-wide default assertion status 259 */ defaultAssertionStatus()260 static final boolean defaultAssertionStatus() 261 { 262 return true; 263 } 264 265 /** 266 * The system default for package assertion status. This is used for all 267 * ClassLoader's packageAssertionStatus defaults. It must be a map of 268 * package names to Boolean.TRUE or Boolean.FALSE, with the unnamed package 269 * represented as a null key. 270 * 271 * XXX - Not implemented yet; this requires native help. 272 * 273 * @return a (read-only) map for the default packageAssertionStatus 274 */ packageAssertionStatus()275 static final Map packageAssertionStatus() 276 { 277 return new HashMap(); 278 } 279 280 /** 281 * The system default for class assertion status. This is used for all 282 * ClassLoader's classAssertionStatus defaults. It must be a map of 283 * class names to Boolean.TRUE or Boolean.FALSE 284 * 285 * XXX - Not implemented yet; this requires native help. 286 * 287 * @return a (read-only) map for the default classAssertionStatus 288 */ classAssertionStatus()289 static final Map classAssertionStatus() 290 { 291 return new HashMap(); 292 } 293 getSystemClassLoaderInternal()294 static native ClassLoader getSystemClassLoaderInternal(); 295 initBootLoader(String libdir)296 static native void initBootLoader(String libdir); 297 initialize(String libdir)298 static void initialize(String libdir) 299 { 300 initBootLoader(libdir); 301 302 String p 303 = System.getProperty ("gnu.gcj.runtime.VMClassLoader.library_control", 304 ""); 305 if ("never".equals(p)) 306 lib_control = LIB_NEVER; 307 else if ("cache".equals(p)) 308 lib_control = LIB_CACHE; 309 else if ("full".equals(p)) 310 lib_control = LIB_FULL; 311 else 312 lib_control = LIB_NEVER; 313 314 tried_libraries = new HashSet(); 315 } 316 317 /** 318 * Possibly load a .so and search it for classes. 319 */ nativeFindClass(String name)320 static native Class nativeFindClass(String name); 321 getSystemClassLoader()322 static ClassLoader getSystemClassLoader() 323 { 324 // This method is called as the initialization of systemClassLoader, 325 // so if there is a null value, this is the first call and we must check 326 // for java.system.class.loader. 327 String loader = System.getProperty("java.system.class.loader"); 328 ClassLoader default_sys = getSystemClassLoaderInternal(); 329 if (loader != null) 330 { 331 try 332 { 333 Class load_class = Class.forName(loader, true, default_sys); 334 Constructor c 335 = load_class.getConstructor(new Class[] { ClassLoader.class }); 336 default_sys 337 = (ClassLoader) c.newInstance(new Object[] { default_sys }); 338 } 339 catch (Exception ex) 340 { 341 throw new Error("Failed to load requested system classloader " 342 + loader, ex); 343 } 344 } 345 346 return default_sys; 347 } 348 } 349