Java Class的热替换 自定义ClassLoader加载.class
生活随笔
收集整理的這篇文章主要介紹了
Java Class的热替换 自定义ClassLoader加载.class
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
? ? 本文是java熱替換的實驗,參考了
Java 類的熱替換 —— 概念、設計與實現(xiàn)
http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls/index.html。
之前的錯誤是,沒有集成ClassLoader,而是直接使用了
[java]?view plaincopyclassloader?=?(URLClassLoader)ClassLoader.getSystemClassLoader();?? ? ? 這個語句只適用于加載.jar
? ? 如果加載.class的話需要使用自定義的ClassLoader
[java]?view plaincopypackage?yerasel;?? ?? import?java.io.BufferedReader;?? import?java.io.File;?? import?java.io.FileInputStream;?? import?java.io.FileNotFoundException;?? import?java.io.IOException;?? import?java.io.InputStream;?? import?java.io.InputStreamReader;?? import?java.lang.reflect.Field;?? import?java.lang.reflect.InvocationTargetException;?? import?java.lang.reflect.Method;?? ?? import?java.net.MalformedURLException;?? import?java.net.URL;?? import?java.net.URLClassLoader;?? import?java.util.HashSet;?? ?? /*? ?*??實現(xiàn)熱部署,自定義ClassLoader,加載的是.class? ?*/?? class?HowswapCL?extends?ClassLoader?{?? ?? ????private?String?basedir;?//?需要該類加載器直接加載的類文件的基目錄?? ????private?HashSet?dynaclazns;?//?需要由該類加載器直接加載的類名?? ?? ????public?HowswapCL(String?basedir,?String[]?clazns)?{?? ????????super(null);?//?指定父類加載器為?null?? ????????this.basedir?=?basedir;?? ????????dynaclazns?=?new?HashSet();?? ????????loadClassByMe(clazns);?? ????}?? ?? ????private?void?loadClassByMe(String[]?clazns)?{?? ????????for?(int?i?=?0;?i?<?clazns.length;?i++)?{?? ????????????loadDirectly(clazns[i]);?? ????????????dynaclazns.add(clazns[i]);?? ????????}?? ????}?? ?? ????private?Class?loadDirectly(String?name)?{?? ????????Class?cls?=?null;?? ????????StringBuffer?sb?=?new?StringBuffer(basedir);?? ????????String?classname?=?name.replace('.',?File.separatorChar)?+?".class";?? ????????sb.append(File.separator?+?classname);?? ????????File?classF?=?new?File(sb.toString());?? ????????try?{?? ????????????cls?=?instantiateClass(name,?new?FileInputStream(classF),?? ????????????????????classF.length());?? ????????}?catch?(FileNotFoundException?e)?{?? ????????????//?TODO?Auto-generated?catch?block?? ????????????e.printStackTrace();?? ????????}?? ????????return?cls;?? ????}?? ?? ????private?Class?instantiateClass(String?name,?InputStream?fin,?long?len)?{?? ????????byte[]?raw?=?new?byte[(int)?len];?? ????????try?{?? ????????????fin.read(raw);?? ????????????fin.close();?? ????????}?catch?(IOException?e)?{?? ????????????//?TODO?Auto-generated?catch?block?? ????????????e.printStackTrace();?? ????????}?? ?? ????????return?defineClass(name,?raw,?0,?raw.length);?? ????}?? ?? ????protected?Class?loadClass(String?name,?boolean?resolve)?? ????????????throws?ClassNotFoundException?{?? ????????Class?cls?=?null;?? ????????cls?=?findLoadedClass(name);?? ????????if?(!this.dynaclazns.contains(name)?&&?cls?==?null)?? ????????????cls?=?getSystemClassLoader().loadClass(name);?? ????????if?(cls?==?null)?? ????????????throw?new?ClassNotFoundException(name);?? ????????if?(resolve)?? ????????????resolveClass(cls);?? ????????return?cls;?? ????}?? }?? ?? /*? ?*?每隔500ms運行一次,不斷加載class? ?*/?? class?Multirun?implements?Runnable?{?? ????public?void?run()?{?? ????????try?{?? ????????????while?(true)?{?? ????????????????//?每次都創(chuàng)建出一個新的類加載器?? ????????????????//?class需要放在自己package名字的文件夾下?? ????????????????String?url?=?System.getProperty("user.dir")?+?"/lib";//?"/lib/yerasel/GetPI.jar";?? ????????????????HowswapCL?cl?=?new?HowswapCL(url,?? ????????????????????????new?String[]?{?"yerasel.GetPI"?});?? ????????????????Class?cls?=?cl.loadClass("yerasel.GetPI");?? ????????????????Object?foo?=?cls.newInstance();?? ????????????????//?被調用函數(shù)的參數(shù)?? ????????????????Method?m?=?foo.getClass().getMethod("Output",?new?Class[]?{});?? ????????????????m.invoke(foo,?new?Object[]?{});?? ????????????????Thread.sleep(500);?? ????????????}?? ?? ????????}?catch?(Exception?ex)?{?? ????????????ex.printStackTrace();?? ????????}?? ????}?? }?? ?? public?class?Test?{?? ?? ????public?static?Method?initAddMethod()?{?? ????????try?{?? ????????????Method?add?=?URLClassLoader.class.getDeclaredMethod("addURL",?? ????????????????????new?Class[]?{?URL.class?});?? ????????????add.setAccessible(true);?? ????????????return?add;?? ????????}?catch?(Exception?e)?{?? ????????????throw?new?RuntimeException(e);?? ????????}?? ????}?? ?? ????public?static?void?main(String[]?args)?{?? ?? ????????//?熱部署測試代碼?? ????????Thread?t;?? ????????t?=?new?Thread(new?Multirun());?? ????????t.start();?? ????}?? } ?
package?yerasel;?? ?? import?java.io.PrintStream;?? ?? public?class?GetPI?? {?? ??public?static?double?Darts(int?n)?? ??{?? ????int?k?=?0;?? ????double?x?=?0.0D;?? ????double?y?=?0.0D;?? ????for?(int?i?=?0;?i?<?n;?i++)?? ????{?? ??????x?=?Math.random();?? ??????y?=?Math.random();?? ?? ??????if?(x?*?x?+?y?*?y?<=?1.0D)?? ????????k++;?? ????}?? ????return?4?*?k?/?n;?? ??}?? ??//?本熱部署實驗中,上面的Darts函數(shù)沒有用到,請忽略?? ??public?static?void?Output()?{?? ????System.out.println("Output");?? ??}?? } ?
? ? 另一個GetPI.java只在輸出時候改為aaaOutput
jar?cvf?GetPI.jar?GetPI.class??
[java]?view plaincopy
? ? GetPI.Java內容:
[java]?view plaincopy? ? 生成jar包的命令
[java]?view plaincopy
? ? 一定要注意的是:class需要放在package名字的文件夾下
? ? 本文中.class放在/lib(自定義路徑)/yerasel(package名字)下。
? ? 運行時候,程序加載指定文件夾下的.class,即開始輸出aaaOutput,然后手動將另外一個.class(輸出Output的.class)覆蓋此文件,
? ? 程序立即開始輸出Output
? ? 運行結果圖:
? ??
新人創(chuàng)作打卡挑戰(zhàn)賽發(fā)博客就能抽獎!定制產品紅包拿不停!總結
以上是生活随笔為你收集整理的Java Class的热替换 自定义ClassLoader加载.class的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nyoj 211 (Floyd算法求传递
- 下一篇: nyoj99(欧拉路)