最近作一個Java Windows NT服務,爲了方便管理和加載第三方類庫,須要加載指定目錄下的jar,故須要編寫一個本身的類加載器。順便梳理下相關知識。
java
類加載器雙親委派機制url
JVM在加載類時默認採用的是雙親委派機制。通俗的講,就是某個特定的類加載器在接到加載類的請求時,首先將加載任務委託給該類加載器的父類加載器,依次遞歸,若是父類加載器成功加載,就返回;若是父類加載器沒法完成此加載任務時,就委派給他孩子加載,不成功依次遞歸。spa
JVM預約義類加載器.net
啓動類加載器:本地代碼實現,class = null.它負責將 $(JAVA_HOME)/lib 下面的類庫加載到內存中.code
標準擴展類加載器:sun實現。class = sun.misc.Launcher$ExtClassLoader。負責將 $(JAVA_HOME)/lib/ext 或者由系統變量 java.ext.dir 指定位置中的類庫加載到內存中.orm
系統類加載器:sun實現。class = sun.misc.Launcher$AppClassLoader.負責加載classpath配置的類庫.繼承
自定義類加載器遞歸
繼承URLClassLoader。 一個簡單實現的例子:內存
import java.io.File; import java.io.FileFilter; import java.net.MalformedURLException; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; public class NetClassLoader extends URLClassLoader{ private static List<URL> EMPTY_URL_LIST = new ArrayList<URL>(0); public NetClassLoader(URL[] urls) { super(urls); } public NetClassLoader(String dir) { super(getJarURL(dir).toArray(new URL[]{})); } private static List<URL> getJarURL(String dir){ if(dir == null || "".equals(dir.trim())){ return EMPTY_URL_LIST; } File file = new File(dir); List<URL> jarsList = new ArrayList<URL>(); if(file.isDirectory()){ File[] files = file.listFiles(new FileFilter() { public boolean accept(File pathname) { return pathname.getName().endsWith(".jar") || pathname.isDirectory(); } }); if(files.length > 0 ){ for(File f : files){ if(f.isFile()){ addURL(jarsList,f); }else{//處理目錄文件 jarsList.addAll(getJarURL(f.getAbsolutePath())); } } } }else if(file.isFile() && dir.endsWith(".jar")){ addURL(jarsList,file); } return EMPTY_URL_LIST; } private static void addURL(List<URL> list,File file){ try { URL url = file.toURI().toURL(); list.add(url); } catch (MalformedURLException e) { } } }