2013-06-28 4 views
4

Я пытаюсь получить все зависимости в классе Java, включая классы, используемые для параметризации обобщений и типов локальных переменных. Пока что лучшая структура, которую я нашел, - apache bcel. Используя его, я могу легко найти все поля, аргументы метода и локальные переменные из байтового кода. В основном все, кроме типов дженериков и локальных переменных. Например, из строки List<Point> points = new ArrayList<Point>(); я могу найти только одну зависимость - ArrayList с использованием метода JavaClass.getConstantPool() из bcel. Он не может обнаружить ни интерфейс List, ни класс Point. Я также пробовал tattletale и CDA, к сожалению, без успеха (те же результаты). Изучение импорта недостаточно - мне нужны также зависимости от одного и того же пакета, и я не могу принять подстановочные знаки. Я был бы признателен за любую помощь.Найти все зависимости в Java-классе

+0

Вы пытаетесь сделать это во время выполнения из байт-кода? Во время компиляции? –

+0

Я хочу найти все статические зависимости (не время выполнения). Чтение байт-кода, вероятно, является лучшей идеей для этого. Но я также могу попытаться разобрать исходный код (это просто не кажется лучшей идеей, и я не нашел для этого никакого решения). – goobar

+0

Не все исходные зависимости должны заканчиваться в файле класса (общие типы внутри метода, встроенные константы). Просто посмотрите на файлы классов в достойном текстовом редакторе или на UNIX 'strings'. –

ответ

5

Я наконец нашел решение. ASM Bytecode Framework - правильный инструмент для использования. Используя официальный tutorial и правый example, довольно легко получить все необходимые зависимости. В примере уже есть класс посетителей DependencyVisitor, который делает то, что я хочу. Чтобы получить правильное форматирование, я должен был изменить только один метод в DependencyVistitor пример кода, поэтому он добавляет полные имена классов вместо пакетов только:

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; 
} 

Глядя на DependencyVisitor код, который вы можете легко понять, что она делает, и изменить его к вашему необходимо. Запуск его в моем классе классов дает мне приятный, полезный вывод: [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]. Он содержит каждый класс и интерфейс, которые я использовал, и каждый тип, используемый для параметризации дженериков.

+0

отлично, не было такой проблемы раньше, обычно идентифицировать по аннотации, но это круто, спасибо –

+0

Пример кода переместился [здесь] (http://websvn.ow2.org/listing.php?repname=asm&path =% 2Ftrunk% 2Fasm% 2Fexamples% 2Fdependencies% 2Fsrc% 2Forg% 2Fobjectweb% 2Fasm% 2Fdepend% 2F). – seanf