Using URLClassLoader to load .class file

前端 未结 2 857
余生分开走
余生分开走 2021-01-20 13:35

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

相关标签:
2条回答
  • 2021-01-20 14:11

    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.

    0 讨论(0)
  • 2021-01-20 14:12

    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());
    
    0 讨论(0)
提交回复
热议问题