2012-03-13 2 views
2

Я изучаю интересную проблему с производительностью, когда нет вызовов на java.sql.Clob.free() на часто используемом ресурсе. Этот метод на Clob был представлен в Java 6/JDBC 4, поэтому вполне возможно, что это действительно регрессия, возникающая при обновлении с JDBC 3 до JDBC 4.Метод java.sql.Clob.free() JDBC 4 и обратная совместимость

Известно ли это в драйвере Oracle JDBC? Можно ли сказать, что раньше Clobs как-то волшебным образом освобождались, тогда как с JDBC 4 они были освобождены вручную? MUST? Или есть ли настройка драйвера, которая может использоваться для совместимости с JDBC 3?

Обратите внимание, что это относится и к Blob, конечно.

+0

Используете ли вы драйвер JDBC поставщика Oracle? Если да, то какой? http://www.oracle.com/technetwork/database/features/jdbc/index-091264.html# –

+0

@DragosToader: ojdbc6. Мне нужно будет дважды проверить точную версию ... –

ответ

1

Я посмотрел поставщик Oracle JDBC драйвера (ojdbc6.jar) для Oracle Database here
Я нашел файл demo.zip here
Я распаковал его и grepped источника для CLOB и BLOB.
Есть файл TemporaryLobJDBC40.java
В нем есть образец, в котором создаются временные clob и blob, затем заполняются некоторыми данными, а затем вставляются в таблицу через подготовленный оператор (параметризованный INSERT).
Затем оператор выполняется, закрыт, временный clob и blob освобождаются и транзакция совершается.

Затем автор перебирает строки таблицы, создавая постоянные blob/clobs и назначая им объекты, возвращенные из getClob(), getBlob() и выгружает содержимое в поток.

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

После последней итерации два последних объекта Blob/Clob не освобождаются явно, но неявно очищаются сборщиком мусора (когда он решает начать), их область действия заканчивается последней итерацией. (после})

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

Вот код (TemporaryLobJDBC40.java):

/* 
* This sample shows how to create 
* a temporary BLOB and CLOB, write 
* some data to them and then insert 
* them into a table. This makes a 
* permanent copy in the table. The 
* temp lobs are still available for 
* further use if desired until the 
* transaction is committed. 
* When fetched from the table, the 
* lobs are no longer temporary. 
* 
* This version uses the new 
* JDBC 4.0 factory methods in 
* java.sql.Connection and the 
* free methods in java.sql.Blob and Clob 
* 
* Testing for temporary status still 
* requires Oracle specfiic APIs in 
* oracle.sql.BLOB and oracle.sql.CLOB. 
* 
* It needs jdk6 or later version and ojdbc6.jar 
*/ 

import java.sql.Connection; 
import java.sql.SQLException; 
import java.sql.Statement; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.Blob; 
import java.sql.Clob; 


class TemporaryLobJDBC40 
{ 
    public static void main (String args []) 
    throws Exception 
    { 
    Connection conn = DemoConnectionFactory.getHRConnection(args); 
    LobExample.createSchemaObjects(conn); 
    Blob tempBlob = conn.createBlob(); 
    Clob tempClob = conn.createClob(); 

    System.out.println ("tempBlob.isTemporary()="+ 
         ((oracle.sql.BLOB)tempBlob).isTemporary()); 
    System.out.println ("tempClob.isTemporary()="+ 
         ((oracle.sql.CLOB)tempClob).isTemporary()); 
    LobExample.fill(tempBlob, 100L); 
    LobExample.fill(tempClob, 100L); 

    String insertSql = "insert into jdbc_demo_lob_table values (?, ?, ?)"; 
    PreparedStatement pstmt = conn.prepareStatement(insertSql); 
    pstmt.setString(1, "one"); 
    pstmt.setBlob(2, tempBlob); 
    pstmt.setClob(3, tempClob); 
    pstmt.execute(); 
    pstmt.close(); 
    tempBlob.free(); 
    tempClob.free(); 
    conn.commit(); 

    Statement stmt = conn.createStatement(); 
    ResultSet rs = stmt.executeQuery("select b, c from jdbc_demo_lob_table"); 
    while(rs.next()) 
    { 
     Blob permanentBlob = rs.getBlob(1); 
     Clob permanentClob = rs.getClob(2); 
     System.out.println ("permanentBlob.isTemporary()="+ 
          ((oracle.sql.BLOB)permanentBlob).isTemporary()); 
     System.out.println ("permanentClob.isTemporary()="+ 
          ((oracle.sql.CLOB)permanentClob).isTemporary()); 
     LobExample.dump(permanentBlob); 
     LobExample.dump(permanentClob); 
    } 
    rs.close(); 
    stmt.close(); 
    conn.close(); 
    } 
} 
+0

Спасибо за вашу помощь. Это сильные признаки того, что я должен явно освободить свои клобы с помощью Java 6. Но мне действительно интересно узнать о совместимости между ojdbc14 и ojdbc6 ... –

+0

Я могу разрхивировать ojdbc6.jar и ojdbc14.jar, декомпилировать/дизассемблировать соответствующие файлы .class и надеемся получить приблизительный ответ. Как бы то ни было, исходный код скрыт в файлах .class, и только автор или Oracle Corp точно знают ответ. Было бы неплохо, если бы они проверили этот сайт на вопросы о своем коде. На данный момент я бы посоветовал вам изменить свой код, чтобы явно освобождать клобы и капли.Это не так сложно с инструментами регулярного выражения. Если у вас есть файлы .class в дереве зависимостей, и они предполагают неявную сборку мусора clob/blob, вы не можете сделать это –

+0

Именно это я и сделал. Тем не менее, хорошие вещи приходят к тем, кто ждет. Может быть, кто-то знает «твердые факты» или [спросил тома] (http://asktom.oracle.com) раньше, и они отправят ответ здесь ... –

4

Наше приложение должно было быть обязательно называть java.sql.Clob.free() явно на oracle.sql.CLOB (используется toJdbc() для get java.sql.Clob) с Oracle 11g и 'ojdbc6.jar' (спецификация-версия '4.0' и версия-реализация '11 .2.0.3.0 'в MANIFEST.MF). В противном случае приложение страдает от существенных утечек памяти.

+0

Да, это то, что я испытал и в то время. .. –

Смежные вопросы