Исторический контекст: Эта проблема оказалась совсем не такой, как я думал. Причина и решение приведены ниже, но исходная публикация оставлена для справки.
Я разрабатываю простую инфраструктуру для периодического опроса каталога для файлов .properties, затем выполнения SQL-запросов и отправки электронных писем на основе их конфигураций. Поскольку каждый файл .properties имеет одинаковый спектр операций, все они интерпретируются одним и тем же классом Task. Но поскольку каждый из них представляет разные логические операции, каждый из них получает отдельные файлы журнала.
Это достигается путем совместного использования одного экземпляра log4j RollingFileAppender и динамического изменения его выходного файла на основе значения в файле .properties. Поскольку это однопоточное приложение, оно отлично работает.
Однако я заметил, что в определенных ситуациях этот RollingFileAppender будет закрыт, и приложение будет продолжаться, не обращая внимания, за исключением того, что теперь регистрация не ведется. Мне удалось поймать это в действие только один раз, благодаря выводу на консоль, поскольку обычно эта служба работает в качестве фонового процесса на сервере Linux. Вот что случилось:
1) StartScheduler, основной класс, каждую минуту создает новый экземпляр TaskPoller.
2) TaskPoller сканирует каталог, загружает небольшую информацию из каждого файла .properties и определяет, следует ли его запускать. Он также имеет свой отдельный RollingFileAppender, который он получает через Logger.getLogger (TaskPoller.class). Если задача должна быть запущена, то она создает экземпляр объекта Task, передавая определенный файл .properties для запуска.
3) Задача получает свой RollingFileAppender, затем вызывает fileAppender.setFile ("newtaskname.log") и fileAppender.activateOptions () для изменения местоположения выходного файла. Затем во время его выполнения происходит нечто подобное:
[TaskPoller]
...
task = new Task(fileName); //Points RollingFileAppender to the right place
if (!task.Execute())
logger.warn(fileName + " returned with an error code."); //Succeeds
[Task.Execute]
...
try {
dbDAO.Connect();
} catch (Exception e) {
logger.fatal{"Database connection error.", e}; //Different RFA; Fails
return false;
}
[DBDAO.Connect throws SQLException, ClassNotFoundException]
...
try {
Class.forName(dbDriver); //Dynamically loaded jdbc driver class name
connection = DriverManager.getConnection(urlString, userName, password);
} catch (SQLException e) {
if (connection != null)
try { connection.close(); } catch (Exception e2) { ; }
throw e;
}
Происходит следующее: во время DBDAO.Connect () иногда я получаю исключение com.mysql.jdbc.exceptions.jdbc4.CommunicationsException (или какое-то другое непредвиденное исключение из любого загруженного класса jdbc). Это не будет перехвачено Connect (), но будет перехвачено Execute ().
Каким-то образом этот процесс вызывает закрытие приложения RollingFileAppender для Task. Единственное, что я могу придумать, что является особенным для этой ситуации, в отличие от ее стабильной и стабильной нормальной работы, это то, что выбрасываемое исключение не объявляется как выброшенное Connect (). Но я не думаю, что это должно привести к закрытию App4 log4j.
Итак, мой вопрос: что могло вызвать неожиданное закрытие этого приложения в методах, не имеющих отношения к его конфигурации?
- Edit--
Похоже, я был полностью сбит с толку; проблема где-то во взаимодействиях между Quartz, который я использовал для запуска TaskPoller каждую минуту, и log4j. Я пока не совсем понимаю его причину, но [это решение] [1], кажется, решает эту проблему. До сих пор это не проявлялось как наблюдаемая проблема, поэтому я подумал, что это как-то связано с тем, что происходило в последнее время.