`
budairenqin
  • 浏览: 199322 次
  • 性别: 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 ...

    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源...

    Spring.net框架

    string rootPath = Path.GetDirectoryName(Assembly.GetEntryAssembly().Location) + Path.DirectorySeparatorChar; ConfigInfo cfgInfo = (ConfigInfo)ConfigurationSettings.GetConfig("IocInCSharp/objects")...

    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 ...

    网络架构师148讲视频课程

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

    VB.NET Developer's Guide(4574).pdf

    programs at runtime. They allow us to see the values of variables and the values of properties on objects. In addition to being able to view these values, you can also assign new values. 153_VBnet_TOC...

    springmybatis

    以前曾经用过ibatis,这是mybatis的前身,当时在做项目时,感觉很不错,比hibernate灵活。性能也比hibernate好。而且也比较轻量级,因为当时在项目中,没来的及做很很多笔记。后来项目结束了,我也没写总结文档。已经...

    新版Android开发教程.rar

    � 采用了对有限内存、电池和 CPU 优化过的虚拟机 Dalvik , Android 的运行速度比想象的要快很多。 � 运营商(中国移动等)的大力支持,产业链条的热捧。 � 良好的盈利模式( 3/7 开),产业链条的各方:运营商、...

    基于MyEclipse搭建maven+springmvc整合图文教程(含源码0

    3. runtime,只在运行时使用,如JDBC驱动,适用运行和测试阶段。 4. test,只在测试时使用,用于编译和运行测试代码。不会随项目发布。 5. system,类似provided,需要显式提供包含依赖的jar,Maven不会在 ...

    ICS delphixe10源码版

    to ease support of multiple versions of Delphi and platforms, and to ease location of similar sample projects. Please don't install V8 over an existing V7 installation, it will be a mess of old and ...

    fso浏览54646465465464564

    '本程序只供在需要特别处理服务器文件时使用,严禁用于非法目的 '由于非正当使用本程序而造成的一切后果及责任自负 '版本: v0.12 '作者: 河北科技大学 rssn | Risingsun,Hebust 'QQ: 126027268 'E-mail: rssn@163....

    spring-boot-reference.pdf

    14.2. Locating the Main Application Class 15. Configuration Classes 15.1. Importing Additional Configuration Classes 15.2. Importing XML Configuration 16. Auto-configuration 16.1. Gradually Replacing ...

    Bochs - The cross platform IA-32 (x86) emulator

    class, optional commit support on Bochs exit, save/restore file attributes, 1.44 MB floppy support, set file modification date/time - converted the complete hdimage stuff to the new 'hdimage' ...

    C#编程实例代码集合

    Example012-在运行时更新状态栏信息 Example013-无标题窗体的拖动 Example014-设置应用程序的图标 Example015-共享菜单项 Example016-动态设置窗体的光标 Example017-自己绘制菜单 Example018-向窗体的系统菜单添加...

    [精典材料]Patran的PCL用户手册.doc

    Debugging Runtime Errors 64 Accessing PCL Functions 66 From The Command Line 66 From Any MSC.Patran Form 67 PCL Functions with Field Variables 68 MSC.Patran Built-In Functions 69 Naming Conventions ...

    php.ini-development

    at runtime. Currently, [PATH=] and [HOST=] sections only work under ; CGI/FastCGI. ; http://php.net/ini.sections ; Directives are specified using the following syntax: ; directive = value ; ...

Global site tag (gtag.js) - Google Analytics