參考了幾篇文章
載入jar包的類URLClassLoader中使用的方法為addURL,但是這個方法是protected類型
分別用了兩種方法
一、
參考 http://blog.csdn.net/ozwarld/article/details/7440937
反射到這個類
Method add = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class }); add.setAccessible(true);
然後再執行add載入jar包,之後再次反射擷取需要執行的類
URLClassLoader classloader = (URLClassLoader)ClassLoader.getSystemClassLoader(); URL url = new File(jarPath).toURI().toURL();add.invoke(classloader, new Object[] { url }); Class<?> clazz = Class.forName(className);Method method = clazz.getDeclaredMethod("xxxx");method.invoke(clazz.newInstance());
最開始使用的是下面的方法,感覺簡單,但是由於沒設定parentClassLoader,導致出現各種bug,最後雖然調通了,但是依然選擇了上面的方法(不確定是否還有其他問題)
二、
參考的http://www.cnblogs.com/flyingzl/articles/3139028.html
文章中先建立個子類,這樣可以執行addURL這個方法了
static class MyClassLoader extends URLClassLoader { public MyClassLoader(URL[] urls) { super(urls); } public MyClassLoader(URL[] urls, ClassLoader parent) { super(urls, parent); } public void addJar(URL url) { this.addURL(url); } }
載入jar,並執行
URL[] urls = new URL[] {}; MyClassLoader classLoader = new MyClassLoader(urls,ClassLoader.getSystemClassLoader()) try { classLoader.addJar(new File("c:/hello.jar").toURI().toURL()); Class<?> clazz = classLoader.loadClass("pakcagename.classname"); Method method = clazz.getDeclaredMethod("run"); method.invoke(clazz.newInstance()); classLoader.close(); } catch (Exception e) { e.printStackTrace(); }
另、
如果是本地jar的話,這樣就ok了,在hdfs上的話,會有點問題,URL不支援hdfs協議
URL.setURLStreamHandlerFactory(new FsUrlStreamHandlerFactory());
這樣就支援hdfs協議了,path就可以轉url了,當然,得載入下hdfs相關設定檔,擷取FileSystem執行個體
Path path = fs.getFileStatus(new Path(jarPath)).getPath();URL url = path.toUri().toURL();classLoader.addJar(url);
只運行普通jar的話,在hdfs上是可以的
但是
如果載入的是mapreduce程式的jar包,只能是本地路徑,不能使用hdfs路徑,在setJarByClass方法中,是需要尋找到jar包絕對路徑的
----------------------------------------------
使用一段時間後發現,進程是不停的,需要載入的jar包是可能需要修改的,所以導致多次載入不同版本的jar包之後,程式會有bug,讀不到最新的jar包,不太可能更新jar包就重啟下程式
於是,又研究了下classloarder,在當前線程載入jar包比較保險,線程結束會釋放掉,保證每次載入都是最新的,而且也不佔記憶體
(URLClassLoader)ClassLoader.getSystemClassLoader();
改為當前線程類載入器
(URLClassLoader)Thread.currentThread().getContextClassLoader();