Как корректно организовать версионирование java patched compiled core?

compiled core versioning

Projack

Бессмертный
VIP
Участник Новогоднего Фонда 2023
Победитель в номинации 2023
Победитель в номинации 2022
Стальной Визионер
Куратор Данных
Сообщения
490
Розыгрыши
0
Решения
2
Репутация
964
Реакции
851
Баллы
1 668
Хроники
  1. Interlude
Исходники
Отсутствуют
Сборка
любая java compiled
Допустим у нас есть скомпилированная активно развивающаяся сборка ядра, которая поставляется в скомпилированном виде(и это устраивает исходники не нужны), не signed. Мы можем декомпилировать, поправить необходимые нам вещи и запатчить обратно. Потом выйдет новая версия и придется повторять патч.
Если я правильно понял, то от компиляции к компиляции байткод особо не меняется и с помощью JarDiff можно отслеживать были ли изменения в пропатченых файлах и только в этом случае мерджить руками и пересобирать класс, иначе просто закидываем старые патченные классы обратно.

В моей голове путь автоматизации примерно такой(используя существующие тулы):
1. Репозиторий с VCS, допустим git, в котором будем держать 2 ветки, допустим patched, original. В ветке original лежит core.jar, в ветке patched лежит core.jar, core.patched.jar и папка patch, которая повторяет внутреннюю структуру jar файла и содержит только измененные .class файлы.
2. В ветку original заливается обновленный jar файл.
3. Дергаем скрипт(руками или хуком), который:
- переключаемся на ветку patched
- копируем core.jar(для diff) и делаем merge изменений из original
- получает список diff классов из jarников (jardiff)
- получаем список файлов из папки patch
- сравниваем списки, если есть конфликты, то декомпилируем конфликтные файлы и с помощью merge-file накладываем изменения в папку patch, собираем. Если есть конфликты, то алертим и дальше проходим по всем файлам с последующим выходом из скрипта.
- копируем с заменой core.jar в core.patched.jar и применяем все файлы из папки patch на jar. ( jar uf core.jar com\core\Test.class )
- подчищаем все от временных файлов
4. коммитим изменения и получаем перепропатченый core.patched.jar от обновленного core.jar

Тут кажется есть проблемы, после декомпиляции и попытки merge чаще всего будут конфликты просто из-за нейминга переменных после декомпилятора

С java на вытянутых руках и не знаю верны ли мои выводы или подход. Подскажите как вы решаете подобные проблемы(если вообще решаете) или может я в чем-то с ходу не прав? Решение выглядит накрученным
 
Последнее редактирование:
Хоть убей не понимаю смысл всех этих замудреных извращений, для чего и зачем.
 
Хоть убей не понимаю смысл всех этих замудреных извращений, для чего и зачем.
Например:
Есть классический скомпилированный java сервер. Все работает как надо, но есть необходимость добавить фичу - автоприянятие группы, трейда вторым окном. Вроде не сложно делается и все понятно. Декомплируем нужные классы, добавляем проверку по хвид и acceptим автоматически. Патчим jar геймсервера и все здорово и работает. Правленый класс сохраняем.
Таких файлов с правками накапливается штук 40. И тут приходит разработчик сервера и говорит, я поправил кучу всего, всем стало еще лучше - вот новый jar. Правки важные и нужные. А у нас 40 файлов еще со своими правками, часть из которых еще и пересекается.
И приходится вручную повторять правки для нового jar геймсервера, что конечно ладно, если между релизами месяцы. Но будь релизы чаще и правок больше, то это превращается в неприятную рутину.

Извращения для того, чтобы меньше страдать. Зачем - иначе выше шанс человеческой ошибки и начнут тратиться человекочасы
 
Projack, если я правильно понял что нужно, то можно сделать по примеру как в lameguard, но не уверен что это будет правильный подход.

У нас есть либа (core.jar) в которой два класс Launcher и Base
Launcher:
Java:
package ru;

public class Launcher
{
    public static void main(String... args)
    {
        Base base = new Base();

        System.out.println("STR: " + base.STR);
    }
}
Base:
Java:
package ru;

public class Base
{
    public final String STR;

    public Base()
    {
        STR = "Variation1";
    }
}
запустив
Код:
java -classpath core.jar ru.Launcher
мы увидем STR: Variation1

к примеру нам нужно изменить значение переменной STR в классе Base. Создаем новую либу (patcher.jar) с классом Patcher и Base
Patcher
Java:
package com;

import java.lang.reflect.Method;
import java.util.Arrays;

public class Patcher
{
    public static void main(String... args) throws Throwable
    {
        if (args.length == 0) {
            System.out.println("Main class not specified!");
            return;
        }

        Class<?> clazz = null;
        try {
            clazz = Class.forName(args[0]);
        } catch (Exception e) {
            // ignore
        }

        if (clazz == null) {
            System.out.println("Main class not found : " + args[0] + "!");
            return;
        }

        Method main = clazz.getDeclaredMethod("main", new Class[] { String[].class });
        args = Arrays.copyOfRange(args, 1, args.length);
        main.invoke(null, new Object[] { args });
    }
}
Base (пространство имен должно совподать с классом в оригинальной либе)
Java:
package ru;

public class Base
{
    public final String STR;

    public Base()
    {
        STR = "Variation2";
    }
}
и запустив
Код:
java -classpath patcher.jar;core.jar com.Patcher ru.Launcher
мы увидем уже STR: Variation2

1655931518665.png

зы - надеюсь смысл понятен
зыы - порядок указания либ в класспатче обязателен
 
òbi хм. Интересно. Спасибо! Попробую поиграться с таким подходом
 
А добавить кастомки без декомпила через data/scripts нельзя, или они тоже в собранном виде находятся?
 
А добавить кастомки без декомпила через data/scripts нельзя, или они тоже в собранном виде находятся?
Я описал пример чуть выше, без правок в ядре я как-то не понимаю как это реализовать
 
Назад
Сверху Снизу