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());