问题
Does anyone know how to programmaticly find out where the java classloader actually loads the class from?
I often work on large projects where the classpath gets very long and manual searching is not really an option. I recently had a problem where the classloader was loading an incorrect version of a class because it was on the classpath in two different places.
So how can I get the classloader to tell me where on disk the actual class file is coming from?
Edit: What about if the classloader actually fails to load the class due to a version mismatch (or something else), is there anyway we could find out what file its trying to read before it reads it?
回答1:
Here's an example:
package foo;
public class Test
{
public static void main(String[] args)
{
ClassLoader loader = Test.class.getClassLoader();
System.out.println(loader.getResource("foo/Test.class"));
}
}
This printed out:
file:/C:/Users/Jon/Test/foo/Test.class
回答2:
Another way to find out where a class is loaded from (without manipulating the source) is to start the Java VM with the option: -verbose:class
回答3:
getClass().getProtectionDomain().getCodeSource().getLocation();
回答4:
This is what we use:
public static String getClassResource(Class<?> klass) {
return klass.getClassLoader().getResource(
klass.getName().replace('.', '/') + ".class").toString();
}
This will work depending on the ClassLoader implementation:
getClass().getProtectionDomain().getCodeSource().getLocation()
回答5:
Jon's version fails when the object's ClassLoader is registered as null which seems to imply that it was loaded by the Boot ClassLoader.
This method deals with that issue:
public static String whereFrom(Object o) {
if ( o == null ) {
return null;
}
Class<?> c = o.getClass();
ClassLoader loader = c.getClassLoader();
if ( loader == null ) {
// Try the bootstrap classloader - obtained from the ultimate parent of the System Class Loader.
loader = ClassLoader.getSystemClassLoader();
while ( loader != null && loader.getParent() != null ) {
loader = loader.getParent();
}
}
if (loader != null) {
String name = c.getCanonicalName();
URL resource = loader.getResource(name.replace(".", "/") + ".class");
if ( resource != null ) {
return resource.toString();
}
}
return "Unknown";
}
回答6:
Edit just 1st line: Main.class
Class<?> c = Main.class;
String path = c.getResource(c.getSimpleName() + ".class").getPath().replace(c.getSimpleName() + ".class", "");
System.out.println(path);
Output:
/C:/Users/Test/bin/
Maybe bad style but works fine!
回答7:
Take a look at this similar question. Tool to discover same class..
I think the most relevant obstacle is if you have a custom classloader ( loading from a db or ldap )
回答8:
Typically, we don't what to use hardcoding. We can get className first, and then use ClassLoader to get the class URL.
String className = MyClass.class.getName().replace(".", "/")+".class";
URL classUrl = MyClass.class.getClassLoader().getResource(className);
String fullPath = classUrl==null ? null : classUrl.getPath();
回答9:
This approach works for both files and jars:
Class clazz = Class.forName(nameOfClassYouWant);
URL resourceUrl = clazz.getResource("/" + clazz.getCanonicalName().replace(".", "/") + ".class");
InputStream classStream = resourceUrl.openStream(); // load the bytecode, if you wish
回答10:
Assuming that you're working with a class named MyClass, the following should work:
MyClass.class.getClassLoader();
Whether or not you can get the on-disk location of the .class file is dependent on the classloader itself. For example, if you're using something like BCEL, a certain class may not even have an on-disk representation.
来源:https://stackoverflow.com/questions/227486/find-where-java-class-is-loaded-from