首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > 软件开发 >

运行时(at runtime)找出Class对象的classfile location

2012-09-29 
运行时(at runtime)找到Class对象的classfile location以下代码参考http://www.javaworld.com/javaworld/j

运行时(at runtime)找到Class对象的classfile location
以下代码参考
http://www.javaworld.com/javaworld/javaqa/2003-07/01-qa-0711-classsrc.html

在项目中经常会碰到jar包冲突的情况,有时候想知道jvm到底是加载了哪个jar里面的对应类,下面这段代码就要派上用场鸟,呼呼
代码清晰易懂,我就不多做解释了,记录下来留着自己以后用

    /**     * Given a Class<?> object, attempts to find its .class location [returns     * null if no such definiton could be found].     *      * @return URL that points to the class definition [null if not found]     */    public static URL getClassLocation(final Class<?> cls) {        if (cls == null)            throw new IllegalArgumentException("null input: cls");        URL result = null;        final String clsAsResource = cls.getName().replace('.', '/').concat(".class");        final ProtectionDomain pd = cls.getProtectionDomain();        // java.lang.Class<?> contract does not specify if 'pd' can ever be        // null;        // it is not the case for Sun's implementations, but guard against null        // just in case:        if (pd != null) {            final CodeSource cs = pd.getCodeSource();            // 'cs' can be null depending on the classloader behavior:            if (cs != null)                result = cs.getLocation();            if (result != null) {                // convert a code source location into a full class file                // location                // for some common cases:                if ("file".equals(result.getProtocol())) {                    try {                        if (result.toExternalForm().endsWith(".jar") || result.toExternalForm().endsWith(".zip"))                            result = new URL("jar:".concat(result.toExternalForm()).concat("!/").concat(clsAsResource));                        else if (new File(result.getFile()).isDirectory())                            result = new URL(result, clsAsResource);                    } catch (MalformedURLException ignore) { }                }            }        }        if (result == null) {            // try to find 'cls' definition as a resource; this is not            // documented to be legal but Sun's implementations seem to allow            // this:            final ClassLoader clsLoader = cls.getClassLoader();            result = clsLoader != null ? clsLoader.getResource(clsAsResource) : ClassLoader.getSystemResource(clsAsResource);        }        return result;    }


http://www.nakov.com/wp-content/uploads/2008/08/classscopejava.html
这个ClassScope类提供了除getClassLocation方法外其他的一些常用方法
import java.io.File;import java.lang.reflect.Field;import java.net.MalformedURLException;import java.net.URL;import java.security.CodeSource;import java.security.ProtectionDomain;import java.util.Arrays;import java.util.HashSet;import java.util.LinkedList;import java.util.List;import java.util.Set;import java.util.Vector;/** * A simple static API for listing classes loaded in a JVM. Based on * {@link #getClassLocation(Class)} from * http://www.javaworld.com/javaworld/javaqa/2003-07/01-qa-0711-classsrc.html * @author (C) <a href="http://www.javaworld.com/columns/jw-qna-index.shtml">Vlad Roubtsov</a>, 2003 */public class ClassScope {        private static final Class<?>[] EMPTY_CLASS_ARRAY = new Class<?>[0];    private static final Throwable CVF_FAILURE, CR_FAILURE; // set in <clinit>                static {        Throwable failure = null;        Field tempf = null;        try {            // this can fail if this is not a Sun-compatible JVM            // or if the security is too tight:            tempf = ClassLoader.class.getDeclaredField("classes");            if (tempf.getType() != Vector.class) {                throw new RuntimeException("not of type java.util.Vector: " + tempf.getType().getName());            }            tempf.setAccessible(true);        } catch (Throwable t) {            failure = t;        }                CLASSES_VECTOR_FIELD = tempf;        CVF_FAILURE = failure;        failure = null;        CallerResolver tempcr = null;                try {            // this can fail if the current SecurityManager does not allow            // RuntimePermission ("createSecurityManager"):            tempcr = new CallerResolver();        } catch (Throwable t) {            failure = t;        }        CALLER_RESOLVER = tempcr;        CR_FAILURE = failure;    }        /**     * Given a class loader instance, returns all classes currently loaded by     * that class loader.     *      * @param defining class loader to inspect [may not be null]     * @return Class array such that every Class has 'loader' as its defining     *         class loader [never null, may be empty]     * @throws RuntimeException     *             if the "classes" field hack is not possible in this JRE     */    @SuppressWarnings("unchecked")    public static Class<?>[] getLoadedClasses(final ClassLoader loader) {        if (loader == null) {            throw new IllegalArgumentException("null input: loader");        }        if (CLASSES_VECTOR_FIELD == null) {            throw new RuntimeException("ClassScope::getLoadedClasses() cannot be used in this JRE", CVF_FAILURE);        }                try {            final Vector<Class<?>> classes = (Vector<Class<?>>) CLASSES_VECTOR_FIELD.get(loader);            if (classes == null)                return EMPTY_CLASS_ARRAY;            final Class<?>[] result;            // note: Vector is synchronized in Java 2, which helps us make            // the following into a safe critical section:            synchronized (classes) {                result = new Class<?>[classes.size()];                classes.toArray(result);            }            return result;        }        // this should not happen if <clinit> was successful:        catch (IllegalAccessException e) {            e.printStackTrace(System.out);            return EMPTY_CLASS_ARRAY;        }            }        /**     * A convenience multi-loader version of     * {@link #getLoadedClasses(ClassLoader)}.     *      * @param an array of defining class loaders to inspect [may not be null]     * @return Class<?> array [never null, may be empty]     * @throws RuntimeException     *             if the "classes" field hack is not possible in this JRE     */    public static Class<?>[] getLoadedClasses(final ClassLoader[] loaders) {        if (loaders == null)            throw new IllegalArgumentException("null input: loaders");        final List<Class<?>> resultList = new LinkedList<Class<?>>();        for (int l = 0; l < loaders.length; ++l) {            final ClassLoader loader = loaders[l];            if (loader != null) {                final Class<?>[] classes = getLoadedClasses(loaders[l]);                resultList.addAll(Arrays.asList(classes));            }        }        final Class<?>[] result = new Class<?>[resultList.size()];        resultList.toArray(result);        return result;    }        /**     * Returns the class loader set "relevant" to the calling class, as     * described in the article. Starting with the class that is the caller of     * this method, it collects all class loaders that are loaders for all     * classes on the call stack and their respective parent loaders.     *      * @return ClassLoader array [never null]     * @throws RuntimeException     *             if the caller context resolver could not be instantiated     */    public static ClassLoader[] getCallerClassLoaderTree() {        if (CALLER_RESOLVER == null)            throw new RuntimeException("Class<?>Scope::getCallerClassLoaderTree() cannot be used in this JRE", CR_FAILURE);        final Class<?>[] callContext = CALLER_RESOLVER.getClassContext();        final Set<ClassLoader> resultSet = new HashSet<ClassLoader>();        for (int c = 2; c < callContext.length; ++c) {            getClassLoaderTree(callContext[c], resultSet);        }        final ClassLoader[] result = new ClassLoader[resultSet.size()];        resultSet.toArray(result);        return result;    }        /**     * Given a Class<?> object, attempts to find its .class location [returns     * null if no such definiton could be found].     *      * @return URL that points to the class definition [null if not found]     */    public static URL getClassLocation(final Class<?> cls) {        if (cls == null)            throw new IllegalArgumentException("null input: cls");        URL result = null;        final String clsAsResource = cls.getName().replace('.', '/').concat(".class");        final ProtectionDomain pd = cls.getProtectionDomain();        // java.lang.Class<?> contract does not specify if 'pd' can ever be        // null;        // it is not the case for Sun's implementations, but guard against null        // just in case:        if (pd != null) {            final CodeSource cs = pd.getCodeSource();            // 'cs' can be null depending on the classloader behavior:            if (cs != null)                result = cs.getLocation();            if (result != null) {                // convert a code source location into a full class file                // location                // for some common cases:                if ("file".equals(result.getProtocol())) {                    try {                        if (result.toExternalForm().endsWith(".jar") || result.toExternalForm().endsWith(".zip"))                            result = new URL("jar:".concat(result.toExternalForm()).concat("!/").concat(clsAsResource));                        else if (new File(result.getFile()).isDirectory())                            result = new URL(result, clsAsResource);                    } catch (MalformedURLException ignore) { }                }            }        }        if (result == null) {            // try to find 'cls' definition as a resource; this is not            // documented to be legal but Sun's implementations seem to allow            // this:            final ClassLoader clsLoader = cls.getClassLoader();            result = clsLoader != null ? clsLoader.getResource(clsAsResource) : ClassLoader.getSystemResource(clsAsResource);        }        return result;    }        /**     * A helper class to get the call context. It subclasses SecurityManager to     * make getClassContext() accessible. An instance of CallerResolver only     * needs to be created, not installed as an actual security manager.     */    private static final class CallerResolver extends SecurityManager {        protected Class<?>[] getClassContext() {            return super.getClassContext();        }    } // end of nested class        private ClassScope() { } // this class is not extendible        private static void getClassLoaderTree(final Class<?> cls, final Set<ClassLoader> resultSet) {        if ((cls != null) && (resultSet != null)) {            for (ClassLoader loader = cls.getClassLoader(); loader != null; loader = loader.getParent()) {                resultSet.add(loader);            }        }    }        private static final Field CLASSES_VECTOR_FIELD;        // set in <clinit> [can be null]    private static final CallerResolver CALLER_RESOLVER;    // set in <clinit> [can be null]}

热点排行