确定一个类来自哪个JAR文件

我现在不在IDE的前面,只是看API规范。

CodeSource src = MyClass.class.getProtectionDomain().getCodeSource(); if (src != null) { URL jar = src.getLocation(); } 

我想确定一个类来自哪个JAR文件。 这是做到这一点的方法吗?

是。 它适用于除bootstrap classloader加载的类以外的所有类。 另一种方式来确定是:

 Class klass = String.class; URL location = klass.getResource('/' + klass.getName().replace('.', '/') + ".class"); 

由于notnoop指出getProtectionDomain().getCodeSource().getLocation()方法返回类文件本身的位置。 例如:

 jar:file:/jdk/jre/lib/rt.jar!/java/lang/String.class file:/projects/classes/pkg/MyClass$1.class 

klass.getResource()方法返回jar文件或CLASSPATH的位置

 file:/Users/home/java/libs/ejb3-persistence-1.0.2.GA.jar file:/projects/classes 

从Lombok Patcher LiveInjector.java检出LiveInjector.findPathJar() 。 请注意,在特殊情况下,文件实际上并不在一个jar文件中,您可能需要更改该文件。

 /** * If the provided class has been loaded from a jar file that is on the local file system, will find the absolute path to that jar file. * * @param context The jar file that contained the class file that represents this class will be found. Specify {@code null} to let {@code LiveInjector} * find its own jar. * @throws IllegalStateException If the specified class was loaded from a directory or in some other way (such as via HTTP, from a database, or some * other custom classloading device). */ public static String findPathJar(Class<?> context) throws IllegalStateException { if (context == null) context = LiveInjector.class; String rawName = context.getName(); String classFileName; /* rawName is something like package.name.ContainingClass$ClassName. We need to turn this into ContainingClass$ClassName.class. */ { int idx = rawName.lastIndexOf('.'); classFileName = (idx == -1 ? rawName : rawName.substring(idx+1)) + ".class"; } String uri = context.getResource(classFileName).toString(); if (uri.startsWith("file:")) throw new IllegalStateException("This class has been loaded from a directory and not from a jar file."); if (!uri.startsWith("jar:file:")) { int idx = uri.indexOf(':'); String protocol = idx == -1 ? "(unknown)" : uri.substring(0, idx); throw new IllegalStateException("This class has been loaded remotely via the " + protocol + " protocol. Only loading from a jar on the local file system is supported."); } int idx = uri.indexOf('!'); //As far as I know, the if statement below can't ever trigger, so it's more of a sanity check thing. if (idx == -1) throw new IllegalStateException("You appear to have loaded this class from a local jar file, but I can't make sense of the URL!"); try { String fileName = URLDecoder.decode(uri.substring("jar:file:".length(), idx), Charset.defaultCharset().name()); return new File(fileName).getAbsolutePath(); } catch (UnsupportedEncodingException e) { throw new InternalError("default charset doesn't exist. Your VM is borked."); } } 
 private String resourceLookup(String lookupResourceName) { try { if (lookupResourceName == null || lookupResourceName.length()==0) { return ""; } // "/java/lang/String.class" // Check if entered data was in java class name format if (lookupResourceName.indexOf("/")==-1) { lookupResourceName = lookupResourceName.replaceAll("[.]", "/"); lookupResourceName = "/" + lookupResourceName + ".class"; } URL url = this.getClass().getResource(lookupResourceName); if (url == null) { return("Unable to locate resource "+ lookupResourceName); } String resourceUrl = url.toExternalForm(); Pattern pattern = Pattern.compile("(zip:|jar:file:/)(.*)!/(.*)", Pattern.CASE_INSENSITIVE); String jarFilename = null; String resourceFilename = null; Matcher m = pattern.matcher(resourceUrl); if (m.find()) { jarFilename = m.group(2); resourceFilename = m.group(3); } else { return "Unable to parse URL: "+ resourceUrl; } if (!jarFilename.startsWith("C:") ){ jarFilename = "/"+jarFilename; // make absolute path on Linux } File file = new File(jarFilename); Long jarSize=null; Date jarDate=null; Long resourceSize=null; Date resourceDate=null; if (file.exists() && file.isFile()) { jarSize = file.length(); jarDate = new Date(file.lastModified()); try { JarFile jarFile = new JarFile(file, false); ZipEntry entry = jarFile.getEntry(resourceFilename); resourceSize = entry.getSize(); resourceDate = new Date(entry.getTime()); } catch (Throwable e) { return ("Unable to open JAR" + jarFilename + " "+resourceUrl +"\n"+e.getMessage()); } return "\nresource: "+resourceFilename+"\njar: "+jarFilename + " \nJarSize: " +jarSize+" \nJarDate: " +jarDate.toString()+" \nresourceSize: " +resourceSize+" \nresourceDate: " +resourceDate.toString()+"\n"; } else { return("Unable to load jar:" + jarFilename+ " \nUrl: " +resourceUrl); } } catch (Exception e){ return e.getMessage(); } }