From d8c8d2bb1b8ddbeb0d11fae9ebbea95d73fa2b27 Mon Sep 17 00:00:00 2001 From: aclement Date: Tue, 27 May 2008 18:46:34 +0000 Subject: [PATCH] 210470: preventing weaver leaks: get control of the classloader references in Bcel --- .../bcel/util/ClassLoaderReference.java | 67 +++++++++++++++++ .../bcel/util/ClassLoaderRepository.java | 23 +++--- .../util/DefaultClassLoaderReference.java | 75 +++++++++++++++++++ .../util/NonCachingClassLoaderRepository.java | 16 ++-- 4 files changed, 165 insertions(+), 16 deletions(-) create mode 100644 bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderReference.java create mode 100644 bcel-builder/src/org/aspectj/apache/bcel/util/DefaultClassLoaderReference.java diff --git a/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderReference.java b/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderReference.java new file mode 100644 index 000000000..f6fcbf5f8 --- /dev/null +++ b/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderReference.java @@ -0,0 +1,67 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.aspectj.apache.bcel.util; + +/** + * Implementors should provide access to a ClassLoader instance. The reference can be passed around and cached + * but will not cause the code that caches it to have a hard reference to the classloader, so it is easier + * to manage the classloader instance. The default implementation will just wrap a classloader object but + * more sophisticated implementations could keep a WeakReference to the loader. + */ +public interface ClassLoaderReference { + + java.lang.ClassLoader getClassLoader(); + +} diff --git a/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderRepository.java b/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderRepository.java index f7cdee26b..74f3d47a2 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderRepository.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/util/ClassLoaderRepository.java @@ -80,13 +80,13 @@ import org.aspectj.apache.bcel.classfile.JavaClass; * * @see org.aspectj.apache.bcel.Repository * - * @version $Id: ClassLoaderRepository.java,v 1.9 2006/10/12 19:58:18 aclement Exp $ + * @version $Id: ClassLoaderRepository.java,v 1.10 2008/05/27 18:46:34 aclement Exp $ * @author M. Dahm * @author David Dixon-Peugh */ public class ClassLoaderRepository implements Repository { private static java.lang.ClassLoader bootClassLoader = null; - private java.lang.ClassLoader loader; + private ClassLoaderReference loaderRef; // Choice of cache... private WeakHashMap /**/localCache = new WeakHashMap(); @@ -107,9 +107,13 @@ public class ClassLoaderRepository implements Repository { private int cacheHitsLocal = 0; private int missLocalEvicted = 0; // Misses in local cache access due to reference GC - public ClassLoaderRepository( java.lang.ClassLoader loader ) { - this.loader = (loader != null) ? loader : getBootClassLoader(); - } + public ClassLoaderRepository(java.lang.ClassLoader loader) { + this.loaderRef = new DefaultClassLoaderReference((loader != null) ? loader : getBootClassLoader()); + } + + public ClassLoaderRepository(ClassLoaderReference loaderRef) { + this.loaderRef = loaderRef; + } private static synchronized java.lang.ClassLoader getBootClassLoader() { if (bootClassLoader == null) { @@ -246,7 +250,7 @@ public class ClassLoaderRepository implements Repository { URL url = (URL)nameMap.get(className); if (url==null) { String classFile = className.replace('.', '/'); - url = loader.getResource( classFile + ".class" ); + url = loaderRef.getClassLoader().getResource(classFile + ".class"); nameMap.put(className, url); } return url; @@ -280,7 +284,7 @@ public class ClassLoaderRepository implements Repository { try { // Load it String classFile = className.replace('.', '/'); - InputStream is = (useSharedCache?url.openStream():loader.getResourceAsStream( classFile + ".class" )); + InputStream is = (useSharedCache ? url.openStream() : loaderRef.getClassLoader().getResourceAsStream(classFile + ".class")); if (is == null) { throw new ClassNotFoundException(className + " not found "+(url==null?"":"- using url "+url)); } @@ -298,10 +302,9 @@ public class ClassLoaderRepository implements Repository { } } - /** - * Produce a report on cache usage. - */ + * Produce a report on cache usage. + */ public String report() { StringBuffer sb = new StringBuffer(); sb.append("BCEL repository report."); diff --git a/bcel-builder/src/org/aspectj/apache/bcel/util/DefaultClassLoaderReference.java b/bcel-builder/src/org/aspectj/apache/bcel/util/DefaultClassLoaderReference.java new file mode 100644 index 000000000..259991308 --- /dev/null +++ b/bcel-builder/src/org/aspectj/apache/bcel/util/DefaultClassLoaderReference.java @@ -0,0 +1,75 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2001 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, + * if any, must include the following acknowledgment: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgment may appear in the software itself, + * if and wherever such third-party acknowledgments normally appear. + * + * 4. The names "Apache" and "Apache Software Foundation" and + * "Apache BCEL" must not be used to endorse or promote products + * derived from this software without prior written permission. For + * written permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache", + * "Apache BCEL", nor may "Apache" appear in their name, without + * prior written permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + */ + +package org.aspectj.apache.bcel.util; + +/** + * Simplistic ClassLoaderReference that merely delegates to a classloader. More sophisticated ones could allow for the + * loader to be weakly referenced. + * + * @author Andy Clement + */ +public class DefaultClassLoaderReference implements ClassLoaderReference { + + private java.lang.ClassLoader loader; + + public DefaultClassLoaderReference(java.lang.ClassLoader classLoader) { + this.loader = classLoader; + } + + public java.lang.ClassLoader getClassLoader() { + return loader; + } + +} diff --git a/bcel-builder/src/org/aspectj/apache/bcel/util/NonCachingClassLoaderRepository.java b/bcel-builder/src/org/aspectj/apache/bcel/util/NonCachingClassLoaderRepository.java index 20c82006d..d41188cf1 100644 --- a/bcel-builder/src/org/aspectj/apache/bcel/util/NonCachingClassLoaderRepository.java +++ b/bcel-builder/src/org/aspectj/apache/bcel/util/NonCachingClassLoaderRepository.java @@ -72,7 +72,7 @@ import org.aspectj.apache.bcel.classfile.JavaClass; * * @see org.aspectj.apache.bcel.Repository * - * @version $Id: NonCachingClassLoaderRepository.java,v 1.1 2006/10/12 19:58:18 aclement Exp $ + * @version $Id: NonCachingClassLoaderRepository.java,v 1.2 2008/05/27 18:46:34 aclement Exp $ * @author M. Dahm * @author David Dixon-Peugh * @@ -82,13 +82,17 @@ public class NonCachingClassLoaderRepository { private static java.lang.ClassLoader bootClassLoader = null; - private java.lang.ClassLoader loader; + private ClassLoaderReference loaderRef; private WeakHashMap loadedClasses = new WeakHashMap(); // CLASSNAME X JAVACLASS - public NonCachingClassLoaderRepository( java.lang.ClassLoader loader ) { - this.loader = (loader != null) ? loader : getBootClassLoader(); - } + public NonCachingClassLoaderRepository(java.lang.ClassLoader loader) { + this.loaderRef = new DefaultClassLoaderReference((loader != null) ? loader : getBootClassLoader()); + } + + public NonCachingClassLoaderRepository(ClassLoaderReference loaderRef) { + this.loaderRef = loaderRef; + } private static synchronized java.lang.ClassLoader getBootClassLoader() { if (bootClassLoader == null) { @@ -137,7 +141,7 @@ public class NonCachingClassLoaderRepository try { InputStream is = - loader.getResourceAsStream( classFile + ".class" ); + loaderRef.getClassLoader().getResourceAsStream(classFile + ".class"); if(is == null) { throw new ClassNotFoundException(className + " not found."); -- 2.39.5