Как отладить скопилированный JAVA Spring MVC jar?
Есть сторонний jar файл с проектом Spring MVC (Spring Boot), содержащий в себе полное приложение со всеми зависимостями.
Как с помощью intellij idea (который умеет декомпилировать код) отладить проект.
Т.е нужно залезть в когд и идти по шагам.
Когда я подключаю jar через концигурацию билда (Run/Debug Configuration -> JAR Application), приложение запускается через IDE, но как подключить декомпилированные исходники и шагать в отладке по ним?
- Вопрос задан более трёх лет назад
- 135 просмотров
3 комментария
Простой 3 комментария
Декомпилятор Intellij
Есть проект с кучей классов и надо его декомпилировать, однако вручную с каждым классом возиться (1000+ классов) весьма затруднительно. Нельзя ли каким то образом заставить intellij декомпилить все сразу? просто сроки поджимают
Отслеживать
задан 25 июл 2017 в 17:05
Алексей Серебряков Алексей Серебряков
21 1 1 бронзовый знак
1 ответ 1
Сортировка: Сброс на вариант по умолчанию
- Сбилдите идеевский декомпилятор fernflower
- Запустите java -jar fernflower.jar
Результат будет лежать в папочке
Отслеживать
ответ дан 25 июл 2017 в 17:21
Дмитрий Игоревич Дмитрий Игоревич
271 1 1 серебряный знак 3 3 бронзовых знака
- java
- intellij-idea
- jar
-
Важное на Мете
Похожие
Подписаться на ленту
Лента вопроса
Для подписки на ленту скопируйте и вставьте эту ссылку в вашу программу для чтения RSS.
Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.10.27.43697
Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.
IntelliJ Idea : Декомпиляция, Компиляция, Субституция (или как править чужие ошибки)
«Да не изобрети ты велосипед» — одно из главных правил успешной и эффективной работы. Но что делать, когда свой велосипед изобретать не хочется, а у чужого руль оказался кривой, а колёса квадратными? Данный обзор предназначен для по возможности краткого ознакомления с приёмом исправления в чужих библиотеках «на крайний случай» и о том, как это дело распространить дальше своего компьютера.
Введение
- Подготовить испытуемое приложение для примера (на примере Hibernate проекта)
- Поиск изменяемого места
- Выполнение изменения
- Разворачивание репозитория
Подготовка испытуемого
Итак, нам нужен подопытный проект. Нам идеально подойдёт Hibernate, т.к. это «стильно, модно, современно». Не буду особо вдаваться в детали, т.к. статья не про Hibernate. Будем делать всё быстро и по делу. И будем, как правильные разработчики , использовать систему сборки. Например, нам так же подойдёт Gradle, который для данной статьи должен быть установлен (https://gradle.org/install/). Сначала, нам нужно создать проект. У Maven’а для этого есть архетипы, а у Gradle для этого есть особенный плагин: Gradle Init. Итак, открываем командную строку любым известным вам способом. Создаём каталог для проекта, переходим в него и выполняем комманду:
mkdir javarush cd javarush gradle init --type java-application
Прежде чем выполнять импорт проекта внесём некоторые изменения в файл, описывающий, каким образом нужно выполнять сборку. Этот файл называется build script’ом и имеет имя build.gradle. Находится он в том каталоге, в котором мы выполнили gradle init. Поэтому, просто открываем его (например, в windows командой start build.gradle). Находим там блок «dependencies», т.е. зависимости. Тут описываются все сторонние jar, которые мы будем использовать. Теперь надо понять, что тут описывать. Перейдём на сайт Hibernate (http://hibernate.org/). Нас интересует Hibernate ORM. Нам нужен последний релиз. В меню слева есть подраздел «Releases». Выбираем «latest stable». Проматываем вниз и находим «Core implementation (includes JPA)». Раньше нужно было поддержку JPA подключать отдельно, но теперь всё стало проще и достаточно только одной зависимости. Также нам понадобится при помощи Hibernate работать с базой данных. Для этого возьмём самый простой вариант – H2 Database. Выбор сделан, вот наши зависимости:
dependencies < // Базовая зависимость для Hibernate (новые версии включают и JPA) compile 'org.hibernate:hibernate-core:5.2.17.Final' // База данных, к которой мы будем подключаться compile 'com.h2database:h2:1.4.197' // Use JUnit test framework testCompile 'junit:junit:4.12' >
Отлично, что дальше? Надо настроить Hibernate. У Hibernate есть «Getting Started Guide», но он дурацкий и больше мешает, чем помогает. Поэтому пойдём как правильные люди сразу в «User Guide». В оглавлении видим раздел «Bootstrap», что переводится как «Начальная загрузка». То что надо. Там написано много умных слов, но смысл в том, что на classpath должен быть каталог META-INF, а там файл persistence.xml. На classpath по стандарту попадает каталог «resources». Поэтому создаём указанный каталог: mkdir src\main\resources\META-INF Создаём там файл persistence.xml и открываем его. Там же в документации есть пример «Example 268. META-INF/persistence.xml configuration file» из которого мы возьмём содержимое и вставим в файл persistence.xml. Далее запускаем IDE и импортируем в неё наш созданный проект. Теперь нам нужно что-то сохранять в базу. Это что-то называется сущности. Сущности представляют что-то из так называемой доменной модели. И в оглавлении, о чудо, видим «2. Domain Model». Спускаемся ниже по тексту и видим в главе «2.1. Mapping types» простой пример сущности. Забираем его к себе, чуть сократив:
package entity; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; @Entity(name = "Contact") public class Contact < @Id @GeneratedValue private Integer id; private String name; public Contact(String name) < this.name = name; >>
Теперь у нас появился класс, представляющий сущность. Вернёмся в persistence.xml и поправим там одно место: Там где указан class укажем свой класс entity.Contact . Отлично, осталось запуститься. Возвращаемся в главу «Bootstrap». Так как у нас нет сервера приложений, который нам предоставит особое EE окружение (т.е. окружение, которое реализует для нас определённое поведение системы), то мы работаем в SE окружении. Для него нам подойдёт только пример «Example 269. Application bootstrapped EntityManagerFactory». Например, сделаем так:
public class App < public static void main(String[] args) < EntityManagerFactory emf = Persistence.createEntityManagerFactory("CRM"); EntityManager em = emf.createEntityManager(); em.getTransaction().begin(); Contact contact = new Contact("Vasya"); em.persist(contact); em.getTransaction().commit(); Query sqlQuery = em.createNativeQuery("select count(*) from contact"); BigInteger count = (BigInteger) sqlQuery.getSingleResult(); emf.close(); System.out.println("Entiries count: " + count); >>
Ура, наш испытуемый готов. Эту часть я не хотел опускать, т.к. для следующих глав желательно понимать то, как появился наш испытуемый.
Поиск изменяемого поведения
Давайте встанем на место инициализации поля count типа BigInteger и поставим там точки останова (BreakPoint). Встав на нужной строке это можно сделать при помощи Ctrl+F8 или через меню Run -> Toggle Line Breakpoint. После чего запускаем наш main метод в дебаге (Run -> Debug):
Немного неуклижий пример, но, допустим, мы хотим изменить количество query spaces при старте. Как мы видим, наш sqlQuery это NativeQueryImpl. Нажимаем Ctrl+N , пишем название класса, переходим в него. Чтоб при переход в класс нас перебрасывало на то место, где лежит этот класс включил автоскрол:
Сразу заметим, что Idea не знает сейчас, где можно найти исходный код программы (исходники, то есть). Поэтому она милостиво декомпилировала для нас из class файла содержимое:
Заметим так же, что в заголовке окна IntelliJ Idea пишется, где Gradle сохраняет для нас артефакт. Теперь, получим в Idea путь, где лежит наш артефакт:
Перейдём в этот каталог в командной строке при помощи команды cd путь к каталогу . Сразу сделаю замечание: если есть возможность собрать проект из исходников, лучше собирать из исходников. Например, исходный код Hibernate доступен на официальном сайте. Лучше забрать его для нужной версии и сделать все изменения там и собраться при помощи скриптов сборки, которые указаны в проекте. Я же привожу в статье самый ужасный вариант – есть jar, а исходного кода нет. И замечание номер 2: Gradle может получить исходный код при помощи плагинов. Подробнее см. «How to download javadocs and sources for jar using Gradle.
Выполнение изменения
Нам нужно воссоздать структуру каталогов в соответствии с тем, в каком пакете лежит изменяемый нами класс. В данном случае: mkdir org\hibernate\query\internal , после чего создаём в этом каталоге файл NativeQueryImpl.java . Теперь открываем данный файл и копируем туда всё содержимое класса из IDE (то самое, которое для нас декомпилировала Idea). Изменяем нужные строки. Например:
- [1] — hibernate-core-5.2.17.Final.jar
- [2] — hibernate-jpa-2.1-api-1.0.0.Final.jar
Ура, теперь можно выполнить jar update. Можем руководствоваться официальными материалами: jar uf hibernate-core-5.2.17.Final.jar org\hibernate\query\internal\*.class Открытая IntelliJ Idea, скорей всего, не даст изменять файлы. Поэтому до выполнения jar update, скорей всего, придётся закрыть Idea, а после обновления — открыть. После этого можно заново открываем IDE, опять выполняем dubug. Break Points не сбрасываются между перезапусками IDE. Поэтому, выполнение программы остановится там, где и раньше. Вуаля, мы видим как работают наши изменения:
Отлично. Но тут возникает вопрос – благодаря чему? Просто благодаря тому, что когда gradle собирает проект, он анализирует блок dependencies и repositories. У грэдла есть некий build cache, который лежит в определённом месте (см. «How to set gradle cache location?». Если в кэше нет зависимости, то Gradle её скачает из репозитория. Т.к. мы меняли jar в самом кэше, то Gradle думает, что в кэше библиотека есть и ничего не выкачивает. Но любая очистка кэша приведёт к тому, что наши изменения пропадут. Плюс, никто кроме нас не может просто взять и получить их. Сколько неудобств, не правда ли? Что же делать. Хм, скачивает из репозитория? Значит, нам нужен наш репозиторий, с преферансом и поэтессами. Об этом следующий этап.
Разворачивание репозитория
Для разворачивания своего репозитория существуют разные бесплатные решения: одно из них Artifactory, а другое — Apache Archive. Артифактори выглядит модно, стильно, современно, но с ним у меня возникли трудности, никаких не хотел правильно размещать артефакты и генерировал ошибочные мавен метаданные. Поэтому, неожиданно для себя, у меня заработал апачевский вариант. Он оказался не такой красивый, зато работает надёжно. На странице загрузки ищем Standalone версию, распаковываем. У них есть свой «Quick Start». После запуска надо дождаться, когда по адресу http://127.0.0.1:8080/#repositorylist . После этого выбираем «Upload Artifact»:
Нажимаем «Start Upload», а после «Save Files». После этого появится зелёное сообщение об успешности и артефакт станет доступен в разделе «Browse». Так надо сделать для jar и для pom файлов:
Это связано с тем, что в pom файле прописаны дополнительные зависимости хибернейта. А нам осталось только 1 шаг — указать репозиторий в нашем билд скрипте:
repositories < jcenter() maven < url "http://127.0.0.1:8080/repository/internal/" >>
И, соответственно, версия нашего хибернейта станет: compile ‘org.hibernate:hibernate-core:5.2.17.Final-JAVARUSH’ . Вот и всё, теперь наш проект использует исправленный нами вариант, а не изначальный.
Заключение
- Есть такой веб-сервер Undertow. До некоторого времени был баг, который при использовании прокси не давал узнать IP конечного пользователя.
- До поры до времени WildFly JPA определённым образом обрабатывал один не учтённый спефицикацией момент, из-за этого сыпались Exception. И это не настраивалось.
How to decompile to java files intellij idea
IDEA has a great built-in feature — decompiler. It works great.I can copy source code, but I cannot find option to extract all decompiled java classes to java files.
This project has a lot of java classes and packages, so I will be to long to copy this manually.
Does anyone know how to extract to java source files. Thx
asked Feb 8, 2015 at 0:04
user4541912 user4541912
Look Inside Compiled Code with Java Bytecode Decompiler — This page introduced the plugin Java Bytecode Decompiler in 2020.03. By using this bundled plugin inside Intellij, it’s pretty easy to decompile .jar to java code.
Nov 3, 2020 at 9:43
11 Answers 11
As of August 2017 and IntelliJ V2017.2, the accepted answer does not seem to be entirely accurate anymore: there is no fernflower.jar to use.
The jar file is called java-decompiler.jar and does not include a main manifest. Instead you can use the following command (from a Mac install):
java -cp "/Applications/IntelliJ IDEA.app/Contents/plugins/java-decompiler/lib/java-decompiler.jar" org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler
(you will get the wrong Usage command, but it does work).
answered Aug 5, 2017 at 16:09
2,942 1 1 gold badge 23 23 silver badges 25 25 bronze badges
Merging this answer with the top comment from the accepted answer, the command to launch to use the same params that IDEA uses by default is java -cp «/Applications/IntelliJ IDEA.app/Contents/plugins/java-decompiler/lib/java-decompiler.jar» org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -hdc=0 -dgs=1 -rsy=1 -rbr=1 -lit=1 -nls=1 -mpm=60 /absolute/path/to/src1 /absolute/path/to/src2 /absolute/path/to/dst
Jul 11, 2018 at 8:37
On Arch install: java -cp «/usr/share/idea/plugins/java-decompiler/lib/java-decompiler.jar» org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -hdc=0 -dgs=1 -rsy=1 -rbr=1 -lit=1 -nls=1 -mpm=60 /absolute/path/to/src1 /absolute/path/to/src2 /absolute/path/to/dst
Sep 5, 2018 at 14:38
This more brief command worked for me (based on these answers and the usage note): java -cp /java-decompiler/lib/java-decompiler.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -dgs=true
Oct 25, 2018 at 15:24
Windows decompile.cmd scr1 src2 dst: java -cp «%ProgramFiles%\JetBrains\IntelliJ IDEA 2018.3\plugins\java-decompiler\lib\java-decompiler.jar» org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -hdc=0 -dgs=1 -rsy=1 -rbr=1 -lit=1 -nls=1 -mpm=60 %*
Jan 17, 2019 at 16:28
how could you read what intellij is using as params? i didn’t find these info here github.com/JetBrains/intellij-community/tree/master/plugins/…
Aug 7 at 16:07
Follow instructions for IntelliJ JD plugin. Or see an excerpt from the instructions below.
java -jar fernflower.jar []+
+ means 1 or more times
: file or directory with files to be decompiled. Directories are recursively scanned. Allowed file extensions are class, zip and jar.
: destination directory
java -jar fernflower.jar -hdc=0 -dgs=1 -rsy=1 -lit=1 c:\Temp\binary\ -e=c:\Java\rt.jar c:\Temp\source\
Be aware that if you pass it a «.jar» file for the source, it will create another «.jar» file in the destination, however, within the new «.jar» file, the files will be .java instead of .class files (it doesn’t explode the jar).
UPDATE
People ask me: How do I get the fernflower.jar?
If you have any IntelliJ product installed, chances are that you already have the Fernflower decompiler on your computer. IntelliJ IDEA comes with Java Bytecode Decompiler plugin (bundled) which is a modern extension of Fernflower.
- Locate the file in $\plugins\java-decompiler\lib\java-decompiler.jar (example: C:\Program Files\JetBrains\IntelliJ IDEA 2018\plugins\java-decompiler\lib).
- Copy it somewhere and rename to fernflower.jar (optional).
- This JAR is not executable, so we can’t run it using java -jar . However something like this works:
java -cp fernflower.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler []+
org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler is the class that contains the main method to run the decompiler. Example:
mkdir output_src java -cp fernflower.jar org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler -hdc=0 -dgs=1 -rsy=1 -lit=1 ./input.jar ./output_src
If you don’t have IntelliJ products installed, either download it now (available on jetbrains.com) or make your own decompiler executable from sources (available on Github).