java實現動態加載jar包中的class(破壞雙親委派來實現)

背景

最近在項目中在使用Drools來做規則,drools確實功能比較強大,但是學習成本也比較高,語法比較繁瑣。我們項目是做的動態規則,用戶可以通過上傳jar包的方式來動態的再我們ruleengine service中生成規則,然後通過restful的方式來rule規則。在jar包中包含了需要用戶自定義的pojo和用戶配置的excel,這個excel就是drools的desicion table,有興趣的可以去drool瞭解,這裏不做過多的描述。

遇到的問題

上面講了一個規則jar包中包含了pojo,那麼比如用戶更改了pojo的字段,那麼這個class需要jvm重新來加載,那麼問題就來了,我們都知道jvm加載一個類需要經過加載,驗證,解析,卸載啊 這些階段,而且基於雙親委派原則,就是說,優先父類來加載,只要這個class在父類的scope,就父類加載,父類加載不到就交給子類加載,那麼在加載的時候只要發現這個類被加載過了,就會使用加載的cache,不會再次重新加載。

解決方案

我當時的思路是先讓jvm卸載這個class,然後再重新加載,但是呢我們知道就算我們調用的Syatem.gc();這是也不會馬上執行GC的,跑垃圾回收我們控制不了,還有個問題就是我當時對雙親委派不太瞭解(哈啊哈,看來還需要花更多的時間來學習JVM),錯誤地以爲用一個相同的classloader去加載class,就會覆蓋之間所加載的,這個錯誤的方向也讓我陷入了死衚衕,這個根本行不通。後來經過study,我找到了解決辦法。
就是我們需要自己實現一個classloader來加載class,把每次加載好的class存在一個cache的concurrenthashmap裏面。key就是package+classname,value就是自己實現的classloader加載之後的Object對象,這樣我們每次使用就用package+classname的key去get出具體的Object對象,如果使用URLClassloader或者Classloader類來加載的話始終都是遵循了雙親委派原則,會加載在之前的cache。通過自己實現classloader和把加載後的對象存cache存儲在map的方式,解決更新class的問題。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章