Re: [問題] 在物件被註銷時自動執行某些事

看板java作者 (十年~)時間13年前 (2012/06/17 16:36), 編輯推噓2(203)
留言5則, 4人參與, 最新討論串7/7 (看更多)
我的理解是:有些物件會占用一部分有限的資源,如果在釋放對這些物件的 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
那些「暫時不提」的東西可以哪天來提一下嗎? Orz
06/17 16:56, 1F

06/17 17:13, , 2F
其實connection pool更重要的一個功能剛好是'不close'連線
06/17 17:13, 2F

06/17 17:17, , 3F
在這裡 close 指的是實際斷了 network connection 或
06/17 17:17, 3F

06/17 17:20, , 4F
歸還給 pool。pool 裡的東西算是有限的資源。
06/17 17:20, 4F

06/17 19:11, , 5F
謝謝回答 m(_ _)m
06/17 19:11, 5F
※ 編輯: sbrhsieh 來自: 218.173.112.28 (06/17 20:28)
文章代碼(AID): #1FtPSBu1 (java)
討論串 (同標題文章)
文章代碼(AID): #1FtPSBu1 (java)