#java #jvm #reverse-engineering #bytecode
#java #jvm #обратное проектирование #байт-код
Вопрос:
У меня проблема со старым приложением, которое работает на сервере Java Tomcat, и исходный код приложения недоступен полностью, но файлы .class, очевидно, все запущены на сервере tomcat.
Могу ли я каким-то образом манипулировать байт-кодом файла .class (используемого JVM), чтобы я мог изменять тип данных переменных (потому что это то, что нужно сделать)? Или даже перепроектировать его до старого.исходный код Java?
До сих пор я использовал декомпиляторы и команду javap. Могу ли я каким-то образом скопировать все приложение Tomcat и:
- декомпилируйте его
- внесите мои изменения
- перекомпилировать его?
Комментарии:
1. Не может ли это иметь эффект снежного кома, требующий от вас изменять даже другие классы, которые зависят от тех, которые вы изменили? Что вы собираетесь делать с собственными методами, которые могут получить доступ к этому значению, которое не будет декомпилировано из скомпилированных классов?
2. Да, я знаю, что это может произойти, но переменная является filesizelimit для операции загрузки на локальный сервер, и они хотят, чтобы она была больше. Итак, в основном с точки зрения клиента нам сказали: «мы знаем, что мы делаем», что бы это ни значило…
3. Это кажется немного наивным. Изменение типа переменных не меняет логику программы. Ограничение накладывается значением , хранящимся в переменной. Поэтому вам нужно изменить весь код, отвечающий за определение этого значения и присвоение его переменной. Затем есть код, использующий эту переменную. Если первоначальные авторы создали переменную с меньшим типом данных, маловероятно, что код, использующий ее, может обрабатывать большие типы данных. Это может означать, что код, выполняющий фактическую загрузку, не может ее обработать.
Ответ №1:
Ну, если вы декомпилируете его для внесения изменений и перекомпиляции, то вам не нужно будет напрямую изменять байтовый код.
Если вы измените тип, вам придется изменить тип любых методов (например, геттеров и сеттеров), которые используют переменную. Затем вам нужно будет изменить вызовы любых методов во всех классах, которые ВЫЗЫВАЮТ эти методы, и типы их переменных, которые содержат эти значения, и т.д. Хорошей новостью является то, что, если вам удастся его успешно декомпилировать, ваша среда IDE сообщит вам, где находятся все эти места, предполагая, что новый тип несовместим со старым типом.
Я бы оценил это как «теоретически возможное», но проблематичное. С той небольшой информацией, которую вы нам предоставили, невозможно узнать размер задания ПОСЛЕ успешной декомпиляции всего приложения.
Комментарии:
1. Не говоря уже о том, что создание нового кода, который решает эту проблему, может быть в 10 раз проще, чем прямое управление байтовым кодом. Итак, зачем вообще пытаться?
2. это именно то, о чем я думаю, но клиенты…
3. Таким образом, в основном речь идет об изменении переменной с целого числа на длинное целое число.
4. Что ж, хорошей новостью является то, что eclipse и, вероятно, компилятор Java также помечают пользователя long, когда ожидается значение int . Я боялся, что этого не произойдет. Таким образом, компилятор сообщит вам все места, которые вам нужно изменить. И если вы храните это в базе данных где угодно, сложность возрастает.
Ответ №2:
У меня есть дикая и сумасшедшая идея; Я этого не делал, но пока мы говорим о вещах, которые теоретически возможны…
ЕСЛИ вам удастся декомпилировать весь код и получить систему, которую вы можете перекомпилировать и запустить (и я настоятельно рекомендую вам сделать это перед внесением каких-либо изменений), если вы сможете определить, где находится int, который вы хотите заменить на long, а затем все прямые и косвенные ссылкинадеюсь, что для этого (потому что это только ограничение на размер файла, которое вы упоминаете в другом месте) вы получите только несколько классов.
Декомпиляция должна сообщить вам их имена. Создайте новые классы с точно такими же именами, содержащие (конечно) весь их декомпилированный код. Измените методы, которые вам нужно изменить.
Теперь поместите эти классы в jar, поиск в котором выполняется перед jar, содержащим приложение. Вы ограничиваете количество классов, для которых вы предоставляете новые файлы .class, только ими. Это облегчает будущим программистам точное представление о том, что было изменено, если оно больше ничего не делает. Это возможно из-за того, как Java обрабатывает свою среду выполнения; шаг, эквивалентный «связыванию» в традиционном скомпилированном языке без виртуальной машины, происходит при загрузке класса, а не во время компиляции.
Ответ №3:
Я это сделал. Не совсем так, но что-то очень похожее. Вместо декомпиляции и перекомпиляции, что очень долго и утомительно, я напрямую отредактировал байт-код файла класса.
плюсы
- Вам вообще не нужно ничего компилировать, вы просто редактируете файл
- не требуется SDK, IDE и т. Д., Просто редактор java-байтового кода
- для небольших изменений вам может сойти с рук модификация одного метода
минусы
- очень-очень подвержен ошибкам, даже если вы знаете, что делаете
- нет способа отслеживать изменения, как вы делаете с git
- вероятно, потребуется изменить все зависимые классы
- вы должны иметь некоторые знания о том, как выглядит и ведет себя скомпилированный код, прежде чем даже пытаться это сделать.
- вы, скорее всего, нарушите один или два закона, поскольку это не будет для «образовательных» целей
- вы будете отмечены как «хакер», и каждое нечетное задание будет перенаправлено вам
PS: Мне пришлось отредактировать класс лицензирования продукта, чтобы разрешить большему количеству пользователей. Компания, написавшая его, прекратила свое существование, поэтому покупка не была вариантом. Мы все равно перешли на новый продукт, это было просто временно.