📄 webappclassloader.java
字号:
/**
* Clear references.
*/
protected void clearReferences() {
// Unregister any JDBC drivers loaded by this classloader
Enumeration drivers = DriverManager.getDrivers();
while (drivers.hasMoreElements()) {
Driver driver = (Driver) drivers.nextElement();
if (driver.getClass().getClassLoader() == this) {
try {
DriverManager.deregisterDriver(driver);
} catch (SQLException e) {
log.warn("SQL driver deregistration failed", e);
}
}
}
// Null out any static or final fields from loaded classes,
// as a workaround for apparent garbage collection bugs
if (ENABLE_CLEAR_REFERENCES) {
Iterator loadedClasses = ((HashMap) resourceEntries.clone()).values().iterator();
while (loadedClasses.hasNext()) {
ResourceEntry entry = (ResourceEntry) loadedClasses.next();
if (entry.loadedClass != null) {
Class clazz = entry.loadedClass;
try {
Field[] fields = clazz.getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
int mods = field.getModifiers();
if (field.getType().isPrimitive()
|| (field.getName().indexOf("$") != -1)) {
continue;
}
if (Modifier.isStatic(mods)) {
try {
field.setAccessible(true);
if (Modifier.isFinal(mods)) {
if (!((field.getType().getName().startsWith("java."))
|| (field.getType().getName().startsWith("javax.")))) {
nullInstance(field.get(null));
}
} else {
field.set(null, null);
if (log.isDebugEnabled()) {
log.debug("Set field " + field.getName()
+ " to null in class " + clazz.getName());
}
}
} catch (Throwable t) {
if (log.isDebugEnabled()) {
log.debug("Could not set field " + field.getName()
+ " to null in class " + clazz.getName(), t);
}
}
}
}
} catch (Throwable t) {
if (log.isDebugEnabled()) {
log.debug("Could not clean fields for class " + clazz.getName(), t);
}
}
}
}
}
// Clear the IntrospectionUtils cache.
IntrospectionUtils.clear();
// Clear the classloader reference in common-logging
org.apache.juli.logging.LogFactory.release(this);
// Clear the classloader reference in the VM's bean introspector
java.beans.Introspector.flushCaches();
}
protected void nullInstance(Object instance) {
if (instance == null) {
return;
}
Field[] fields = instance.getClass().getDeclaredFields();
for (int i = 0; i < fields.length; i++) {
Field field = fields[i];
int mods = field.getModifiers();
if (field.getType().isPrimitive()
|| (field.getName().indexOf("$") != -1)) {
continue;
}
try {
field.setAccessible(true);
if (Modifier.isStatic(mods) && Modifier.isFinal(mods)) {
// Doing something recursively is too risky
continue;
} else {
Object value = field.get(instance);
if (null != value) {
Class valueClass = value.getClass();
if (!loadedByThisOrChild(valueClass)) {
if (log.isDebugEnabled()) {
log.debug("Not setting field " + field.getName() +
" to null in object of class " +
instance.getClass().getName() +
" because the referenced object was of type " +
valueClass.getName() +
" which was not loaded by this WebappClassLoader.");
}
} else {
field.set(instance, null);
if (log.isDebugEnabled()) {
log.debug("Set field " + field.getName()
+ " to null in class " + instance.getClass().getName());
}
}
}
}
} catch (Throwable t) {
if (log.isDebugEnabled()) {
log.debug("Could not set field " + field.getName()
+ " to null in object instance of class "
+ instance.getClass().getName(), t);
}
}
}
}
/**
* Determine whether a class was loaded by this class loader or one of
* its child class loaders.
*/
protected boolean loadedByThisOrChild(Class clazz)
{
boolean result = false;
for (ClassLoader classLoader = clazz.getClassLoader();
null != classLoader; classLoader = classLoader.getParent()) {
if (classLoader.equals(this)) {
result = true;
break;
}
}
return result;
}
/**
* Used to periodically signal to the classloader to release JAR resources.
*/
protected boolean openJARs() {
if (started && (jarFiles.length > 0)) {
lastJarAccessed = System.currentTimeMillis();
if (jarFiles[0] == null) {
for (int i = 0; i < jarFiles.length; i++) {
try {
jarFiles[i] = new JarFile(jarRealFiles[i]);
} catch (IOException e) {
if (log.isDebugEnabled()) {
log.debug("Failed to open JAR", e);
}
return false;
}
}
}
}
return true;
}
/**
* Find specified class in local repositories.
*
* @return the loaded class, or null if the class isn't found
*/
protected Class findClassInternal(String name)
throws ClassNotFoundException {
if (!validate(name))
throw new ClassNotFoundException(name);
String tempPath = name.replace('.', '/');
String classPath = tempPath + ".class";
ResourceEntry entry = null;
entry = findResourceInternal(name, classPath);
if (entry == null)
throw new ClassNotFoundException(name);
Class clazz = entry.loadedClass;
if (clazz != null)
return clazz;
synchronized (entry) {
if (entry.binaryContent == null && entry.loadedClass == null)
throw new ClassNotFoundException(name);
// Looking up the package
String packageName = null;
int pos = name.lastIndexOf('.');
if (pos != -1)
packageName = name.substring(0, pos);
Package pkg = null;
if (packageName != null) {
synchronized (this) {
pkg = getPackage(packageName);
// Define the package (if null)
if (pkg == null) {
if (entry.manifest == null) {
definePackage(packageName, null, null, null, null,
null, null, null);
} else {
definePackage(packageName, entry.manifest,
entry.codeBase);
}
}
}
}
if (securityManager != null) {
// Checking sealing
if (pkg != null) {
boolean sealCheck = true;
if (pkg.isSealed()) {
sealCheck = pkg.isSealed(entry.codeBase);
} else {
sealCheck = (entry.manifest == null)
|| !isPackageSealed(packageName, entry.manifest);
}
if (!sealCheck)
throw new SecurityException
("Sealing violation loading " + name + " : Package "
+ packageName + " is sealed.");
}
}
if (entry.loadedClass == null) {
clazz = defineClass(name, entry.binaryContent, 0,
entry.binaryContent.length,
new CodeSource(entry.codeBase, entry.certificates));
entry.loadedClass = clazz;
entry.binaryContent = null;
entry.source = null;
entry.codeBase = null;
entry.manifest = null;
entry.certificates = null;
} else {
clazz = entry.loadedClass;
}
}
return clazz;
}
/**
* Find specified resource in local repositories. This block
* will execute under an AccessControl.doPrivilege block.
*
* @return the loaded resource, or null if the resource isn't found
*/
protected ResourceEntry findResourceInternal(File file, String path){
ResourceEntry entry = new ResourceEntry();
try {
entry.source = getURI(new File(file, path));
entry.codeBase = getURL(new File(file, path), false);
} catch (MalformedURLException e) {
return null;
}
return entry;
}
/**
* Find specified resource in local repositories.
*
* @return the loaded resource, or null if the resource isn't found
*/
protected ResourceEntry findResourceInternal(String name, String path) {
if (!started) {
log.info(sm.getString("webappClassLoader.stopped", name));
return null;
}
if ((name == null) || (path == null))
return null;
ResourceEntry entry = (ResourceEntry) resourceEntries.get(name);
if (entry != null)
return entry;
int contentLength = -1;
InputStream binaryStream = null;
int jarFilesLength = jarFiles.length;
int repositoriesLength = repositories.length;
int i;
Resource resource = null;
boolean fileNeedConvert = false;
for (i = 0; (entry == null) && (i < repositoriesLength); i++) {
try {
String fullPath = repositories[i] + path;
Object lookupResult = resources.lookup(fullPath);
if (lookupResult instanceof Resource) {
resource = (Resource) lookupResult;
}
// Note : Not getting an exception here means the resource was
// found
if (securityManager != null) {
PrivilegedAction dp =
new PrivilegedFindResource(files[i], path);
entry = (ResourceEntry)AccessController.doPrivileged(dp);
} else {
entry = findResourceInternal(files[i], path);
}
ResourceAttributes attributes =
(ResourceAttributes) resources.getAttributes(fullPath);
contentLength = (int) attributes.getContentLength();
entry.lastModified = attributes.getLastModified();
if (resource != null) {
try {
binaryStream = resource.streamContent();
} catch (IOException e) {
return null;
}
if (needConvert) {
if (path.endsWith(".properties")) {
fileNeedConvert = true;
}
}
// Register the full path for modification checking
// Note: Only syncing on a 'constant' object is needed
synchronized (allPermission) {
int j;
long[] result2 =
new long[lastModifiedDates.length + 1];
for (j = 0; j < lastModifiedDates.length; j++) {
result2[j] = lastModifiedDates[j];
}
result2[lastModifiedDates.length] = entry.lastModified;
lastModifiedDates = result2;
String[] result = new String[paths.length + 1];
for (j = 0; j < paths.length; j++) {
result[j] = paths[j];
}
result[paths.length] = fullPath;
paths = result;
}
}
} catch (NamingException e) {
}
}
if ((entry == null) && (notFoundResources.containsKey(name)))
return null;
JarEntry jarEntry = null;
synchronized (jarFiles) {
if (!ope
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -