问题: 当我拥有一个类X的实例我怎么在运行的时候实时找出它的类的物理所在? 在我给你答案之前我必须指出如果你坚持养成一个好习惯编程序时总是考虑与硬盘位置无关那么你的java学习将会进展的很顺利当你要装载资源的时候比如一些属性和配置文件尽可能的使用ResourceBundlegetBundle()而不是使用javautilFile除非真的是必须这样这样做不仅有利于你的JEE应用开发而且越到后来你就越会发现我怎么有那么多东西要装载?这个时候你就会觉得这个方法确实给你带来了方便 尽管如此追寻到class的根源有时候在程序测试和debug的时候会很有用由于这个想法我给出了一种很有帮助的方法能够替我们完成这个任务这些所有都是基于jse的api的 /** * Given a Class object attempts to find its class location [returns null * if no such definition can be found] Use for testing/debugging only * * @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 = clsgetName ()replace ( /ncat (class); final ProtectionDomain pd = clsgetProtectionDomain (); // javalangClass contract does not specify if pd can ever be null; // it is not the case for Suns implementations but guard against null // just in case: if (pd != null) { final CodeSource cs = pdgetCodeSource (); // cs can be null depending on the classloader behavior: if (cs != null) result = csgetLocation (); if (result != null) { // Convert a code source location into a full class file location // for some common cases: if (fileequals (resultgetProtocol ())) { try { if (resulttoExternalForm ()endsWith (jar) || resulttoExternalForm ()endsWith (zip)) result = new URL (jar:ncat (resulttoExternalForm ()) ncat(!/ncat (clsAsResource)); else if (new File (resultgetFile ())isDirectory ()) result = new URL (result clsAsResource); } catch (MalformedURLException ignore) {} } } } if (result == null) { // Try to find cls definition as a resource; this is not // document.d to be legal but Suns implementations seem to //allow this: final ClassLoader clsLoader = clsgetClassLoader (); result = clsLoader != null ? clsLoadergetResource (clsAsResource) : ClassLoadergetSystemResource (clsAsResource); } return result; } 你最好通过这个类的ProtectionDomain方法来获得这个类的代码文件来源以及url地址然而有一个问题就是 ClassgetProtectionDomain()似乎并不会返回一个null值在api里也似乎是这么说的 但是ClassgetProtectionDomain()并不一定就会返回一个有效的url值所以我们在后面通过判断result来得知是否有效 所有的细节都是classloader的动作我们知道classloader就是装载和定义我们的class的通过javalangClassLoaderdefineClass()—个参数而且ProtectionDomain参数不能为空我们可以建立需要的类以及相关受保护的区域 一般来讲 URLClassLoader以及相关的扩展一般都会遵循这个规则但是并非所有自定义的classloader都会保证自动实现它 如果第一步失败了你可以试试通过getResource()来获得class结尾的文件的位置Java规范里面并没有详细说明这样作是否允许:因为任何代码都能通过URLS读取整个类的定义是一个潜在的安全漏洞有一些jvm已经禁止通过getResource()来装载class文件然而sun的jdk却是通过这个途径来装载类的这似乎传递了某些合法的信息 最后千万不要忘记不要去寻找任何不存在的东西一个javalangClass类是不需要真正存在一个class文件的一个明显的例子就是动态代理类:它的字节码定义是在运行的时候合成的 对于它getClassLocation()将会返回null 将来jee里面将更多的依靠这种运行时构造的方法因为这些原因还有就是虚拟机各自都不同我提供的这种方法你最好只是用来做测试和debug |