Newsgroup: it.comp.java
Titolo: Odbc Succhia Memoria ..

Salve...
.. vi chiedo un consiglio: Ho una applicazione che si connette ad un DB e
che periodicamente esegue delle query. Fino a questa mattina la connessione
con il DB avveniva in modo permanente (istanziavo una connesstione e uno
statment e la riutilizzavo per ogni query). Poi questa mattina mi sono
deciso di cambiare il tutto e di aprire e chiudere la connessione ogni volta
che eseguo una query. Il motivo? Se il Database č su una macchina diversa da
dove eseguo l'applicazione Java e per caso la rete si inchioda, l'ODBC non
torna su da solo al ripristino della rete e va in errore.
Quello che ho provato a fare allora č aprire e chiudere la connessione al DB
e lo Statment ad ogni query ma con il pessimo risultato che si volatilizzano
2mb di memoria ogni secondo... Idem istanziando un nuovo oggetto "database"
ogni volta ... sembra proprio che il driver ODBC non rilasci le risorse se
non dopo un certo tempo, moooolto lungo (credo). Qualche suggerimento? ....
Il problema non č con Java nel senso che la stessa cosa avviena anche in
Perl usando la stessa "logica" di aprire e chiudere l'odbc ad ogni query.
Il semplice codice che uso e che succhia circa 2mb al secondo č:
public class OdbcComm {
  private String url = "jdbc:odbc:";
  private String username = "";
  private String password = "";
  private Connection con;
  private Statement stmt;
  public OdbcComm(String name) {
    url = url+name;
    try {
      Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
      con = DriverManager.getConnection(url,username,password);
      stmt = con.createStatement();
    }
    catch (Exception e) {
      Utility.logError ("Failed to load JDBC/ODBC driver: "+e.getMessage());
    }
  }
  public void close () {
    try {
      stmt.close();
      con.close();
    }
    catch (Exception e) {
      Utility.logError ("Problems closing DB: "+e);
    }
  }
  public ResultSet selectQuery (String query) {
    ResultSet rs = null;
    try {
      rs = stmt.executeQuery(query);
    }
    catch (Exception e) {
      Utility.logError ("Problems with SELECT sent to "+url+":
"+e.getMessage());
      Utility.logError ("Query: " + query);
      return null;
    }
    return rs;
  }
}
public class dbTest {
  public dbTest() {
    while (true) {
      OdbcComm db = new OdbcComm("demoSmarties");
      java.sql.ResultSet rs = db.selectQuery("select * from inbox");
      db.close();
    }
  }
  public static void main(String[] args) {
    dbTest dbTest1 = new dbTest();
  }
}
Dan

Dan wrote:
[SNIP]
Nel tuo codice non ho trovato nulla che chiudesse il rs, una dimenticanza?
Ciao,
 Stefano
----------
"X WindowSSS, teSSSoro mio... lo odieremo per SSSempre"
Bill Gollum
----------

 Nel tuo codice non ho trovato nulla che chiudesse il rs, una dimenticanza?
Più che una dimenticanza ... nelle varie prove che ho fatto chiudere il
ResultSet non dava nessun cambiamento.... e da qua la dimenticanza.
Ho riscritto il codice nel modo più essenziale possibile in modo che un
"taglie e incolla" permetta a chiunque (ne abbia voglia) di provarlo e
vedere il "succhiamento" di memoria che provoca. ... Uff...
Daniele
import java.sql.*;
public class DB {
  public DB() {
    while (true) {
      OdbcComm db = new OdbcComm("demoSmarties");
      ResultSet rs = db.selectQuery("select * from inbox");
      try {rs.close();}
      catch (Exception e) {System.out.println(e);}
      db.close();
    }
  }
  public static void main(String[] args) {
    DB d = new DB();
  }
}  // end DB
class OdbcComm {
  private Connection con;
  private Statement stmt;
  public OdbcComm(String name) {
    try {
      Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
      con = DriverManager.getConnection("jdbc:odbc:"+name,"","");
      stmt = con.createStatement();
    }
    catch (Exception e) {System.out.println (e.getMessage());}
  }
  public void close () {
    try {
      stmt.close();
      stmt.cancel();
      con.close();
    }
    catch (Exception e) {System.out.println (e.getMessage());}
  }
  public ResultSet selectQuery (String query) {
    ResultSet rs = null;
    try { rs = stmt.executeQuery(query); }
    catch (Exception e) {System.out.println (e.getMessage());}
    return rs;
  }
}

 Il problema non è con Java nel senso che la stessa cosa avviena anche in


 ResultSet non dava nessun cambiamento.... e da qua la dimenticanza.
Ciao, chiudere il resultset è buona norma ma se non lo fai ci pensa il 
driver quando chiudi lo statement e poi ancora dopo la connection che 
quando la chiudi, chiude lo/gli statement associati, questo spiega 
perchè non vedi differenze.
Il tuo problema mi aveva fatto perdere le notti anche a me e avevo poi 
scoperto che è proprio un baco dell'ODBC versione ???? (quasi tutte 
comunque). Avevo risolto la cosa con un Pool di connessioni che 
ovviamente ti occupa memoria quando le allochi ma poi puoi ridurre 
sensibilmente le aperture chiusure di Connection e quindi l'effetto dei 
2Mb che si volatilizzano ad ogni volta (per me però si parlava di circa 
mezzo mega).
La cosa l'avevo verificata anche con un profiler e con il grafico di 
occupazione di memoria di NT: si vedeva chiaramente che nonostante il 
profiler registrasse correttamente la deallocazione della ram alla 
chiusura di uno statement/connection (diversi MB) questa non ricompariva 
nel grafico della memoria disponibile di NT, che invece ricompariva di 
botto quando chiudevi l'applicazione.
Dove andava tutta la RAM? Nella pancia di ODBC ma occupando memoria a 
nome della tua applicazione, ecco perchè poi quando chiudevo l'app tutto 
tornava  a posto.
Spero ti sia utile per risolvere il tuo problema
ciao
Marco

 wrote in message
huKr6.20226$x3.3...@news2.tin.it...



usa hypersonicsql
www.hypersonicsql.com
 mi pare