📄 adaptiveclassloader.java
字号:
// The class object that will be returned. Class c = null; // Use the cached value, if this class is already loaded into // this classloader. ClassCacheEntry entry = (ClassCacheEntry) cache.get(name); if (entry != null) { if( debug>0) log( "Found in cache " + name); // Class found in our cache c = entry.loadedClass; if (resolve) resolveClass(c); return c; } // Make sure we can access this class when using a SecurityManager if (sm != null) { int i = name.lastIndexOf('.'); if (i >= 0) { sm.checkPackageAccess(name.substring(0,i)); sm.checkPackageDefinition(name.substring(0,i)); } } if (parent != null) { try { if( debug>0) log( "loadClass() from parent " + name); c = parent.loadClass(name); if (c != null) { if (resolve) resolveClass(c); return c; } } catch (ClassNotFoundException e) { c = null; } catch (Exception e) { c = null; } } // Attempt to load the class from the system if( debug>0) log( "loadClass() from system " + name); try { c = loadSystemClass(name, resolve); if (c != null) { return c; } } catch (Exception e) { c = null; } if( debug>0) log( "loadClass() from local repository " + name); // Try to load it from each repository Enumeration repEnum = repository.elements(); // Cache entry. ClassCacheEntry classCache = new ClassCacheEntry(); while (repEnum.hasMoreElements()) { byte[] classData=null; ClassRepository cp = (ClassRepository) repEnum.nextElement(); File file = cp.getFile(); try { if (file.isDirectory()) { classData = loadClassFromDirectory(file, name, classCache); } else { classData = loadClassFromZipfile(file, name, classCache); } } catch(SecurityException sex) { sex.printStackTrace(); throw sex; } catch(IOException ioe) { // Error while reading in data, consider it as not found classData = null; } catch( Exception ex ) { ex.printStackTrace(); } if (classData != null) { // Define the class with a ProtectionDomain if using // a SecurityManager // Origin is set by the specific loader classCache.lastModified = classCache.origin.lastModified(); if( debug>0) log( "Add to cache() " + name + " " + classCache); cache.put(name, classCache); if( debug>0) log( "Before define class " + name); try { classCache.loadedClass = doDefineClass(name, classData, cp.getProtectionDomain()); } catch(Throwable t ) { t.printStackTrace(); } if( debug>0) log( "Class defined " + classCache.loadedClass); // Cache the result; // Resolve it if necessary if (resolve) resolveClass(classCache.loadedClass); return classCache.loadedClass; } } // If not found in any repository throw new ClassNotFoundException(name); } // Override this with PD protected Class doDefineClass(String name, byte classData[], Object pd ) { return defineClass(name, classData, 0, classData.length); } /** * Load a class using the system classloader. * * @exception ClassNotFoundException if the class loader cannot * find a the requested class. * @exception NoClassDefFoundError if the class loader cannot * find a definition for the class. */ private Class loadSystemClass(String name, boolean resolve) throws NoClassDefFoundError, ClassNotFoundException { Class c = findSystemClass(name); // Throws if not found.// // Add cache entry// ClassCacheEntry cacheEntry = new ClassCacheEntry();// cacheEntry.origin = null;// cacheEntry.loadedClass = c;// cacheEntry.lastModified = Long.MAX_VALUE;// cache.put(name, cacheEntry); if (resolve) resolveClass(c); return c; } /** * Tries to load the class from a directory. * * @param dir The directory that contains classes. * @param name The classname * @param cache The cache entry to set the file if successful. */ private byte[] loadClassFromDirectory(File dir, String name, ClassCacheEntry cache) throws IOException { // Translate class name to file name String classFileName = name.replace('.', File.separatorChar) + ".class"; // Check for garbage input at beginning of file name // i.e. ../ or similar if (!Character.isJavaIdentifierStart(classFileName.charAt(0))) { // Find real beginning of class name int start = 1; while (!Character.isJavaIdentifierStart( classFileName.charAt(start++))); classFileName = classFileName.substring(start); } File classFile = new File(dir, classFileName); if (classFile.exists()) { cache.origin = classFile; InputStream in = new FileInputStream(classFile); try { return loadBytesFromStream(in, (int) classFile.length()); } finally { in.close(); } } else { // Not found return null; } } /** * Tries to load the class from a zip file. * * @param file The zipfile that contains classes. * @param name The classname * @param cache The cache entry to set the file if successful. */ private byte[] loadClassFromZipfile(File file, String name, ClassCacheEntry cache) throws IOException { // Translate class name to file name String classFileName = name.replace('.', '/') + ".class"; ZipFile zipfile = new ZipFile(file); try { ZipEntry entry = zipfile.getEntry(classFileName); // System.out.println("XXX Found " + classFileName + " " + entry + " " + entry.getSize() ); if (entry != null) { cache.origin = file; return loadBytesFromStream(zipfile.getInputStream(entry), (int) entry.getSize()); } else { // Not found return null; } } finally { zipfile.close(); } } /** * Loads all the bytes of an InputStream. */ private byte[] loadBytesFromStream(InputStream in, int length) throws IOException { byte[] buf = new byte[length]; int nRead, count = 0; while ((length > 0) && ((nRead = in.read(buf,count,length)) != -1)) { count += nRead; length -= nRead; } return buf; } /** * Get an InputStream on a given resource. Will return null if no * resource with this name is found. * <p> * The JServClassLoader translate the resource's name to a file * or a zip entry. It looks for the resource in all its repository * entry. * * @see java.lang.Class#getResourceAsStream(String) * @param name the name of the resource, to be used as is. * @return an InputStream on the resource, or null if not found. */ public InputStream getResourceAsStream(String name) { // Try to load it from the system class if( debug > 0 ) log( "getResourceAsStream() " + name ); // First ask the parent class loader to fetch it, if possible InputStream s = null; if (parent != null) { s = parent.getResourceAsStream(name); if (s != null) return (s); } // Second ask the system class loader to fetch it from the classpath s = getSystemResourceAsStream(name); // Third, check our own repositories if (s == null) { // Try to find it from every repository Enumeration repEnum = repository.elements(); while (repEnum.hasMoreElements()) { ClassRepository cp = (ClassRepository) repEnum.nextElement(); File file = cp.getFile(); if (file.isDirectory()) { s = loadResourceFromDirectory(file, name); } else if(name.endsWith(".initArgs")) { // XXX XXX XXX What is this ? File dir = new File(file.getParent()); s = loadResourceFromDirectory(dir, name); } else { s = loadResourceFromZipfile(file, name); } // System.out.println("LOADING " + file + " " + name + " " + s ); if (s != null) { break; } } } return s; } /** * Loads resource from a directory. */ private InputStream loadResourceFromDirectory(File dir, String name) { // Name of resources are always separated by / String fileName = name.replace('/', File.separatorChar); File resFile = new File(dir, fileName); if (resFile.exists()) { try { return new FileInputStream(resFile); } catch (FileNotFoundException shouldnothappen) { return null; } } else { return null; } } /** * Loads resource from a zip file */ private InputStream loadResourceFromZipfile(File file, String name) { ZipFile zipfile = null; try { zipfile = new ZipFile(file); ZipEntry entry = zipfile.getEntry(name); if (entry != null) { // workaround - the better solution is to not close the // zipfile !!!! byte[] data= loadBytesFromStream(zipfile.getInputStream(entry), (int) entry.getSize()); if(data != null) { InputStream istream = new ByteArrayInputStream(data); return istream; } } } catch(IOException e) { } finally { // if we close the zipfile bad things will happen - we can't read the stream // on some VMs if ( zipfile != null ) { try { zipfile.close(); } catch ( IOException ignored ) { } } } // default case return null; } /** * Find a resource with a given name. The return is a URL to the * resource. Doing a getContent() on the URL may return an Image, * an AudioClip,or an InputStream. * <p> * This classloader looks for the resource only in the directory * repository for this resource. * * @param name the name of the resource, to be used as is. * @return an URL on the resource, or null if not found. */ public URL getResource(String name) { if( debug > 0 ) log( "getResource() " + name ); // First ask the parent class loader to fetch it, if possible URL u = null; if (parent != null) { u = parent.getResource(name); if (u != null) return (u); } // Second ask the system class loader to fetch it from the classpath u = getSystemResource(name); if (u != null) { return u; } if (name == null) { return null; } // Third, check our own repositories Enumeration repEnum = repository.elements(); while (repEnum.hasMoreElements()) { ClassRepository cp = (ClassRepository) repEnum.nextElement(); File file = cp.getFile(); // Construct a file://-URL if the repository is a directory if (file.isDirectory()) { String fileName = name.replace('/', File.separatorChar); File resFile = new File(file, fileName); if (resFile.exists()) { // Build a file:// URL form the file name try { return new URL("file", null, resFile.getAbsolutePath()); } catch(java.net.MalformedURLException badurl) { badurl.printStackTrace(); return null; } } } else { // a jar:-URL *could* change even between minor releases, but // didn't between JVM's 1.1.6 and 1.3beta. Tested on JVM's from // IBM, Blackdown, Microsoft, Sun @ Windows and Sun @ Solaris try { ZipFile zf = new ZipFile(file.getAbsolutePath()); ZipEntry ze = zf.getEntry(name); if (ze != null) { try { return new URL("jar:file:" + file.getAbsolutePath() + "!/" + name); } catch(java.net.MalformedURLException badurl) { badurl.printStackTrace(); return null; } } } catch (IOException ioe) { ioe.printStackTrace(); return null; } } } // Not found return null; } public String toString() { return "AdaptiveClassLoader( )"; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -