作者brianhsu (坟墓)
看板java
标题Re: [问题] 在物件被注销时自动执行某些事
时间Thu Jun 14 10:50:18 2012
※ 引述《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)
1F:推 LaPass:谢谢 try-with-resource我在C#中有用过,那没办法达到我想 06/14 11:49
2F:→ LaPass:要的功能。 06/14 11:51
3F:→ adrianshum:你看任何一本入门书都会告诉你,不要依赖 finalize 06/14 22:29
4F:→ adrianshum:作为万一没清理时作最後安全网是可以,依靠它则不可 06/14 22:30
5F:推 LaPass:有时候,方法是会越找越奇怪的..... 06/14 23:57
6F:→ LaPass:我还蛮铁齿的,别人或是书上说不行,我会去搞懂为什麽不行 06/15 00:01
7F:→ LaPass:,而不是没搞懂就跟着说不行。 06/15 00:03
上面就已经很多人和你说过「为什麽」了,甚至我也给了你 code 告诉你:
Java 里的 GC / finalize 不一定会执行 ==> connection 不一定会关闭
这句话就算你用 System.gc() 也一样,因为
就算系统里有垃圾物件,
System.gc() 仍然不保证会叫醒 GC,呼叫这个函式却啥都没发生的情形
也很多。
如果你还要坚持依赖这种不一定会执行的东西,来处理理论上一定要执行
的动作,那我也无话可说了……orz.
8F:→ dou0228:你是因为一堆人没照着规矩,才会想用这种方法吧.. 06/15 00:16
9F:→ dou0228:如果是别人不照规矩,你也只能确定自己有 close 就好 06/15 00:18
10F:→ dou0228:在GC/Reference上动手脚,只会让你延後遇到问题,不是解决 06/15 00:21
11F:推 Chikei:那你需要的是搞懂java物件生命周期跟GC大致上是怎麽实作的. 06/15 01:37
12F:→ Chikei:搞懂这两个自然就不会去期待让java在销毁物件时做事 06/15 01:41
※ 编辑: brianhsu 来自: 220.137.22.123 (06/15 08:58)
13F:推 LaPass:看到上一篇那几条挂着一个多小时的连线,应该就没人会想靠 06/15 09:34
14F:→ LaPass:GC去清东西了啦..... 06/15 09:36
15F:→ LaPass:还有,我不是坚持依赖那种方法,而是去想各种解决方法的可 06/15 09:49
16F:→ LaPass:行性。 06/15 09:50
17F:→ qrtt1:不去导正观念就只能在 work around 生态系下打泥巴战了。 06/15 09:55
18F:推 LaPass:qrtt1,现有的方法我知道,但是我想找其他方法,如此而已。 06/15 10:06
19F:→ qrtt1:其他方法那就是统一管理了,我们这其他人写 query 都不会摸 06/15 10:13
20F:→ qrtt1:到 Connection, Statement, ResultSet 只有 sql 跟吐回 data 06/15 10:14
21F:→ qrtt1:资料库看起来异常就直接修 library 更新上去就好了。 06/15 10:15
22F:推 PsMonkey:如果你想找其他方法,那提出来的假说也不要抵触已知 06/15 10:17
23F:→ askeing:想找其他方法之前先搞懂生命周期跟GC机制… 06/15 11:53
24F:推 LaPass:如果是每本JAVA书的开头那一两章的内容,我已经看过很多次 06/15 12:42
25F:→ LaPass:。但是还是会想去挖挖看有没有自己不知道例外状况,例如, 06/15 12:45
26F:→ LaPass:「JAVA其实有提供干预生命周期的机制」之类的,可惜没有。 06/15 12:46