I\'m aware that this question has been asked before:
How to use URLClassLoader to load a *.class file?
However I don\'t really understand due to the lack of
Your _sHashFunctionFilePath
needs to have the package name of the target class removed from it, so the ClassLoader will look in _sHashFunctionFilePath
+ package.name
+ HashFunction.class
as the path to the file. If you don't do that, the ClassLoader won't be able to find the file.
So if the target class is my.great.HashFunction
in HashFunction.class
, then it needs to be in a directory called my/great/
if you want to use URLClassLoader. Then, you'd use /path/to
as the file:///
URL for your URLClassLoader if the .class file was actually found in /path/to/my/great/HashFunction.class
.
In the directory /home/shackle/somedir/classes/pkg
I have a file Test.class created from a java file with package pkg;
eg :
package pkg;
public class Test {
public String toString() {
return "secret_string";
}
}
Then I load it with :
System.out.println(new URLClassLoader(
new URL[]{new File("/home/shackle/somedir/classes").toURI().toURL()}
).loadClass("pkg.Test").newInstance().toString());
Notice that I do not put the pkg/Test in the URL string but the load class argument has the pkg. prefix.
You can get the class name directly from the file like this:
Class clsReaderClss = ClassLoader.getSystemClassLoader().loadClass("jdk.internal.org.objectweb.asm.ClassReader");
System.out.println("clsReaderClss = " + clsReaderClss);
Constructor con = clsReaderClss.getConstructor(InputStream.class);
Object reader = con.newInstance(new FileInputStream(directFile));
Method m = clsReaderClss.getMethod("getClassName");
String name = m.invoke(reader).toString().replace('/', '.');
System.out.println("name = " + name);
An alternative that doesn't require access to internal classes.
String pathToClassFile = "/home/shackle/somedir/classes/pkg/Test.class";
ProcessBuilder pb = new ProcessBuilder("javap",pathToClassFile);
Process p = pb.start();
String classname = null;
try(BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()))) {
String line;
while(null != (line = br.readLine())) {
if(line.startsWith("public class")) {
classname = line.split(" ")[2];
break;
}
}
}
System.out.println("classname = " + classname);
Class can then be loaded with:
String pathToPackageBase = pathToClassFile.substring(0, pathToClassFile.length() - (classname + ".class").length());
System.out.println("pathToPackagBase = " + pathToPackageBase);
Class clss = new URLClassLoader(
new URL[]{new File(pathToPackageBase).toURI().toURL()}
).loadClass(classname);
System.out.println(clss.newInstance().toString());