日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

通过ClassLoader调用外部jar包

發布時間:2023/12/13 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 通过ClassLoader调用外部jar包 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
通過ClassLoader調用外部jar包

我們大家都知道,每個運行中的線程都有一個成員contextClassLoader,用來在運行時動態地載入其它類。

系統默認的contextClassLoader是systemClassLoader,所以一般而言java程序在執行時可以使用JVM自帶的類、$JAVA_HOME/jre/lib/ext/中的類和$CLASSPATH/中的類,對于非默認的jar,一般只能手動在配置環境添加。

但事實上,我們可以通過Thread.currentThread().setContextClassLoader()更改當前線程的contextClassLoader行為,實現在程序內加載外部jar。

PS:
ClassLoader的工作原理是:
1) 線程需要用到某個類時,contextClassLoader將被請求來載入該類
2) contextClassLoader請求它的父ClassLoader來完成該載入請求
3) 如果父ClassLoader無法載入類,則contextClassLoader試圖自己來載入



package?org.loon.framework.jar;

/**?*//**
?*?<p>Title:?LoonFramework</p>
?*?<p>Description:JarLoader,用于jar包的外部操作</p>
?*?<p>Copyright:?Copyright?(c)?2007</p>
?*?<p>Company:?LoonFramework</p>
?*?
@author?chenpeng??
?*?@email:ceponline@yahoo.com.cn?
?*?
@version?0.1
?
*/

import?java.io.BufferedInputStream;
import?java.io.ByteArrayInputStream;
import?java.io.ByteArrayOutputStream;
import?java.io.File;
import?java.io.FileInputStream;
import?java.io.FileNotFoundException;
import?java.io.IOException;
import?java.io.InputStream;
import?java.lang.reflect.Method;
import?java.net.MalformedURLException;
import?java.net.URL;
import?java.util.ArrayList;
import?java.util.HashMap;
import?java.util.Hashtable;
import?java.util.jar.JarEntry;
import?java.util.jar.JarInputStream;
import?java.util.jar.Manifest;

