下邊這段代碼的大致邏輯是,在main方法中有兩部分,第一部分是啟動一個子執行緒,這個執行緒會在2小時后,使用自定義的classloader重新加載MyService這個類。第二部分就是在main執行緒中,有一個死回圈,會不斷的呼叫MyService的方法。
如果在1小時后,我們修改了MyService.class中的execute方法。
然后在第二個小時的時候,我們自定義的classloader會主動去加載這個修改后的類檔案。在加載了之后,我們main執行緒中,在new MyService的時候,使用的是新的MyService嗎?
public class App
{
public static void main( String[] args )
{
Thread t = new Thread(()-> {
try {
TimeUnit.HOURS.sleep(2);
} catch (InterruptedException e) {
}
//在睡眠了2個小時后,使用UrlClassloader從硬碟指定路徑加載MyService.class檔案
// UrlClassloader xxx .....
});
t.start();
//xxxxxxx
while(true) {
MyService service = new MyService();
service.execute();
}
}
}
uj5u.com熱心網友回復:
哪位兄弟幫忙看一下?謝謝。uj5u.com熱心網友回復:
已經加載過的應該不會再加載了.如果你要達到熱加載的效果,應該不能這么簡單的玩,按照我的理解,你熱加載成功之后,new不new物件都是不重要的,new之前的物件也是會采用新加載的class的方法區.
可以參考eclipse debug模式下修改代碼能立馬生效,現在都spring環境,物件啟動時就裝配好了
uj5u.com熱心網友回復:
URLClassLoader貌似也是要檢查bootstrap classload之前是否加載,除非你重新寫一個,不做雙親委托,但我估計是不能用new這種方式來創建物件,拿到class反射應該可以確保不是bootstrap classload加載的uj5u.com熱心網友回復:
沒測驗過哈,有空玩一下uj5u.com熱心網友回復:
同一種型別的加載器加載類之后存入快取好像是根據類的名稱來存盤的,findClass時也是根據名稱來查找是否已加載,這樣的話你的兩小時之后的類可能就不會被加載了uj5u.com熱心網友回復:
我理解是舊的,即使你能用自己的類加載器加載進去,App這個類也不會使用你自己加載的MyService, 在虛擬機中類加載器+類的全域限定名會定位到一個類, 你改變了類加載器相當于另外一個類了.例如我們在tomcat中部署兩個相同的應用程式,雖然里面有的類全域限定名(包名+類名)一樣的類,但呼叫時不會出現跨專案呼叫,因為不同專案的類檔案使用了不同的類加載器加載
uj5u.com熱心網友回復:
我也記得是有這樣一個規則,就是優先使用當前加載器進行類的加載。在這里,AppClassLoader加載了我們的main方法所在的App.class.
在執行的程序中,它遇到了MyService這個類,現在代碼執行點處于App.class,而這個類是由AppClassLoader加載的,那么現在就會使用AppClassLoader來加載MyService.class. 即使在另外的執行緒中顯示通過自定義的加載器去加載了這個類,但是在背景關系中也不會被使用。
uj5u.com熱心網友回復:
已經加載過的不會再次加載!自定義的classLoader,加載前會問父加載器AppClassLoader是否能加載,而父加載器會從快取中看,自己是否加載過,如果已經加載過,則不再加載。
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/14652.html
標籤:Java EE
上一篇:我的程式主要是資料庫的增刪改查統計這樣,我看資料說有時要使用TRY進行例外處理,誰能給我舉個例子到底什么時候使用
下一篇:Unity性能優化技巧
