Java自定义类加载和ClassPath类加载器
Posted 进无止境
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java自定义类加载和ClassPath类加载器相关的知识,希望对你有一定的参考价值。
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());
以上是关于Java自定义类加载和ClassPath类加载器的主要内容,如果未能解决你的问题,请参考以下文章