📄 adaptiveclassloader.java
字号:
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
u = findResourceInternal(name);
if ( u != null ) {
return u;
}
// Not found
return null;
}
protected URL findResourceInternal(String name) {
try {
return (URL) findResourcesInternal(name, true).elementAt(0);
} catch( IOException e ) {
return null;
} catch(ArrayIndexOutOfBoundsException e){
return null;
}
}
protected Vector findResourcesInternal(String name, boolean justOne) throws IOException {
Vector urls = new Vector( repository.size() );
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 {
urls.add( new URL("file", null, resFile.getAbsolutePath()) );
if(justOne) return urls;
} 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);
zf.close();
if (ze != null) {
try {
urls.add( new URL("jar:file:" + file.getAbsolutePath() + "!/" + name) );
if(justOne) return urls;
} catch(java.net.MalformedURLException badurl) {
badurl.printStackTrace();
return null;
}
}
} catch (IOException ioe) {
ioe.printStackTrace();
return null;
}
}
}
return urls;
}
public String toString() {
return "AdaptiveClassLoader( )";
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -