Как динамически декомпилировать объект класса в памяти?

Я делаю инструмент для динамического отображения исходного кода запуска класса Java. Мне нужен инструмент, который поможет мне динамически декомпилировать исходный код из Class Object в String. Я знаю, что некоторые инструменты декомпиляции, такие как Jad, DJ decompiler, могут декомпилировать файл .class, но я ожидаю, что инструмент может:

Class<?> c = ..; // get from runtime environment
String sourcecode = **DecompileTool**.decompileClassObject(c);
return sourcecode;

Мне нужен такой DecompileTool, кто-нибудь знает? Спасибо


person JerryCai    schedule 02.07.2012    source источник
comment
дублирование stackoverflow.com/questions /272535/   -  person Nir Alfasi    schedule 02.07.2012
comment
@alfasin не совсем, в этом вопросе они признают существование определенных компиляторов, но не поддерживаемых ими интерфейсов.   -  person Kristopher Micinski    schedule 02.07.2012


Ответы (4)


Я не знаю ни одного декомпилятора, который можно было бы использовать таким образом.

Действительно, в общем случае невозможно реализовать декомпилятор, работающий так:

  • Объект Class<?>, который вы получаете из среды выполнения, не предоставляет никакого способа получить байт-коды.

  • Чтобы получить байт-коды, вам нужно будет повторить то, что делает загрузчик классов, когда он находит файл «.class» из пути к классам.

  • Я не думаю, что есть способ узнать, какие загрузчики классов используются ... если вы включите возможность динамически создаваемых загрузчиков классов. (И такие загрузчики классов являются обычной практикой (например) в веб-контейнерах.)

  • В общем случае загрузчик классов сделает это способами, которые вы не сможете воспроизвести... без обратного проектирования и жесткого кодирования той же логики в коде вашего адаптера декомпилятора.

Кроме того, делать это на лету, вероятно, бессмысленно, потому что велика вероятность того, что декомпилятор выдаст некомпилируемый исходный код.

person Stephen C    schedule 02.07.2012
comment
Спасибо, интересно, есть ли способ получить путь к файлу .class (используется в файле jar) из Classloader, я нашел такой способ: Class<?> c = ...; URL url = c.getClassLoader().getResource(classname); // use this URL object to locate .class file? - person JerryCai; 02.07.2012
comment
Обычно это работает, но есть случаи, когда это не сработает, а в других случаях это не поможет. Один из случаев, когда это не работает, — это когда ресурс встроен в загруженный файл. Один случай, когда это не помогает, - это когда вы используете файл JAR с зашифрованными файлами классов и настраиваемым загрузчиком классов, который расшифровывает во время загрузки. - person Stephen C; 02.07.2012

Я не думаю, что какой-либо из этих декомпиляторов поддерживает такой уродливый интерфейс.

Прежде всего, большинство декомпиляторов будут представлять любой код в формате, аналогичном фактическому компилятору, то есть в виде абстрактного синтаксического дерева. Если вам повезет, и у декомпилятора есть интерфейс, скорее всего, он будет такого типа. Возврат необработанного String вряд ли будет удовлетворительным, потому что как человек, пишущий декомпилятор, может иметь какое-либо представление о том, как вы хотите отформатировать код (одна из самых больших проблем при декомпиляции — представить результат пользователю!).

Вместо этого вам следует написать небольшую обертку, которая делает это правильно: на лету генерируются файлы, которые необходимо декомпилировать, отправляя их через декомпилятор и извлекая результат в строку (которую вы можете получить сразу если вы делаете умные разветвления и конвейеры и т. д., но на самом деле вы, вероятно, просто хотите отформатировать выходной файл декомпилятора..)

person Kristopher Micinski    schedule 02.07.2012
comment
Спасибо, но, как сказал @Stephen C, возможно, нет способа преобразовать Class<?> в файл байт-кода .class. :( - person JerryCai; 02.07.2012
comment
Интересно, есть ли способ получить путь к файлу .class (используется в файле jar) из Classloader, я нашел такой способ: Class<?> c = ...; URL url = c.getClassLoader().getResource(classname); // use this URL object to locate .class file? - person JerryCai; 02.07.2012

Попробуйте Cavaj Java Decomplier, он может быть вам полезен. Если вы не удовлетворены это, попробуйте JadClipse с eclipse IDE.

person Sai Ye Yan Naing Aye    schedule 02.07.2012

Вы можете сделать следующие шаги

1) Вы можете использовать декомпиляторы, доступные для декомпиляции кода, например

Process p = Runtime.getRuntime().exec("jad /location/CompilesClass.class");
BufferedReader in = new BufferedReader(  
    new InputStreamReader(p.getInputStream()));  
String line = null;  
while ((line = in.readLine()) != null) {  
    System.out.println(line);  
}  

2) Теперь скомпилированный класс преобразуется в расширение .jad (исходный код) по пути, где был файл класса

3) Теперь вы можете прочитать этот .jad файл с помощью Scanner класса JDK6. Нравиться

        Scanner scanner = new Scanner(new File("locationOfJADFIle")).useDelimiter("\n");

        while(scanner.hasNext()){
            System.out.println(scanner.next());
        }
person Bhavik Ambani    schedule 02.07.2012
comment
Благодарю. Если я получу файл .class, я воспользуюсь вашим методом. Но перед этим самая большая проблема заключается в том, как я могу найти этот файл .class из объекта Class<?>? Или есть ли способ в java искать и копировать файл .class в банке по имени класса? - person JerryCai; 02.07.2012