Соединение с Oracle не закрывается в приложении Java - PullRequest
2 голосов
/ 23 сентября 2010

У меня есть утечка соединения в некоторых старых веб-приложениях Java, которые не используют пул соединений.Попытка найти утечку трудна, потому что ИТ не предоставит мне доступ к v $ session SELECT Count(*) FROM v$session;

Так что вместо этого я пытаюсь отладить операторы System.out.Даже после закрытия соединения conn.close();, когда я печатаю conn в файл системного журнала, он дает мне имя объекта соединения.

try { 
    Connection conn;
    conn.close() 
    } 
catch (SQLException e) { }
finally { 
    if (conn != null) {
        try {
           System.out.println("Closing the connection"); 
           conn.close();
           }
        catch (Exception ex) 
            {
            System.out.println("Exception is " + ex); 
            }
     }
 }
// I then check conn and it is not null and I can print the object name.
    if (conn != null) {
            System.out.println("Connection is still open and is " + conn); 
    }

однако, если я добавлю conn = null; ниже оператора conn.close();, соединение теперь кажется закрытым.Итак, мой вопрос: conn.close ();на самом деле освободить мое соединение, или я должен также сделать его нулевым, чтобы действительно освободить мое соединение.Как я уже говорил, мне действительно трудно определить, действительно ли соединение освобождено, не имея возможности запросить v $ session.Есть ли фрагмент кода Java, который может дать мне мои открытые соединения ??

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

Ответы [ 6 ]

6 голосов
/ 23 сентября 2010

Важной частью закрытия является то, что происходит на стороне базы данных. Это СУБД, которая должна закрыть это соединение. Вызов метода close () - это то, что передает сообщение в базу данных, чтобы закрыть соединение.

Установка нулевого соединения не заставляет СУБД делать что-либо.

Та же логика применяется к ResultSet, который является курсором на стороне базы данных, и к Statement. Вам нужно закрыть их в отдельных блоках try / catch в блоке finally метода, который их создал, в обратном порядке создания. В противном случае вы увидите ошибки об «превышении максимальных курсоров».

4 голосов
/ 23 сентября 2010

Установка для conn значения null только разрывает ссылочную ссылку на объект подключения и не влияет на открытое подключение или нет. Если соединение все еще открыто, то на него все равно будет ссылаться изнутри JDBC-драйвер / пул соединений и т. Д. ...

Установка переменной в null больше говорит сборщику мусора, что можно чистить исходный объект, когда он хочет, чем что-либо еще.

3 голосов
/ 23 сентября 2010

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

Чтобы закрыть соединение, наберите conn.close(). Это не будет устанавливать переменную conn равной нулю. Вы можете проверить, открыто ли соединение с помощью conn.isClosed().



Если вам больше не нужно отслеживать соединение в вашем коде, вы можете conn = null. Этот не немедленно закрывает соединение. Я полагаю, что соединение будет автоматически закрыто на основе документации JDBC :

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

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

1 голос
/ 23 сентября 2010

Утечки соединения являются лучшими.Я думаю, что хорошей стратегией является объединение получения и освобождения соединений в пару функций, а затем всегда получать и освобождать ваши соединения через эти функции.Затем эти функции могут вести список всех открытых соединений и выполнять трассировку стека для вызывающей функции allocate.Затем есть экран, который показывает список всех открытых соединений и откуда они пришли.Запустите это в тестовой среде, бегите, используя несколько экранов, затем закройте их все, чтобы все соединения ДОЛЖНЫ закрыться, затем откройте экран, который показывает открытые соединения, и злодей должен быть обнаружен.

0 голосов
/ 23 сентября 2010

Есть ли фрагмент кода Java, который может дать мне мои открытые соединения?

Statement smt = null;
    ResultSet rs = null;
    try { 
        // Create Statement from connection
        smt = conn.createStatement();
        // Execute Query in statement 
        rs = stmt.executeQuery("SELECT 1 FROM Dual");

        if (rs.next()) {
            return true; // connection is valid
        }
        catch (SQLException e) {
            // Some sort of logging
            return false;
        }
        finally {
            if (smt != null) smt.close();
            if (rs != null) rs.close();
        }

Просто быстрое предположение, если вы используете Oracle.Sugession: Почему бы вам не установить jboss и не настроить там пул соединений?

0 голосов
/ 23 сентября 2010

Мое объяснение здесь обоснованное предположение.

На практике я всегда устанавливал conn = null после закрытия.Я полагаю, что когда вы делаете conn.close (), вы говорите сборщику мусора, что он готов к сборке мусора.Тем не менее, это будет процесс сбора мусора, чтобы определить, когда это сделать.

Также вы можете изменить

if (conn! = Null)

на

if (conn.isClosed ())

..

...