作者sbrhsieh (十年~)
看板java
标题Re: [问题] 在物件被注销时自动执行某些事
时间Sun Jun 17 16:36:23 2012
我的理解是:有些物件会占用一部分有限的资源,如果在释放对这些物件的
reference 之前没有先行释放占用的资源,在这些物件尚未被 JVM reclaim 之前,
被占用的资源就无法再利用。这是你想要解决的问题。
若你真有难处无法要求他人去遵守/实现前几篇由版友建议的 convention/pattern(
设计层面的解法),我这一篇想提供比较偏向系统面(工程面的做法<-若形容的不好
请见谅),至於提到的做法是否会比之前版友的建议好,甚至是不是真的可行,我想
这对你来说应该也不是挺重要的。
之前你有提到是否有办法自己去做 reference counting,是可以让 agent 透过
JVMTI 来获得关於 heap 里的 object graph 的资讯,不过 JVMTI 这把刀太大了
一点,不提。
另外的考量是利用 bytecode engineering 或 AOP(Aspect-Oriented Programming),
自己以前者从头搞起会太累,暂时也不提。相较於泛 bytecode engineering 高阶的
AOP 我觉得有他的可行性在,policy enforcement 本来就是 AOP 常被用来实现的事
之一,如果遵守 convention/pattern 看成是一种 policy,那麽 AOP 这时候就可能
有他的用处。此处要提的就是若采用 AOP 来挤出一个解法之下我的想法。
现把问题缩小集中在有限的资源是 java.sql.Connection 实际所建立的连线,要克服
有些人不小心忘了执行 Connection::close 的操作或不把它当一回事,希望透过 AOP
来强制 Connection object 不再使用了就一定要 close。
我想要使用 AOP 来达到一个简单的 manually reference counting 的机制:
1. 当一个 Connection object reference 被存到任何的 class/object 的
field 里表示这个 Connection 被 retain(reference count + 1)。反之,
有存 Connection reference 的 field 被设值为 null 或被其他值覆盖,
表示原来所参照的 Connection 被 release(reference count - 1)。
至於被放到 local variable/array cell 里,暂时不管;持有 Connection
reference 的 object 是否是 strongly reachable、是否被销毁回收了也
暂时不管。
2. 这个 reference counting 机制只作用在 Connection 被取出之後到执行
close 之前。
3. 如果一个 Connection 建构所处的 method 结束,若其 reference count
为 0 则对其做 close 操作。
4. 若进行 Connection 取出的 thread 已经终结,那麽在 Connection 的
reference count 降为 0 时,对其做 close 操作。
以 AOP 来实现,大约可以这麽做:
A. 拦截取出 Connection object 的操作,纪录(thread local)所在的 thread
与 stack depth(见下一项)。
B. 拦截每一个 method,用来纪录 call depth(这个 depth 不是绝对的,它
跟你 weave 了哪些 class 有关),当这个 depth 小於 Connection 取出时的 depth
就表示取出时所在的 method(caller) 已结束。并检查是否有 Connection 需要
close。
C. 拦截对每一个 Connection type field 的存取,用来更新 reference count,
必要时 close Connection。
D. 拦截对 Connection 的 close 操作。一旦某个 Connection 已进行过 close
操作就不再监视之。
若以 Eclipse 的 AspectJ 来实做上述的功能,大致上会是这样子:
http://ideone.com/QXadU
我自己没有做很多测试,可能尚有许多细节没注意到,而他所能 handle 的情况
也故意设计的很单纯,但也不是完全的 trivial。
注1:
这个部份应该依照贵专案中的程式所采取的取得 Connection 方式下去调整。比如
透过 driver manager or connection pool or both。
注2:
目前的写法会拦截送进 weaver 内的每个 class 里的每个 method。应该调整成
专案中可能会使用到 java.sql.Connection 的 class 集合。
注3:
也可以利用这个 advice 来 enfore 其他的 policy,比如:不能自己从 driver
manager 建 connection,只能透过 connection pool 拿。
--
※ 发信站: 批踢踢实业坊(ptt.cc)
◆ From: 218.173.82.52
1F:推 PsMonkey:那些「暂时不提」的东西可以哪天来提一下吗? Orz 06/17 16:56
2F:→ bitlife:其实connection pool更重要的一个功能刚好是'不close'连线 06/17 17:13
3F:→ sbrhsieh:在这里 close 指的是实际断了 network connection 或 06/17 17:17
4F:→ sbrhsieh:归还给 pool。pool 里的东西算是有限的资源。 06/17 17:20
5F:推 LaPass:谢谢回答 m(_ _)m 06/17 19:11
※ 编辑: sbrhsieh 来自: 218.173.112.28 (06/17 20:28)