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?
This question is related to
java
classpath
classloader
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()
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 )
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.
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();
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 )
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
getClass().getProtectionDomain().getCodeSource().getLocation();
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 )
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()
getClass().getProtectionDomain().getCodeSource().getLocation();
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";
}
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!
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
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!
Simple way:
System.out.println(java.lang.String.class.getResource(String.class.getSimpleName()+".class"));
Out Example:
jar:file:/D:/Java/jdk1.8/jre/lib/rt.jar!/java/lang/String.class
Or
String obj = "simple test"; System.out.println(obj.getClass().getResource(obj.getClass().getSimpleName()+".class"));
Out Example:
jar:file:/D:/Java/jdk1.8/jre/lib/rt.jar!/java/lang/String.class
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.
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
Simple way:
System.out.println(java.lang.String.class.getResource(String.class.getSimpleName()+".class"));
Out Example:
jar:file:/D:/Java/jdk1.8/jre/lib/rt.jar!/java/lang/String.class
Or
String obj = "simple test"; System.out.println(obj.getClass().getResource(obj.getClass().getSimpleName()+".class"));
Out Example:
jar:file:/D:/Java/jdk1.8/jre/lib/rt.jar!/java/lang/String.class
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.
getClass().getProtectionDomain().getCodeSource().getLocation();
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
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()
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
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()
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";
}
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.
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
getClass().getProtectionDomain().getCodeSource().getLocation();
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();
Source: Stackoverflow.com