1 自定義類加載器:
實現規則: 自定義類加載器,需要重寫findClass,然后通過調用loadClass進行類加載(loadClass通過遞歸實現類的雙親委派加載)
package com.daxin; import java.io.*; /** * 自定義類加載器,需要重寫findClass,然后通過調用loadClass進行類加載(loadClass通過遞歸實現類的雙親委派加載) */ public class MyClassLoader extends ClassLoader { /** * 設置類的路徑 */ private String root; protected Class<?> findClass(String name) throws ClassNotFoundException { byte[] classData = loadClassData(name); if (classData == null) { throw new ClassNotFoundException(); } else { return defineClass(name, classData, 0, classData.length); } } private byte[] loadClassData(String className) { String fileName = root + File.separatorChar + className.replace('.', File.separatorChar) + ".class"; InputStream ins = null; try { ins = new FileInputStream(fileName); ByteArrayOutputStream baos = new ByteArrayOutputStream(); int bufferSize = 1024; byte[] buffer = new byte[bufferSize]; int length = 0; while ((length = ins.read(buffer)) != -1) { baos.write(buffer, 0, length); } return baos.toByteArray(); } catch (IOException e) { e.printStackTrace(); } finally { try { ins.close(); } catch (IOException e) { e.printStackTrace(); } } return null; } public void setRoot(String root) { this.root = root; } public static void main(String[] args) { MyClassLoader classLoader = new MyClassLoader(); classLoader.setRoot("C:\\temp"); Class<?> testClass = null; try { testClass = classLoader.loadClass("com.daxin.classloader.StaticClassDemo"); Object object = testClass.newInstance(); System.out.println(object.getClass().getClassLoader()); } catch (ClassNotFoundException e) { e.printStackTrace(); } catch (InstantiationException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } }
2 自定義ClassPath類加載器:
類加載器的繼承關系圖:
ClassPath類加載器實現源碼:
package org.apache.loadjar; import java.io.BufferedReader; /** * * */ import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.lang.reflect.Method; import java.net.URL; import java.net.URLClassLoader; import java.util.ArrayList; import java.util.List; public final class ExtClassPathLoader { private static Method addURL = initAddMethod(); public static URLClassLoader classloader = (URLClassLoader) ClassLoader.getSystemClassLoader(); /** * 初始化addUrl 方法. * * @return 可訪問addUrl方法的Method對象 */ private static Method initAddMethod() { try { // 反射獲取addURL方法 Method add = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class }); // 設置訪問權限 add.setAccessible(true); return add; } catch (Exception e) { throw new RuntimeException(e); } } /** * 加載jar classpath。 */ public static void loadClasspath() { List<String> files = getJarFiles(); if (files == null) return; for (String f : files) { loadClasspath(f); } List<String> resFiles = getResFiles(); if (resFiles == null) return; for (String r : resFiles) { loadResourceDir(r); } } private static void loadClasspath(String filepath) { File file = new File(filepath); loopFiles(file); } private static void loadResourceDir(String filepath) { File file = new File(filepath); loopDirs(file); } /** */ /** * 循環遍歷目錄,找出所有的資源路徑。 * * @param file * 當前遍歷文件 */ private static void loopDirs(File file) { // 資源文件只加載路徑 if (file.isDirectory()) { addURL(file); File[] tmps = file.listFiles(); for (File tmp : tmps) { loopDirs(tmp); } } } /** * 循環遍歷目錄,找出所有的jar包。 * * @param file * 當前遍歷文件 */ private static void loopFiles(File file) { if (file.isDirectory()) { File[] tmps = file.listFiles(); for (File tmp : tmps) { loopFiles(tmp); } } else { if (file.getAbsolutePath().endsWith(".jar") || file.getAbsolutePath().endsWith(".zip")) { addURL(file); } } } /** * 通過filepath加載文件到classpath。 * * @param filePath * 文件路徑 * @return URL * @throws Exception * 異常 */ private static void addURL(File file) { try { addURL.invoke(classloader, new Object[] { file.toURI().toURL() }); } catch (Exception e) { } } /** * * 將當前classpath下jar.txt的清單jar明見加載到classpath中 * * @return * @throws Exception */ private static List<String> getJarFiles() { // TODO 從properties文件中讀取配置信息 如果不想配置 可以自己new 一個List<String> 然后把 jar的路徑加進去 // 然后返回 InputStream in = ClassLoader.getSystemResourceAsStream("jar.txt"); BufferedReader br = new BufferedReader(new InputStreamReader(in)); String line = null; List<String> list = new ArrayList<String>(); try { line = br.readLine(); while (line != null) { list.add(line); line = br.readLine(); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (br != null) br.close(); } catch (IOException e) { e.printStackTrace(); } } return list; } /** * 從配置文件中得到配置的需要加載classpath里的資源路徑集合 * * @return */ private static List<String> getResFiles() { // TODO 從properties文件中讀取配置信息略 如果不想配置 可以自己new 一個List<String> 然后把 // jar的路徑加進去 然后返回 額 如果沒有資源路徑為空就可以了 return null; } }
使用示例:
package org.apache.action; import java.io.BufferedReader; import java.io.FileNotFoundException; import java.io.FileReader; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URLClassLoader; import org.apache.loadjar.ExtClassPathLoader; /** * * * @date 2017年8月14日 下午9:13:40 * */ public class MainClassLoaderTest { public static void main(String[] args) throws InstantiationException, IllegalAccessException, ClassNotFoundException, Exception { ExtClassPathLoader.loadClasspath(); System.out.println((URLClassLoader)ExtClassPathLoader.classloader); // StringUtils su =new StringUtils(); // su.sayHello(); //// // System.out.println(su.getClass().getClassLoader()); } } // ExtClasspathLoader.loadClasspath(); // //ExtClasspathLoader.loadClasspath("C:\\Users\\Daxin\\Desktop\\myjar.jar"); // //StringUtils su = new StringUtils(); // //su.sayHello(); // //su.saySomeThing("I am daxin!"); //只會讀取第一行 //ClassLoader.getSystemResource("jar.txt"); //InputStream in = ClassLoader.getSystemResourceAsStream("jar.txt"); //BufferedReader br =new BufferedReader(new InputStreamReader(in)); //System.out.println(br.readLine());