2

I try to analyze Java source code in Java6. ANTLR4 does great job in lexical analysis indeed but now I wonder if more advanced problems, such as listing inherited methods, can be managed.

My idea (according to some googling):

  1. load source files
  2. get system compiler by ToolProvider.getSystemJavaCompiler() and compile sources via run() into .class files
  3. [maybe?] pack .class files to .jar and load them somehow
  4. use Java reflection to analyze compiled classes
  5. delete .class files
  6. write output (e.g. inherited methods/fields etc.)

Bullets 1, 4, 5 and 6 are clean enough and well described. I belive nr. 2 can be solved using this tutorial. So my core problem is nr. 3 as I can't figure out how to load .class files and analyse them.

Any ideas? Is this even possible? If so, how? Could you recommend me either a tutorial or examples? Is my idea even correct?

I prefer not using third-party libraries as I'd like to understand in depth.

9
  • The class file format is well-defined. IMO doing this manually is a pretty awful idea, though; I understand wanting to learn in-depth, but that's ancillary to doing byte code analysis. Commented Jun 30, 2014 at 13:13
  • @DaveNewton Couldn't I just extend (somehow) classpath to compiled .class files and then analyse them using reflection? IMHO all I need is to access compiled classes for Class.forName(...), isn't it? Commented Jun 30, 2014 at 13:16
  • How will you know what to reflect on? Commented Jun 30, 2014 at 13:21
  • Lexical analysis provided by ANTLR gives AST including class names etc. So I could call Class.forName with full class name including package. Commented Jun 30, 2014 at 13:27
  • 1
    The usual answer to "How do I static analysis (having never read a compiler book)?" is "Go read a compiler book, then ask again". Google for my essay Life After Parsing if you want a pithier discussion. Commented Jun 30, 2014 at 14:26

1 Answer 1

1

Thanks to all comments and google I finally figured it out - basically I needed an example like this:

/* 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();
        }

    }
}

I hope it helps others.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.