consideri un oggetto dichiarato in un metodo:Perché un oggetto dichiarato nel metodo è soggetto alla garbage collection prima che il metodo restituisca?
public void foo() {
final Object obj = new Object();
// A long run job that consumes tons of memory and
// triggers garbage collection
}
Sarà obj essere oggetto di garbage collection prima del ritorno di foo()?
UPDATE: precedenza ho pensato obj non è soggetto a garbage collection fino al ritorno foo().
Tuttavia, oggi mi sono sbagliato.
Ho passato diverse ore a correggere un bug e finalmente ho scoperto che il problema è causato da obj garbage collection!
Qualcuno può spiegare perché questo accade? E se voglio che obj venga bloccato come ottenerlo?
Ecco il codice che presenta problemi.
public class Program
{
public static void main(String[] args) throws Exception {
String connectionString = "jdbc:mysql://<whatever>";
// I find wrap is gc-ed somewhere
SqlConnection wrap = new SqlConnection(connectionString);
Connection con = wrap.currentConnection();
Statement stmt = con.createStatement(ResultSet.TYPE_FORWARD_ONLY,
ResultSet.CONCUR_READ_ONLY);
stmt.setFetchSize(Integer.MIN_VALUE);
ResultSet rs = stmt.executeQuery("select instance_id, doc_id from
crawler_archive.documents");
while (rs.next()) {
int instanceID = rs.getInt(1);
int docID = rs.getInt(2);
if (docID % 1000 == 0) {
System.out.println(docID);
}
}
rs.close();
//wrap.close();
}
}
Dopo aver eseguito il programma Java, verrà stampata il seguente messaggio prima che si schianti:
161000
161000
********************************
Finalizer CALLED!!
********************************
********************************
Close CALLED!!
********************************
162000
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Ed ecco il codice della classe SQLConnection:
class SqlConnection
{
private final String connectionString;
private Connection connection;
public SqlConnection(String connectionString) {
this.connectionString = connectionString;
}
public synchronized Connection currentConnection() throws SQLException {
if (this.connection == null || this.connection.isClosed()) {
this.closeConnection();
this.connection = DriverManager.getConnection(connectionString);
}
return this.connection;
}
protected void finalize() throws Throwable {
try {
System.out.println("********************************");
System.out.println("Finalizer CALLED!!");
System.out.println("********************************");
this.close();
} finally {
super.finalize();
}
}
public void close() {
System.out.println("********************************");
System.out.println("Close CALLED!!");
System.out.println("********************************");
this.closeConnection();
}
protected void closeConnection() {
if (this.connection != null) {
try {
connection.close();
} catch (Throwable e) {
} finally {
this.connection = null;
}
}
}
}
Non stai stampando il messaggio in 'finalize()', lo stai stampando in 'close()', e stai chiamando 'close()' te stesso. Sposta il messaggio nel finalizzatore stesso e riprova. – skaffman
Dovresti pubblicare una domanda a parte per il tuo aggiornamento. –
@skaffman: dovrei rimuovere il close() dal main. Il problema persiste ancora. –