2016-06-25 18 views
0

Я пишу программу, которая анализирует файлы .class. Я хочу привязать имя пакета и класс к моему выводу.Перевести пакет + имя класса в .class filename

Мой план состоит в том, чтобы написать функцию, которая принимает имя пакета и класса в качестве входных данных и находит соответствующий файл .class (так что пользователю также не нужно вводить его и не может ошибиться), где «find» следует читать как «дать мне некоторые данные, которые я могу использовать в качестве аргументов для конструктора ClassParser BCEL» (либо имя файла, либо имя zip-файла и имя в zip-файле).

Как это сделать? Есть ли у Java что-то, что делает это? Я понимаю, что разрешение имен должно выполняться в контексте CLASSPATH, поэтому пользователь должен, вероятно, поставить один из них; хорошо.

Примечание: решения должны не выполнить любой код из файла .class. Просто байты, ma'm ;-)

ответ

1

Ну, если вы используете BCEL, все уже есть, см ClassPath:

import java.io.IOException; 
import org.apache.bcel.classfile.ClassParser; 
import org.apache.bcel.classfile.JavaClass; 
import org.apache.bcel.util.ClassPath; 

public class BcelTest { 
    public static void main(String[] args) throws IOException { 
     String classPath=System.getProperty("java.class.path"); 
     // demonstrating with our own class path examplary for an arbitrary path String 
     ClassPath cp=new ClassPath(classPath); 
     ClassPath.ClassFile cf=cp.getClassFile(BcelTest.class.getName()); 
     ClassParser p=new ClassParser(cf.getInputStream(), cf.getPath()); 
     JavaClass jc = p.parse(); 
     System.out.println(jc); 

     // or just using our own system path explicitly 
     cf=ClassPath.SYSTEM_CLASS_PATH.getClassFile("java.lang.Object"); 
     p=new ClassParser(cf.getInputStream(), cf.getPath()); 
     jc = p.parse(); 
     System.out.println(jc); 
    } 
} 
+0

Я не указал явно, хотя я хотел передать, что разрешение класса должно выполняться в пути к классам, предоставленном пользователем, который может отличаться от того, в котором мой код работает под/с. Я думаю, что все, что мне нужно сделать, это дать разные аргументы 'new ClassPath (...)'. С этим на месте это выглядит очень многообещающе! –

+1

Я предполагал, что вам нужна возможность предоставить произвольный путь класса; поэтому я выбрал конструктор в примере, так как иначе для класса будет работать и ClassPath.SYSTEM_CLASS_PATH. Обратите внимание, что 'ClassPath', построенный с явным путем, не находит системные классы, поскольку они недоступны из явного пути класса, вам необходимо [предоставить' SYSTEM_CLASS_PATH' в качестве родителя] (http: //commons.apache. орг/правильный/Обще-BCEL/apidocs/орг/Apache/BCEL/Util/ClassPath.html # ClassPath-org.apache.bcel.util.ClassPath-java.lang.String-) для этого. – Holger

0

Если у вас уже есть класс, просто замените каждое/в имени класса разделителем каталогов для вашей системы и добавьте .class.

Если вы хотите перейти от имени класса Java к имени класса байт-кода, большинство классов довольно просты. Подготовьте пакет + '.' и замените '.' с '/'. Для внутренних и вложенных классов я не уверен, есть ли простой алгоритм.

+0

У меня нет файла класса. Скажем, я запускаю свой проект сам по себе. Он находится в '~/whatever /' с 'main()' в 'invalid/jonaskoelker/Main.java', а мой путь к классам -'.:/Usr/share/java/bcel.jar'. Алгоритм, который я хочу, при запуске на 'org.apache.bcel.classfile.ClassParser' должен вернуть два значения:'/usr/share/java/bcel.jar' и 'org/apache/bcel/classfile/ClassParser.class' (однако вы выполняете два значения в java, например, пару apache-commons). Есть ли встроенная вещь, которая что-то делает в этом направлении? –

+0

@ JonasKölker Что делать, если тот же класс появляется в нескольких банках? – Antimony

+0

Я хочу, чтобы одна java загрузилась, что я предполагаю и, кажется, напомню, это тот, который сначала найден на пути к классам. –

0

Я хочу поблагодарить прекрасных людей в irc://freenode.org/##java для направления меня к следующему рецепту:

// replace 'Throwable' with something else in production code :-) 
JavaClass recipe() throws Throwable { 
    URLClassLoader loader = new URLClassLoader(new URL[] { 
      new URL("file:///usr/share/java/js.jar"), 
     }); 
    String path = "org/mozilla/classfile/ByteCode.class"; 
    InputStream resource = loader.getResourceAsStream(path); 
    String fake_filename = "<" + path + ">"; 
    ClassParser classparser = new ClassParser(resource, fake_filename); 
    JavaClass java_class = classparser.parse(); 
    // System.out.format("%s\n", jc); 
    return java_class; 
} 

Можно было бы де-hardcode путь к классам и значение path путем вычисления строк в правильном формате на основе ввода пользователем.

Я собираюсь использовать ответ, который я принял, поскольку он требует меньше работы с моей стороны, но я хочу упомянуть об этом ответе, потому что он более общеприменим (т. Е. С меньшим количеством зависимостей).

 Смежные вопросы

  • Нет связанных вопросов^_^