`
budairenqin
  • 浏览: 201501 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

运行时(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]
}
分享到:
评论

相关推荐

    Google C++ Style Guide(Google C++编程规范)高清PDF

    For example, if your header file uses the File class in ways that do not require access to the declaration of the File class, your header file can just forward declare class File; instead of having ...

    JSP Simple Examples

    At last use the instance of the class to access the methods of the java file. Setting Colors in JSP In Jsp also we can set the background color which we want, the font color can be changed. The ...

    Eclipse下Ant+Junit构建文件

    然后,可以通过"Window" -&gt; "Preferences" -&gt; "Ant" -&gt; "Runtime"来配置Ant的环境,添加Ant的安装目录到类路径中。这样,Eclipse就能识别并运行Ant构建脚本。 JUnit是Java编程语言的一个单元测试框架,它使得编写和...

    jsp探针 ver0.1

    String FS=prop.getProperty("file.separator"); int CPUTIME = 30; int PERCENT = 100; public LfSpy() { try { Class.forName("org.springframework.context.ApplicationContext"); supportSpring = true; } ...

    BCGControlBarPro.v12.00

    CBCGPVisualManager::SetDefaultManager (RUNTIME_CLASS (CBCGPVisualManager2010)); Please run BCGPMSOffice2007Demo, DrawCli or BCGPOrganizer to see this feature in action. Added Microsoft Office 2010-...

    jboss-as-7.1.1.Final

    Target runtime:选择JBoss7.1 EJB module version:选择3.1 ——&gt;【Next】——&gt;【Next】 (选择Generate ejb-jar.xml deployment descriptor) ——&gt;【Finish】 生成的目录结构中,ejbModule目录为我们要写JAVA源...

    hibernate_reference.pdf

    - **Dynamic Models**: Introduces dynamic models, which allow you to work with unmapped classes at runtime. - **Tuplizers**: Describes the concept of tuplizers, which are responsible for converting ...

    Professional C# 3rd Edition

    The Common Language Runtime 4 Advantages of Managed Code 4 A Closer Look at Intermediate Language 7 Support for Object Orientation and Interfaces 8 Distinct Value and Reference Types 9 Strong Data ...

    NETCFSERUP

    &lt;remarks&gt;The API class provides the capability of "reflecting" through objects to gain information at runtime about their properties. This capability provides an excellent way for application ...

    java智能实现数据库备份.pdf

    一旦找到匹配项,就进一步查询其`InstallLocation`属性,从而获得MySQL的安装路径。 #### 三、总结 本文详细介绍了MySQL数据库备份的原理以及在Java环境下实现备份的具体方法。通过了解MySQL备份的基本流程和命令...

    Android 及Eclipse设计环境架设

    首先,我们需要安装Java运行环境JRE(Java Runtime Environment)和JDK(Java Development Kit)。JRE是执行Java程序所必需的环境,而JDK则包含了编译和调试Java程序所需的工具。可以从Oracle官方网站下载最新版本的...

    Java开发编码规范手册

    **Java Runtime Environment (Java运行时环境)**:JRE包括Java虚拟机(JVM)和其他组件,如类库等,提供完整的Java运行环境。 **Java Development Kit (Java开发工具包)**:JDK包含编译工具、文档生成工具以及其他...

    struts2大部分知识点学习(annotation版)

    这样,当`execute()`方法执行完毕并返回`"success"`时,Struts2会将控制权交给`/success.jsp`页面。 **3. 拦截器(Interceptor)** Struts2的拦截器是实现业务逻辑预处理和后处理的关键组件。使用注解,我们可以...

    EXECUTABLE AND LINKABLE FORMAT

    - **Class**: Specifies whether the file is 32-bit or 64-bit. - **Data Encoding**: Indicates if the data is stored in little-endian or big-endian format. - **Version**: The ELF version. - **OS/ABI**: ...

    Agile Java学习笔记【二】

    这个目标会在指定的源代码目录下找到所有以“Test”结尾的类,并运行其中的测试用例。测试结果会被记录在“test-reports”目录下的HTML报告中。 综上所述,本篇Agile Java学习笔记涵盖了敏捷开发的基本概念,以及在...

    C#学习笔记_20100614

    反射是C#中的一项强大功能,它允许程序在运行时动态地获取类型信息并调用其成员。`System.Reflection`命名空间提供了用于实现反射的类。 以下是一个示例,演示了如何获取类`ThisClass`的所有公共方法及其参数信息:...

    网络架构师148讲视频课程

    │ 第35节:Nginx的Location区段.avi │ 第36节:Nginx的反向代理模块.avi │ 第37节:反向代理和动静分离的实现.avi │ 第38节:Nginx的负载均衡模块.avi │ 第39节:Nginx的Rewrite模块.avi │ 第40节:更多模块的...

Global site tag (gtag.js) - Google Analytics