天天看點

java 動态加載_Java如何在運作時動态加載Jar

導讀:在實際項目開發中,有時會遇到需動态加載jar包的應用場景。如将Flink的UDF自定義方法制作成方法庫(既打成一個Jar),在送出給Flink叢集的Job中動态加載jar便可使用。下面将舉一個簡單實作Java動态加載Jar的例子。環境準備

動态加載Jar實作

解析與拓展

環境準備

為了便于實作Demo,這裡建構一個子產品化Maven項目dynamicloading,項目包含:dyna-loading-function方法庫子產品、dyna-loading-core核心子產品。

java 動态加載_Java如何在運作時動态加載Jar

在dyna-loading-function中編寫方法

編寫一個方法抽象類,及一個實作類Split,class

public abstract class AbstractFunction {

public abstract void eval(String s);

}

public class Split extends AbstractFunction {

@Override

public void eval(String s) {

System.out.println("對字元串"+s+"進行截取操作");

}

}

将dyna-loading-function打成Jar包

java 動态加載_Java如何在運作時動态加載Jar

在dyna-loading-core子產品實作動态加載Jarimport java.io.File;

import java.lang.reflect.Method;

import java.net.URL;

import java.net.URLClassLoader;

public class dynaLoadTest {

public static void main(String[] args) throws Exception{

//jar所在路徑

String jarPath = "C:\\repo\\com\\wxb\\dyna-loading-function\\1.0-SNAPSHOT\\dyna-loading-function-1.0-SNAPSHOT.jar";

loadJar(jarPath);

//利用反射

Class> aClass = Class.forName("function.Split");

Object instance = aClass.newInstance();

//調用方法

aClass.getDeclaredMethod("eval", String.class).invoke(instance,

"hello word");

}

//動态加載Jar

public static void loadJar(String jarPath) {

File jarFile = new File(jarPath);

//檔案存在

if (jarFile.exists() == false) {

System.out.println("jar file not found.");

return;

}

//從URLClassLoader類加載器中擷取類的addURL方法

Method method = null;

try {

method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);

} catch (NoSuchMethodException | SecurityException e1) {

e1.printStackTrace();

}

// 擷取方法的通路權限

boolean accessible = method.isAccessible();

try {

//修改通路權限為可寫

if (accessible == false) {

method.setAccessible(true);

}

// 擷取系統類加載器

URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();

//擷取jar檔案的url路徑

URL url = jarFile.toURI().toURL();

//jar路徑加入到系統url路徑裡

method.invoke(classLoader, url);

} catch (Exception e) {

e.printStackTrace();

} finally {

method.setAccessible(accessible);

}

}

}

運作

java 動态加載_Java如何在運作時動态加載Jar

解析與拓展

ClassLoader是類加載器,其具體作用就是将class檔案加載到jvm虛拟機中去,程式就可以正确運作了。java程式運作的時候,類必須被加載到jvm虛拟機中才可以正常使用。但不是所有的class檔案都在啟動的時候全部加載,根據資料java最早就是為嵌入式系統而設計的,記憶體寶貴。如果開始時就把所有類都加載到jvm中,有些class可能在整個運作過程中都不會被用到,這樣便會占用寶貴的記憶體。是以啟動時會先把保證程式運作的基礎類一次性加載到jvm中,其它class等到jvm用到的時候再通過動态加載将其加載到jvm虛拟中。

java 動态加載_Java如何在運作時動态加載Jar

Java中内置了很多的類加載器,而ClassLoader是所有類加載器的基類,它是個抽象類,其定義了類加載最核心的操作。因本文主題是動态加載Jar,是以下面我們主要讨論URLClassLoader。

java 動态加載_Java如何在運作時動态加載Jar

URLClassLoader

URLClassLoader繼承自SecureClassLoader,支援從jar檔案和檔案夾中擷取class。而SecureClassLoader繼承于ClassLoader。

核心代碼://1、通過getDeclaredMethod擷取URLClassLoader的addURL,這一步的目的是為了設定addURL方法可寫

Method method = URLClassLoader.class.getDeclaredMethod("addURL", URL.class);

method.setAccessible(true);

//2、擷取 URLClassLoader加載器

URLClassLoader classLoader = (URLClassLoader) ClassLoader.getSystemClassLoader();

//3、擷取目标jar的URL

URL url = jarFile.toURI().toURL();

//4、執行addURL方法,通過URLclassLoader從指定jar中擷取class并動态加到jvm虛拟機裡

method.invoke(classLoader, url);

//5、class成功被動态加載進虛拟機後,就可以利用反射擷取

Class> aClass = Class.forName("function.Split");