1 /* VMClassLoader.java -- Reference implementation of native interface 2 required by ClassLoader 3 Copyright (C) 1998, 2001, 2002, 2004, 2005, 2006, 2010 4 Free Software Foundation, Inc. 5 6 This file is part of GNU Classpath. 7 8 GNU Classpath is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 2, or (at your option) 11 any later version. 12 13 GNU Classpath is distributed in the hope that it will be useful, but 14 WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 16 General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with GNU Classpath; see the file COPYING. If not, write to the 20 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 21 02110-1301 USA. 22 23 Linking this library statically or dynamically with other modules is 24 making a combined work based on this library. Thus, the terms and 25 conditions of the GNU General Public License cover the whole 26 combination. 27 28 As a special exception, the copyright holders of this library give you 29 permission to link this library with independent modules to produce an 30 executable, regardless of the license terms of these independent 31 modules, and to copy and distribute the resulting executable under 32 terms of your choice, provided that you also meet, for each linked 33 independent module, the terms and conditions of the license of that 34 module. An independent module is a module which is not derived from 35 or based on this library. If you modify this library, you may extend 36 this exception to your version of the library, but you are not 37 obligated to do so. If you do not wish to do so, delete this 38 exception statement from your version. */ 39 40 41 package java.lang; 42 43 import gnu.classpath.Configuration; 44 import gnu.classpath.SystemProperties; 45 import gnu.java.lang.InstrumentationImpl; 46 47 import java.io.BufferedReader; 48 import java.io.File; 49 import java.io.IOException; 50 import java.io.InputStreamReader; 51 import java.lang.instrument.Instrumentation; 52 import java.net.MalformedURLException; 53 import java.net.URL; 54 import java.security.ProtectionDomain; 55 import java.util.Enumeration; 56 import java.util.HashMap; 57 import java.util.HashSet; 58 import java.util.Map; 59 import java.util.Set; 60 import java.util.StringTokenizer; 61 import java.util.Vector; 62 import java.util.zip.ZipFile; 63 64 /** 65 * java.lang.VMClassLoader is a package-private helper for VMs to implement 66 * on behalf of java.lang.ClassLoader. 67 * 68 * @author John Keiser 69 * @author Mark Wielaard (mark@klomp.org) 70 * @author Eric Blake (ebb9@email.byu.edu) 71 */ 72 final class VMClassLoader 73 { 74 75 /** packages loaded by the bootstrap class loader */ 76 static final HashMap definedPackages = new HashMap(); 77 78 /** jars from property java.boot.class.path */ 79 static final HashMap bootjars = new HashMap(); 80 81 82 /** 83 * Converts the array string of native package names to 84 * Packages. The packages are then put into the 85 * definedPackages hashMap 86 */ 87 static 88 { 89 String[] packages = getBootPackages(); 90 91 if( packages != null) 92 { 93 String specName = 94 SystemProperties.getProperty("java.specification.name"); 95 String vendor = 96 SystemProperties.getProperty("java.specification.vendor"); 97 String version = 98 SystemProperties.getProperty("java.specification.version"); 99 100 Package p; 101 102 for(int i = 0; i < packages.length; i++) 103 { 104 p = new Package(packages[i], 105 specName, 106 vendor, 107 version, 108 "GNU Classpath", 109 "GNU", 110 Configuration.CLASSPATH_VERSION, 111 null, 112 null); 113 definedPackages.put(packages[i], p)114 definedPackages.put(packages[i], p); 115 } 116 } 117 } 118 VMClassLoader()119 private VMClassLoader() {} // Prohibits instantiation. 120 121 /** 122 * Helper to define a class using a string of bytes. This assumes that 123 * the security checks have already been performed, if necessary. 124 * 125 * Implementations of this method are advised to consider the 126 * situation where user code modifies the byte array after it has 127 * been passed to defineClass. This can be handled by making a 128 * private copy of the array, or arranging to only read any given 129 * byte a single time. 130 * 131 * @param name the name to give the class, or null if unknown 132 * @param data the data representing the classfile, in classfile format 133 * @param offset the offset into the data where the classfile starts 134 * @param len the length of the classfile data in the array 135 * @param pd the protection domain 136 * @return the class that was defined 137 * @throws ClassFormatError if data is not in proper classfile format 138 */ defineClass(ClassLoader cl, String name, byte[] data, int offset, int len, ProtectionDomain pd)139 static final native Class defineClass(ClassLoader cl, String name, 140 byte[] data, int offset, int len, 141 ProtectionDomain pd) 142 throws ClassFormatError; 143 144 /** 145 * Helper to resolve all references to other classes from this class. 146 * 147 * @param c the class to resolve 148 */ resolveClass(Class c)149 static final native void resolveClass(Class c); 150 151 /** 152 * Helper to load a class from the bootstrap class loader. 153 * 154 * @param name the class name to load 155 * @param resolve whether to resolve it 156 * @return the class, loaded by the bootstrap classloader or null 157 * if the class wasn't found. Returning null is equivalent to throwing 158 * a ClassNotFoundException (but a possible performance optimization). 159 */ loadClass(String name, boolean resolve)160 static final native Class loadClass(String name, boolean resolve) 161 throws ClassNotFoundException; 162 163 /** 164 * Helper to load a resource from the bootstrap class loader. 165 * 166 * @param name the resource to find 167 * @return the URL to the resource 168 */ getResource(String name)169 static URL getResource(String name) 170 { 171 Enumeration e = getResources(name); 172 if (e.hasMoreElements()) 173 return (URL)e.nextElement(); 174 return null; 175 } 176 177 /** 178 * Helper to get a list of resources from the bootstrap class loader. 179 * 180 * @param name the resource to find 181 * @return an enumeration of resources 182 */ getResources(String name)183 static Enumeration getResources(String name) 184 { 185 StringTokenizer st = new StringTokenizer( 186 SystemProperties.getProperty("java.boot.class.path", "."), 187 File.pathSeparator); 188 Vector v = new Vector(); 189 while (st.hasMoreTokens()) 190 { 191 File file = new File(st.nextToken()); 192 if (file.isDirectory()) 193 { 194 try 195 { 196 File f = new File(file, name); 197 if (!f.exists()) continue; 198 v.add(new URL("file://" + f.getAbsolutePath())); 199 } 200 catch (MalformedURLException e) 201 { 202 throw new Error(e); 203 } 204 } 205 else if (file.isFile()) 206 { 207 ZipFile zip; 208 synchronized(bootjars) 209 { 210 zip = (ZipFile) bootjars.get(file.getName()); 211 } 212 if(zip == null) 213 { 214 try 215 { 216 zip = new ZipFile(file); 217 synchronized(bootjars) 218 { 219 bootjars.put(file.getName(), zip); 220 } 221 } 222 catch (IOException e) 223 { 224 continue; 225 } 226 } 227 String zname = name.startsWith("/") ? name.substring(1) : name; 228 if (zip.getEntry(zname) == null) 229 continue; 230 try 231 { 232 v.add(new URL("jar:file://" 233 + file.getAbsolutePath() + "!/" + zname)); 234 } 235 catch (MalformedURLException e) 236 { 237 throw new Error(e); 238 } 239 } 240 } 241 return v.elements(); 242 } 243 244 /** 245 * Returns a String[] of native package names. The default 246 * implementation tries to load a list of package from 247 * the META-INF/INDEX.LIST file in the boot jar file. 248 * If not found or if any exception is raised, it returns 249 * an empty array. You may decide this needs native help. 250 */ getBootPackages()251 private static String[] getBootPackages() 252 { 253 URL indexList = getResource("META-INF/INDEX.LIST"); 254 if (indexList != null) 255 { 256 try 257 { 258 Set packageSet = new HashSet(); 259 String line; 260 int lineToSkip = 3; 261 BufferedReader reader = new BufferedReader( 262 new InputStreamReader( 263 indexList.openStream())); 264 while ((line = reader.readLine()) != null) 265 { 266 if (lineToSkip == 0) 267 { 268 if (line.length() == 0) 269 lineToSkip = 1; 270 else 271 packageSet.add(line.replace('/', '.')); 272 } 273 else 274 lineToSkip--; 275 } 276 reader.close(); 277 return (String[]) packageSet.toArray(new String[packageSet.size()]); 278 } 279 catch (IOException e) 280 { 281 return new String[0]; 282 } 283 } 284 else 285 return new String[0]; 286 } 287 288 /** 289 * Helper to get a package from the bootstrap class loader. 290 * 291 * @param name the name to find 292 * @return the named package, if it exists 293 */ getPackage(String name)294 static Package getPackage(String name) 295 { 296 return (Package)definedPackages.get(name); 297 } 298 299 300 301 /** 302 * Helper to get all packages from the bootstrap class loader. 303 * 304 * @return all named packages, if any exist 305 */ getPackages()306 static Package[] getPackages() 307 { 308 Package[] packages = new Package[definedPackages.size()]; 309 definedPackages.values().toArray(packages); 310 return packages; 311 } 312 313 /** 314 * Helper for java.lang.Integer, Byte, etc to get the TYPE class 315 * at initialization time. The type code is one of the chars that 316 * represents the primitive type as in JNI. 317 * 318 * <ul> 319 * <li>'Z' - boolean</li> 320 * <li>'B' - byte</li> 321 * <li>'C' - char</li> 322 * <li>'D' - double</li> 323 * <li>'F' - float</li> 324 * <li>'I' - int</li> 325 * <li>'J' - long</li> 326 * <li>'S' - short</li> 327 * <li>'V' - void</li> 328 * </ul> 329 * 330 * @param type the primitive type 331 * @return a "bogus" class representing the primitive type 332 */ getPrimitiveClass(char type)333 static final native Class getPrimitiveClass(char type); 334 335 /** 336 * The system default for assertion status. This is used for all system 337 * classes (those with a null ClassLoader), as well as the initial value for 338 * every ClassLoader's default assertion status. 339 * 340 * XXX - Not implemented yet; this requires native help. 341 * 342 * @return the system-wide default assertion status 343 */ defaultAssertionStatus()344 static final boolean defaultAssertionStatus() 345 { 346 return true; 347 } 348 349 /** 350 * The system default for package assertion status. This is used for all 351 * ClassLoader's packageAssertionStatus defaults. It must be a map of 352 * package names to Boolean.TRUE or Boolean.FALSE, with the unnamed package 353 * represented as a null key. 354 * 355 * XXX - Not implemented yet; this requires native help. 356 * 357 * @return a (read-only) map for the default packageAssertionStatus 358 */ packageAssertionStatus()359 static final Map packageAssertionStatus() 360 { 361 return new HashMap(); 362 } 363 364 /** 365 * The system default for class assertion status. This is used for all 366 * ClassLoader's classAssertionStatus defaults. It must be a map of 367 * class names to Boolean.TRUE or Boolean.FALSE 368 * 369 * XXX - Not implemented yet; this requires native help. 370 * 371 * @return a (read-only) map for the default classAssertionStatus 372 */ classAssertionStatus()373 static final Map classAssertionStatus() 374 { 375 return new HashMap(); 376 } 377 getSystemClassLoader()378 static ClassLoader getSystemClassLoader() 379 { 380 return ClassLoader.defaultGetSystemClassLoader(); 381 } 382 383 /** 384 * Find the class if this class loader previously defined this class 385 * or if this class loader has been recorded as the initiating class loader 386 * for this class. 387 */ findLoadedClass(ClassLoader cl, String name)388 static native Class findLoadedClass(ClassLoader cl, String name); 389 390 /** 391 * The Instrumentation object created by the vm when agents are defined. 392 */ 393 static final Instrumentation instrumenter = null; 394 395 /** 396 * Call the transformers of the possible Instrumentation object. This 397 * implementation assumes the instrumenter is a 398 * <code>InstrumentationImpl</code> object. VM implementors would 399 * have to redefine this method if they provide their own implementation 400 * of the <code>Instrumentation</code> interface. 401 * 402 * @param loader the initiating loader 403 * @param name the name of the class 404 * @param data the data representing the classfile, in classfile format 405 * @param offset the offset into the data where the classfile starts 406 * @param len the length of the classfile data in the array 407 * @param pd the protection domain 408 * @return the new data representing the classfile 409 */ defineClassWithTransformers(ClassLoader loader, String name, byte[] data, int offset, int len, ProtectionDomain pd)410 static final Class defineClassWithTransformers(ClassLoader loader, 411 String name, byte[] data, int offset, int len, ProtectionDomain pd) 412 { 413 414 if (instrumenter != null) 415 { 416 byte[] modifiedData = new byte[len]; 417 System.arraycopy(data, offset, modifiedData, 0, len); 418 String jvmName = name.replace('.', '/'); 419 modifiedData = 420 ((InstrumentationImpl)instrumenter).callTransformers(loader, jvmName, 421 null, pd, modifiedData); 422 423 return defineClass(loader, name, modifiedData, 0, modifiedData.length, 424 pd); 425 } 426 else 427 { 428 return defineClass(loader, name, data, offset, len, pd); 429 } 430 } 431 } 432