public?class?JarLoader?extends?ClassLoader?...{
????
//資源緩存
????public?static?Hashtable?resources?=?new?Hashtable();
?
????
public?static?JarLoader?loader?=?new?JarLoader();

????
public?static?Class?load(byte[]?resource)?throws?Exception?...{
????????
//?主函數所在類全稱
????????String?mainClassName?=?"";
????????
//class資源及實體緩存
????????ArrayList?classNames?=?new?ArrayList();
????????ArrayList?classBuffers?
=?new?ArrayList();
????????
//?存儲依賴類
????????HashMap?depends?=?new?HashMap();
????????
//?將byte[]轉為JarInputStream
????????JarInputStream?jar?=?new?JarInputStream(new?ByteArrayInputStream(
????????????????resource));
????????Manifest?manifest?
=?jar.getManifest();
????????
//?當Main-Class被聲明時,獲得主函數所在類全稱
????????if?(manifest?!=?null)?...{
????????????mainClassName?
=?manifest.getMainAttributes().getValue("Main-Class");
????????}

????????
//?依次獲得對應JAR文件中封裝的各個被壓縮文件的JarEntry
????????JarEntry?entry;
????????
while?((entry?=?jar.getNextJarEntry())?!=?null)?...{
????????????
//?當找到的entry為class時
????????????if?(entry.getName().toLowerCase().endsWith(".class"))?...{
????????????????
//?將類路徑轉變為類全稱
????????????????String?name?=?entry.getName().substring(0,
????????????????????????entry.getName().length()?
-?".class".length()).replace(
????????????????????????
'/',?'.');
????????????????
//?加載該類
????????????????byte[]?data?=?getResourceData(jar);
????????????????
//?緩存類名及數據
????????????????classNames.add(name);
????????????????classBuffers.add(data);

????????????}
?else?...{
????????????????
//?非class結尾但開頭字符為'/'時
????????????????if?(entry.getName().charAt(0)?==?'/')?...{
????????????????????resources.put(entry.getName(),?getResourceData(jar));
????????????????
//?否則追加'/'后緩存????
????????????????}
?else?...{
????????????????????resources.put(
"/"?+?entry.getName(),?getResourceData(jar));
????????????????}

????????????}

????????}

????????
//當獲得的main-class名不為空時
????????while?(classNames.size()?>?0)?...{
????????????
//獲得類路徑全長
????????????int?n?=?classNames.size();
????????????
for?(int?i?=?classNames.size()?-?1;?i?>=?0;?i--)?...{
????????????????
try?...{
????????????????????
//查詢指定類
????????????????????loader.defineClass((String)?classNames.get(i),
????????????????????????????(
byte[])?classBuffers.get(i),?0,
????????????????????????????((
byte[])?classBuffers.get(i)).length);
????????????????????
//獲得類名
????????????????????String?pkName?=?(String)?classNames.get(i);
????????????????????
if?(pkName.lastIndexOf('.')?>=?0)?...{
????????????????????????pkName?
=?pkName
????????????????????????????????.substring(
0,?pkName.lastIndexOf('.'));
????????????????????????
if?(loader.getPackage(pkName)?==?null)?...{
????????????????????????????loader.definePackage(pkName,?
null,?null,?null,
????????????????????????????????????
null,?null,?null,?null);
????????????????????????}

????????????????????}

????????????????????
//查詢后刪除緩沖
????????????????????classNames.remove(i);
????????????????????classBuffers.remove(i);
????????????????}
?catch?(NoClassDefFoundError?e)?...{
????????????????????depends.put((String)?classNames.get(i),?e.getMessage()
????????????????????????????.replaceAll(
"/",?"."));
????????????????}
?catch?(UnsupportedClassVersionError?e)?...{
????????????????????
//jre版本錯誤提示
????????????????????throw?new?UnsupportedClassVersionError(classNames.get(i)
????????????????????????????
+?",?"?+?System.getProperty("java.vm.name")?+?"?"
????????????????????????????
+?System.getProperty("java.vm.version")?+?")");
????????????????}

????????????}

????????????
if?(n?==?classNames.size())?...{
????????????????
for?(int?i?=?0;?i?<?classNames.size();?i++)?...{
????????????????????System.err.println(
"NoClassDefFoundError:"
????????????????????????????
+?classNames.get(i));
????????????????????String?className?
=?(String)?classNames.get(i);
????????????????????
while?(depends.containsKey(className))?...{
????????????????????????className?
=?(String)?depends.get(className);
????????????????????}

????????????????}

????????????????
break;
????????????}

????????}

????????
try?...{
????????????
//加載
????????????Thread.currentThread().setContextClassLoader(loader);
????????????
//?獲得指定類,查找其他類方式相仿
????????????return?Class.forName(mainClassName,?true,?loader);
????????}
?catch?(ClassNotFoundException?e)?...{
????????????String?className?
=?mainClassName;
????????????
while?(depends.containsKey(className))?...{
????????????????className?
=?(String)?depends.get(className);
????????????}

????????????
throw?new?ClassNotFoundException(className);
????????}

????}


????
/**?*//**
?????*?獲得指定路徑文件的byte[]形式
?????*?
@param?name
?????*?
@return
?????
*/

????
final?static?public?byte[]?getDataSource(String?name)?...{
????????FileInputStream?fileInput;
????????
try?...{
????????????fileInput?
=?new?FileInputStream(new?File(name));
????????}
?catch?(FileNotFoundException?e)?...{
????????????fileInput?
=?null;
????????}

????????BufferedInputStream?bufferedInput?
=?new?BufferedInputStream(fileInput);
????????
return?getDataSource(bufferedInput);
????}

????
????
/**?*//**
?????*?獲得指定InputStream的byte[]形式
?????*?
@param?name
?????*?
@return
?????
*/

????
final?static?public?byte[]?getDataSource(InputStream?is)?...{
????????
if?(is?==?null)?...{
????????????
return?null;
????????}

????????ByteArrayOutputStream?byteArrayOutputStream?
=?new?ByteArrayOutputStream();
????????
byte[]?arrayByte?=?null;
????????
try?...{
????????????
byte[]?bytes?=?new?byte[8192];
????????????bytes?
=?new?byte[is.available()];
????????????
int?read;
????????????
while?((read?=?is.read(bytes))?>=?0)?...{
????????????????byteArrayOutputStream.write(bytes,?
0,?read);
????????????}

????????????arrayByte?
=?byteArrayOutputStream.toByteArray();
????????}
?catch?(IOException?e)?...{
????????????
return?null;
????????}
?finally?...{
????????????
try?...{
????????????????
if?(byteArrayOutputStream?!=?null)?...{
????????????????????byteArrayOutputStream.close();
????????????????????byteArrayOutputStream?
=?null;
????????????????}

????????????????
if?(is?!=?null)?...{
????????????????????is.close();
????????????????????is?
=?null;
????????????????}


????????????}
?catch?(IOException?e)?...{
????????????}

????????}

????????
return?arrayByte;
????}


????
/**?*//**
?????*?獲得指定JarInputStream的byte[]形式
?????*?
@param?jar
?????*?
@return
?????*?
@throws?IOException
?????
*/

?????
final?static?private?byte[]?getResourceData(JarInputStream?jar)
????????????
throws?IOException?...{
????????ByteArrayOutputStream?data?
=?new?ByteArrayOutputStream();
????????
byte[]?buffer?=?new?byte[8192];
????????
int?size;
????????
while?(jar.available()?>?0)?...{
????????????size?
=?jar.read(buffer);
????????????
if?(size?>?0)?...{
????????????????data.write(buffer,?
0,?size);
????????????}

????????}

????????
return?data.toByteArray();
????}


?????
/**?*//**
??????*?重載的getResource,檢查是否重復包含
??????
*/

????
public?URL?getResource(String?name)?...{
????????
if?(resources.containsKey("/"?+?name))?...{
????????????
try?...{
????????????????
return?new?URL("file:///"?+?name);
????????????}
?catch?(MalformedURLException?e)?...{
????????????????e.printStackTrace();
????????????}

????????}

????????
return?super.getResource(name);
????}


????
/**?*//**
?????*?執行指定class類
?????*?
@param?clz
?????*?
@param?methodName
?????*?
@param?args
?????
*/

????
public?static?void?callVoidMethod(Class?clz,?String?methodName,
????????????String[]?args)?
...{
????????Class[]?arg?
=?new?Class[1];
????????arg[
0]?=?args.getClass();
????????
try?...{
????????????Method?method?
=?clz.getMethod(methodName,?arg);
????????????Object[]?inArg?
=?new?Object[1];
????????????inArg[
0]?=?args;
????????????method.invoke(clz,?inArg);
????????}
?catch?(Exception?e)?...{
????????????System.err.println(e.getMessage());
????????}

????}

????
?????
/**?*//**
??????*?重載的getResourceAsStream,檢查是否重復包含
??????
*/

????
public?InputStream?getResourceAsStream(String?name)?...{
????????
if?(name.charAt(0)?==?'/')?...{
????????????name?
=?name.substring(1);
????????}

????????
if?(resources.containsKey("/"?+?name))?...{
????????????
return?new?ByteArrayInputStream((byte[])?resources.get("/"?+?name));
????????}

????????
return?super.getResourceAsStream(name);
????}


}


