2012-05-07 2 views
3

Это может быть и должно быть вопросом, который был задан и ответил много раз, но я просто не могу найти ответ.Можно ли заменить файл класса в скомпилированном проекте Java?

Если у меня есть скомпилированное приложение, работающее на сервере, могу ли я скомпилировать приложение на моем локальном компьютере и заменить класс, который я скомпилировал на своей локальной машине, с той, что на сервере?

Другими словами, могу ли я заменить файл, который был скомпилирован и находится на стороне сервера, с файлом почти идентичным, который был скомпилирован и расположен на моей локальной машине?

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

ответ

3

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

Например, если класс, который вы компилируете, включает в себя замену меток методов, используемых в других классах, вам также необходимо их заменить. Пока методы подписи общедоступных, защищенных или дефолтных методов не изменяются, вы должны быть в порядке.

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

public MyObject getObject(MyObject2 mySecondObject) 

против

public MyObject getObject(int a, int b, int c) 

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

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

Это подчеркивает важность инкапсуляции переменных экземпляра и того, как эти зависимости скрыты от других классов.

+1

+1 для указания метода подписи – Matsemann

+0

как насчет версии JDK? Я думаю, что новый файл класса должен быть скомпилирован с использованием того же JDK, что и тот, который нужно заменить. – Cam

+0

Привет @Cam, я почти уверен, что вы правы, но, честно говоря, это было так давно, что я декомпилировал некоторые файлы классов Java, которые я не могу вспомнить. ;) – jmort253

2

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

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

+0

Он вводит риск развертывания, например, забывает локальные классы, возможно, ненужные, поскольку функция «горячей» замены может определять, какие классы не менялись (классы, рассчитанные на serialVersionID). Для развертывания войны может потребоваться больше времени, но можно сделать это автоматически. –

1

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

В этом случае может быть жизнеспособным следующее решение: Java использует classpath переменная. Там вы определяете ряд банок/папок, где ваш процесс будет искать файлы.

Таким образом, вы можете сделать следующее:

  1. Создайте свой новый класс (он должен быть с таким же именем и находится в одном пакете) и компиляция.
  2. Создайте на сервере папку, в которой вы планируете хранить обновленный класс.

  3. Обновления переменного пути к классам (вероятно, в сценарии запуска вашего приложения), так что эта папка будет отображаться перед остальными вашими классами.

  4. Перезагрузите ваш сервер. Теперь ваш новый класс будет разрешен до старого и загружен.

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

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

Надеюсь, это поможет.