Hãy xem xét một đối tượng khai báo trong một phương pháp:Tại sao một đối tượng được khai báo trong phương thức phải chịu thu gom rác trước khi phương thức trả về?
public void foo() {
final Object obj = new Object();
// A long run job that consumes tons of memory and
// triggers garbage collection
}
sẽ obj bị thu gom rác thải trước foo() trả về?
CẬP NHẬT: Trước đây tôi nghĩ obj là không thuộc đối tượng thu gom rác thải cho đến khi foo() trả về.
Tuy nhiên, hôm nay tôi thấy mình sai.
Tôi đã dành vài giờ để sửa lỗi và cuối cùng phát hiện ra sự cố là do rác thải obj thu thập được!
Có ai giải thích tại sao điều này xảy ra không? Và nếu tôi muốn obj được ghim làm thế nào để đạt được nó?
Đây là mã có sự cố.
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();
}
}
Sau khi chạy chương trình Java, nó sẽ in được thông báo sau trước khi nó bị treo:
161000
161000
********************************
Finalizer CALLED!!
********************************
********************************
Close CALLED!!
********************************
162000
Exception in thread "main" com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Và đây là đoạn code của lớp 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;
}
}
}
}
Bạn không in ra thông báo trong 'finalize()', bạn đang in nó ra trong 'close()', và bạn đang gọi 'close()'. Di chuyển thư vào trình hoàn thiện và thử lại. – skaffman
Bạn nên đăng câu hỏi riêng để cập nhật. –
@skaffman: Tôi nên xóa phần đóng() khỏi chính. Vấn đề vẫn còn tồn tại. –