#java #eclipse #compiler-warnings #resource-leak
#java #eclipse #компилятор-предупреждения #утечка ресурсов
Вопрос:
Я не могу понять, почему компилятор предупреждает меня об утечке ресурсов ( Resource leak: 'conn' is not closed at this location
) в следующем коде:
Connection conn = null;
try {
conn = DatabaseConnectionPool.getConnectionFromPool();
// Some code
try {
// Other code
} catch (final SomeException e) {
// More code
throw e; // Resource leak: 'conn' is not closed at this location
}
} catch (final SQLException | OtherExceptions e) {
// Some more code
} finally {
try {
// Another bunch of code
} finally {
DatabaseConnectionPool.freeConnection(conn);
}
}
Обратите внимание, что если я напишу это так
Connection conn = null;
try {
conn = DatabaseConnectionPool.getConnectionFromPool();
// Some code
try {
// Other code
} catch (final SomeException e) {
// More code
throw e;
} finally {
DatabaseConnectionPool.freeConnection(conn);
}
} catch (final SQLException | OtherExceptions e) {
// Some more code
} finally {
// Another bunch of code
}
предупреждение исчезло.
Комментарии:
1. Это не предупреждение компилятора. Вы используете инструмент для создания этого предупреждения, и, скорее всего, это ошибка в инструменте.
2. Я думаю, что блок finally является ключевым
3. @PeterLawrey Это встроенный компилятор Eclipse Java, так что это действительно предупреждение компилятора. Но я думаю, вы правы, это ошибка в этом компиляторе.
4.
final SQLException | OtherExceptions e
— что это значит? (может быть, мне следует изучить не только последнюю версию C , но и последнюю версию java; .. коды быстро развиваются ..)5. @m0skit0 он рассматривает его как ближайший общий родительский элемент, который может быть RuntimeException или Exception. Он был добавлен в Java 7 в 2011 году.
Ответ №1:
Компилятор довольно дамп. Вероятно, он не может знать, что DatabaseConnectionPool.freeConnection(conn)
вызовет close
conn
. Я не уверен, почему второй пример не вызывает это предупреждение, но, вероятно, функция просто не совсем идеальна и может давать ложные отрицательные результаты. По сути, любой ресурс должен быть закрыт путем вызова его close
метода непосредственно в том месте, где получен ресурс; это единственный способ, которым компилятор может выяснить, что вы хотите его закрыть, это не относится к межпроцедурному анализу, чтобы проверить, вызывает ли вызываемая функция close
.
В java7 вам следует рассмотреть возможность использования инструкции try-with-resource; это рекомендуемый способ обработки любых ресурсов, т. Е.:
try(Connection conn = ...){
// Do something with conn
// No close necessary here, done implicitly by the try statement
}
Весь ваш шаблон закрытия соединения путем вызова метода, отличного от close
, кажется мне ошибочным (он работает, но я бы настоятельно не рекомендовал его использовать): любой ресурс должен иметь возможность закрываться при вызове close
. Если ваш ресурс требует DatabaseConnectionPool.freeConnection
вызова для его закрытия, вы нарушаете контракт ресурсов java. Если вы используете оператор try-with-resource , у вас все равно нет выбора: вызовет оператор, close
а не ваш метод.
Комментарии:
1. Он определенно знает
DatabaseConnectionPool.freeConnection(conn)
вызовыclose
, вот почему во втором примере нет предупреждения. Я думаю, что его логика проверки просто не может обрабатывать вложенныеtry
. И спасибо за попытку с ресурсом, я читал об этом, но совершенно забыл его использовать (я все еще в основном ориентирован на Java-6).2. @m0skit0: То, что второй пример работает, не означает, что он это знает. Второй пример может быть ложноотрицательным. Но ваше предположение также может быть правдой.
3. Ну, это работает, чтобы объяснить оба случая, в то время как ваш не может объяснить второй случай; Я пока буду придерживаться его. Спасибо за вашу помощь и напоминание о try-with-resource!
4. Я поддерживаю ваш ответ, но я не могу принять его, поскольку, на мой взгляд, это неправильное объяснение. Комментарий Питера Лори — самый близкий правильный ответ.
5. @m0skit0: Что происходит, когда вы удаляете
close
вызов в своемDatabaseConnectionPool.freeConnection
методе? Выдает ли второй пример также предупреждение? Если это произойдет, то вы правы; если нет, то я прав.