6

I'm trying to get all dependencies in a Java class, including classes used for generics parametrization and local variables types. So far best framework I've found is apache bcel. Using it I can easily find all fields, method arguments and local variables from byte code. Basically everything except of generics and local variables types. For example, from line List<Point> points = new ArrayList<Point>(); I can only find one dependency - ArrayList using JavaClass.getConstantPool() method from bcel. It can't detect neither List interface nor Point class. I also tried tattletale and CDA, unfortunately without success (the same results). Examining imports is not enough - I need also dependencies from the same package and I can't accept wildcards. I would be grateful for any help.

goobar
  • 193
  • 3
  • 9
  • Are you trying to do this at runtime from bytecode? Compile-time? – Louis Wasserman Jun 28 '13 at 19:01
  • I want to find all static dependencies (not runtime). Reading bytecode is probably the best idea for that. But I can try to parse source code as well (it just doesn't seem to be the best idea and I have not found any solution for that). – goobar Jun 28 '13 at 21:34
  • Not all the source dependencies need end up in the class file (generic types within the method, inline constants). Just look at class files in a decent text editor, or on UNIX `strings`. – Tom Hawtin - tackline Jun 28 '13 at 21:44
  • I've just checked it and bytecode does contain everything I need. It contains type of every local variable and every type used for generic classes/interfaces parameterization. I just don't know how to read that data from code using bcel. Thanks for comments. – goobar Jun 28 '13 at 22:29
  • I think the best approach (if in runtime) is Reflection –  Jun 29 '13 at 12:13
  • @user2511414 Reflection is not enough. Using reflection allows me to inspect fields, methods signatures, interfaces and so on. It doesn't show me local variables inside methods. I needed every dependency, inluding those used only inside methods code. Anyway, my problem is already solved. If you are interested, look at my answer. Cheers. – goobar Jun 29 '13 at 12:20

1 Answers1

8

I've finally found solution. ASM Bytecode Framework is the right tool to use. Using official tutorial and right example it's quite easy to get all needed dependencies. In the example there is already a visitor class DependencyVisitor which does what I want. To get right formatting I had to change only one method in DependencyVistitor example code, so it adds full class names instead of packages only:

private String getGroupKey(String name)
{
        //Just comment that block so you can get full class names instead of package only
        /*
        int n = name.lastIndexOf('/');
        if (n > -1)
        {
            name = name.substring(0, n);
        }
       */
        // Replace resource char with package separator char        
        packages.add(name.replace("/", "."));
        //packages.add(name);
        return name;
}

Looking at DependencyVisitor code you can easily understand what it does and modify it to your needs. Running it on my example class it gives me nice, useful output: [java.util.ArrayList, java.lang.Object, java.util.List, java.awt.Point, goobar.test.asmhello.TestClass, java.lang.String, java.lang.Integer, java.awt.Graphics, goobar.test.asmhello.TestClass2]. It contains every class and interface I've used and every type used for generics parameterization.

goobar
  • 193
  • 3
  • 9
  • perfect, haven't had such this problem before, usually identify by annotations, but this is cool, thanks –  Jun 29 '13 at 15:36
  • The example code has moved [here](http://websvn.ow2.org/listing.php?repname=asm&path=%2Ftrunk%2Fasm%2Fexamples%2Fdependencies%2Fsrc%2Forg%2Fobjectweb%2Fasm%2Fdepend%2F). – seanf Jul 06 '17 at 16:17
  • The example code is now on [Guthub](https://github.com/llbit/ow2-asm/tree/master/examples/dependencies/src/org/objectweb/asm/depend) – Benoît Guédas Jan 22 '21 at 17:15