運行示例:

package?org.loon.framework.jar;


/**?*//**
?*?<p>
?*?Title:?LoonFramework
?*?</p>
?*?<p>
?*?Description:從外部啟動jar包
?*?</p>
?*?<p>
?*?Copyright:?Copyright?(c)?2007
?*?</p>
?*?<p>
?*?Company:?LoonFramework
?*?</p>
?*?
?*?
@author?chenpeng
?*?@email:ceponline@yahoo.com.cn
?*?
@version?0.1
?
*/

public?class?JarTest?...{

????
public?static?void?main(String[]?args)?...{
????????
//將jar包轉為byte[]
????????byte[]?resource?=?JarLoader.getDataSource("D:/fps_test.jar");
????????
try?...{
????????????
//通過byte[]獲得主函數所在類
????????????Class?clz?=?JarLoader.load(resource);
????????????
//調用main函數
????????????JarLoader.callVoidMethod(clz,?"main",?new?String[]?...{""});
????????}
?catch?(Exception?e)?...{
????????????e.getStackTrace();
????????}


????}


}


這時即使指定jar包沒有被我們添加到lib中,程序依舊被順利啟動了。

但是有個缺點,在沒有優化的前提下,這種直接加載外部包的速度在jvm會有很大損耗。

我們可以看到,fps值降低到正常值的50%左右(此fps實例見我CSDN以前的文章),所以并不適合直接運用在需要復雜運算的jar中類調用上(當然,有興趣的話,可以在代碼中優化,我自己在項目中寫的另一個例子速度明顯比這個快)。但是對于運算量小的外部jar調用,還是很方便的。 posted on 2007-11-12 15:38 cping 閱讀(...) 評論(...) 編輯 收藏

轉載于:https://www.cnblogs.com/cping1982/archive/2007/11/12/2258094.html

總結

以上是生活随笔為你收集整理的通过ClassLoader调用外部jar包的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。