Re: [問題] 在物件被註銷時自動執行某些事
※ 引述《LaPass (LaPass)》之銘言:
: 後來把那個Conn改成動態欄位,並呼叫System.gc()之後
: 連線就會被釋放了,這時候finalize也會被呼叫
這個叫你運氣好……
: 基本上是不用擔心連線被卡住的問題
: 只是系統的GC時間點.....
只要你的 JVM 還活著,RAM 又夠大,GC 可能根本就懶得回收物件。
: 也看過activity關閉重新打開之後,上次設定的static欄位的值還在之類的狀況
static 的存活和物件 instance 本來就不同,他只要 Class(不是 object) 被載
入之後就會一直在,你 activity 關掉頂多是 Activity 物件被消滅,和 static
無關。
: 我猜這跟平台的運作有關係
: 所以我不確定依靠GC去關Connection,會不會遇到什麼問題
會遇到很大、很大、很大的問題,就像有版友推文說的一樣,這幾乎等於是找
死,真的不推薦這樣做。
Java 裡面物件的消滅是 GC 在處理的,而 GC 的一個特性是你永遠不知道他什
麼時候會執行,甚至是他會不會去回收,把 conn.close() 放在 finalize() 裡
面,等於是在賭博,賭你的 JVM 會在 Connection 爆掉前回收物件,而這是很
危險的。
如果你的 RAM 夠大,JVM 活的夠久,物件不被消滅而一直佔著 Connection 的
毛坑卻不拉屎的機率是很高的,例如下面的程式碼多少可以看出這個狀況:
class Resource
{
static int counter;
int resID = 0;
public Resource()
{
resID = counter;
counter++;
}
public void doSomething()
{
System.out.println("Do something:" + resID);
}
@Override
protected void finalize() throws Throwable
{
System.out.println("Cleanup Resource:" + resID);
}
}
class Test
{
public static void allocateResource()
{
// 理論上 allocateResource() 執行完,Resource 物件就可以被回收
Resource r = new Resource();
r.doSomething();
r = null;
}
public static void main(String [] args) throws Exception
{
for (int i = 0; i < 100; i++) {
allocateResource();
}
// 讓 JVM 一直活著
while (true) {
Thread.sleep(1000);
}
}
}
你會發現理論上我們創造出來的一百個 Resource 物件都是可以回收的狀態,但
大部份的情況下,finalize() 根本不會去執行。
至於你一直提的到 System.gc(),JavaDoc 中講得很清楚,他是 suggest GC,
不是 force GC,你不能假設他一定會回收所有的垃圾物件。
而且現在寫 Java,幾乎都會告訴你不要使用 System.gc(),因為通常他只會托
慢你程式的速度,停下來做不一定需要做的 GC。
最後,JVM 的工程師都已經告訴你 (http://youtu.be/mumvD0r7IH4?t=25m32s)
:
- Finalizer are evil
- System.gc() is just as bad
幹嘛還要那麼堅持用這兩個東西啊……
如果不想用 connection pool,又覺得自己很容易忘記 close 掉資源的話,請使
用 Java 7 的 try-with-resource 這個好朋友,又或者自己寫一個 wrapper 就
好啦。
這兩個都比依懶具有不確定性的 System.gc() 和 finalize() 好多了。
--
~ 白馬帶著她一步步地回到中原。白馬已經老了,只能慢慢地走,
'v' Brian Hsu 但終是能回到中原的。江南有楊柳、桃花,有燕子、金魚……
// \\ ( 墳 墓 )
/( )\ 但這個美麗的姑娘就像古高昌國人那樣固執。 【白馬嘯西風】
^`~'^
http://bone.twbbs.org.tw/blog 『那都是很好很好的,可我偏不喜歡。』
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 140.109.19.224
※ 編輯: brianhsu 來自: 140.109.19.224 (06/14 10:52)
推
06/14 11:49, , 1F
06/14 11:49, 1F
→
06/14 11:51, , 2F
06/14 11:51, 2F
→
06/14 22:29, , 3F
06/14 22:29, 3F
→
06/14 22:30, , 4F
06/14 22:30, 4F
推
06/14 23:57, , 5F
06/14 23:57, 5F
→
06/15 00:01, , 6F
06/15 00:01, 6F
→
06/15 00:03, , 7F
06/15 00:03, 7F
上面就已經很多人和你說過「為什麼」了,甚至我也給了你 code 告訴你:
Java 裡的 GC / finalize 不一定會執行 ==> connection 不一定會關閉
這句話就算你用 System.gc() 也一樣,因為 就算系統裡有垃圾物件,
System.gc() 仍然不保證會叫醒 GC,呼叫這個函式卻啥都沒發生的情形
也很多。
如果你還要堅持依賴這種不一定會執行的東西,來處理理論上一定要執行
的動作,那我也無話可說了……orz.
→
06/15 00:16, , 8F
06/15 00:16, 8F
→
06/15 00:18, , 9F
06/15 00:18, 9F
→
06/15 00:21, , 10F
06/15 00:21, 10F
推
06/15 01:37, , 11F
06/15 01:37, 11F
→
06/15 01:41, , 12F
06/15 01:41, 12F
※ 編輯: brianhsu 來自: 220.137.22.123 (06/15 08:58)
推
06/15 09:34, , 13F
06/15 09:34, 13F
→
06/15 09:36, , 14F
06/15 09:36, 14F
→
06/15 09:49, , 15F
06/15 09:49, 15F
→
06/15 09:50, , 16F
06/15 09:50, 16F
→
06/15 09:55, , 17F
06/15 09:55, 17F
推
06/15 10:06, , 18F
06/15 10:06, 18F
→
06/15 10:13, , 19F
06/15 10:13, 19F
→
06/15 10:14, , 20F
06/15 10:14, 20F
→
06/15 10:15, , 21F
06/15 10:15, 21F
推
06/15 10:17, , 22F
06/15 10:17, 22F
→
06/15 11:53, , 23F
06/15 11:53, 23F
推
06/15 12:42, , 24F
06/15 12:42, 24F
→
06/15 12:45, , 25F
06/15 12:45, 25F
→
06/15 12:46, , 26F
06/15 12:46, 26F
討論串 (同標題文章)
本文引述了以下文章的的內容:
完整討論串 (本文為第 4 之 7 篇):