使用Java(和反射)进一步分析Java源代码



我尝试在Java6中分析Java源代码。ANTLR4在词法分析方面确实做得很好,但现在我想知道是否可以管理更高级的问题,例如列出继承方法。

我的想法(根据一些谷歌):

  1. 加载源文件
  2. 通过ToolProvider.getSystemJavaCompiler()获取系统编译器,通过run()将源代码编译成.class文件
  3. [也许?.class文件打包到.jar并以某种方式加载
  4. 使用Java反射分析编译后的类
  5. 删除.class文件
  6. 写入输出(例如继承的方法/字段等)
符号1456足够清晰,描述得很好。我相信nr. 2可以使用本教程解决。所以我的核心问题是nr. 3,因为我不知道如何加载.class文件并分析它们。

任何想法?这可能吗?如果有,怎么做?你能给我推荐一个教程或例子吗?我的想法对吗?

我不喜欢使用第三方库,因为我想深入了解。

感谢所有的评论和谷歌我终于弄清楚了-基本上我需要一个这样的例子:

/* Usage
--------
$ javac CompileJarLoadReflect.java
$ java CompileJarLoadReflect MyClass YourClass CompileJarLoadReflect
MyClass.java compilation is successful
YourClass.java compilation is successful
CompileJarLoadReflect.java compilation is successful
3 files successfully compiled
Class MyClass
    myMethod
Class YourClass
    yourMethod
Class CompileJarLoadReflect
    main
    compile
    compile
    load
    jar
*/
/* Thanks to
------------
http://www.java2s.com/Code/Java/File-Input-Output/CreateJarfile.htm
http://stackoverflow.com/questions/194698/how-to-load-a-jar-file-at-runtime/673414#673414
*/
import javax.tools.*;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.jar.JarEntry;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.net.URL;
import java.net.URLClassLoader;
import java.lang.reflect.Method;

/** Simple compilation, packaging and loading example */
public class CompileJarLoadReflect {
    /** JAR buffer size*/
    public static int BUFFER_SIZE = 10 * 1024;
    /** Compile all files given (by their location) */
    public void compile(String[] files) throws Exception {
        for (String f : files) compile(f + ".java");
        System.out.println(files.length + " files successfully compiled");
    }
    /** Compile one particular file */
    protected void compile(String f) throws Exception {
        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
        int compilationResult = compiler.run(null, null, null, f);
        if (compilationResult == 0) System.out.println(f + " compilation is successful");
        else throw new Exception("Compilation error at file " + f);
    }
    /** Pack tobeJared classes into jarName */
    public void jar(String jarName, String[] tobeJared) throws Exception {
        File archiveFile = new File(jarName);
        byte buffer[] = new byte[BUFFER_SIZE];
        FileOutputStream stream = new FileOutputStream(archiveFile);
        JarOutputStream out = new JarOutputStream(stream, new Manifest());
        for (String name : tobeJared) {
            File f = new File(name + ".class");
            if (f == null || !f.exists() || f.isDirectory()) throw new Exception("Jar problem at file " + name);
            JarEntry jarAdd = new JarEntry(f.getName());
            jarAdd.setTime(f.lastModified());
            out.putNextEntry(jarAdd);
            FileInputStream in = new FileInputStream(f);
            while (true) {
                int nRead = in.read(buffer, 0, buffer.length);
                if (nRead <= 0) break;
                out.write(buffer, 0, nRead);
            }
            in.close();
        }
        out.close();
        stream.close();
    }
    /** Load jar archive at jarName and then print methods of all classes in clazzes  */
    public void load(String jarName, String[] clazzes) throws Exception {
        File file  = new File(jarName);
        URL url = file.toURL();  
        URL[] urls = new URL[]{url};
        ClassLoader cl = new URLClassLoader(urls);
        for (String c : clazzes) {
            System.out.println("Class " + c);
            Class cls = cl.loadClass(c);
            Method[] methods = cls.getDeclaredMethods();
            for (Method m : methods) System.out.println("t" + m.getName());
        }
    }
    /** Try everyting out, use params without .java */
    public static void main(String[] args) {
        String jarName = "output.jar";
        try {
            CompileJarLoadReflect cjlr = new CompileJarLoadReflect();
            cjlr.compile(args);
            cjlr.jar(jarName, args);
            cjlr.load(jarName, args);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

我希望它能帮助别人。

相关内容

  • 没有找到相关文章

最新更新