Re: [問題] 在物件被註銷時自動執行某些事
我的理解是:有些物件會占用一部分有限的資源,如果在釋放對這些物件的
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
推
06/17 16:56, , 1F
06/17 16:56, 1F
→
06/17 17:13, , 2F
06/17 17:13, 2F
→
06/17 17:17, , 3F
06/17 17:17, 3F
→
06/17 17:20, , 4F
06/17 17:20, 4F
推
06/17 19:11, , 5F
06/17 19:11, 5F
※ 編輯: sbrhsieh 來自: 218.173.112.28 (06/17 20:28)
討論串 (同標題文章)
完整討論串 (本文為第 7 之 7 篇):