Using URLClassLoader to load .class file

前端 未结 2 859
余生分开走
余生分开走 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: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());
    

提交回复
热议问题