1 自定义类加载器:

实现规则: 自定义类加载器,需要重写findClass,然后通过调用loadClass进行类加载(loadClass通过递归实现类的双亲委派加载)

  1. package com.daxin;
  2.  
  3. import java.io.*;
  4.  
  5. /**
  6. * 自定义类加载器,需要重写findClass,然后通过调用loadClass进行类加载(loadClass通过递归实现类的双亲委派加载)
  7. */
  8. public class MyClassLoader extends ClassLoader {
  9.  
  10. /**
  11. * 设置类的路径
  12. */
  13. private String root;
  14.  
  15. protected Class<?> findClass(String name) throws ClassNotFoundException {
  16. byte[] classData = loadClassData(name);
  17. if (classData == null) {
  18. throw new ClassNotFoundException();
  19. } else {
  20. return defineClass(name, classData, 0, classData.length);
  21. }
  22. }
  23.  
  24. private byte[] loadClassData(String className) {
  25. String fileName = root + File.separatorChar
  26. + className.replace('.', File.separatorChar) + ".class";
  27. InputStream ins = null;
  28. try {
  29. ins = new FileInputStream(fileName);
  30. ByteArrayOutputStream baos = new ByteArrayOutputStream();
  31. int bufferSize = 1024;
  32. byte[] buffer = new byte[bufferSize];
  33. int length = 0;
  34. while ((length = ins.read(buffer)) != -1) {
  35. baos.write(buffer, 0, length);
  36. }
  37. return baos.toByteArray();
  38. } catch (IOException e) {
  39. e.printStackTrace();
  40. } finally {
  41. try {
  42. ins.close();
  43. } catch (IOException e) {
  44. e.printStackTrace();
  45. }
  46. }
  47.  
  48. return null;
  49. }
  50.  
  51. public void setRoot(String root) {
  52. this.root = root;
  53. }
  54.  
  55. public static void main(String[] args) {
  56.  
  57. MyClassLoader classLoader = new MyClassLoader();
  58. classLoader.setRoot("C:\\temp");
  59.  
  60. Class<?> testClass = null;
  61. try {
  62. testClass = classLoader.loadClass("com.daxin.classloader.StaticClassDemo");
  63. Object object = testClass.newInstance();
  64. System.out.println(object.getClass().getClassLoader());
  65. } catch (ClassNotFoundException e) {
  66. e.printStackTrace();
  67. } catch (InstantiationException e) {
  68. e.printStackTrace();
  69. } catch (IllegalAccessException e) {
  70. e.printStackTrace();
  71. }
  72. }
  73. }

2 自定义ClassPath类加载器:

类加载器的继承关系图:

ClassPath类加载器实现源码:

  1. package org.apache.loadjar;
  2.  
  3. import java.io.BufferedReader;
  4. /**
  5. *
  6. *
  7. */
  8. import java.io.File;
  9. import java.io.IOException;
  10. import java.io.InputStream;
  11. import java.io.InputStreamReader;
  12. import java.lang.reflect.Method;
  13. import java.net.URL;
  14. import java.net.URLClassLoader;
  15. import java.util.ArrayList;
  16. import java.util.List;
  17.  
  18. public final class ExtClassPathLoader {
  19.  
  20. private static Method addURL = initAddMethod();
  21.  
  22. public static URLClassLoader classloader = (URLClassLoader) ClassLoader.getSystemClassLoader();
  23.  
  24. /**
  25. * 初始化addUrl 方法.
  26. *
  27. * @return 可访问addUrl方法的Method对象
  28. */
  29. private static Method initAddMethod() {
  30. try {
  31. // 反射获取addURL方法
  32. Method add = URLClassLoader.class.getDeclaredMethod("addURL", new Class[] { URL.class });
  33. // 设置访问权限
  34. add.setAccessible(true);
  35. return add;
  36. } catch (Exception e) {
  37. throw new RuntimeException(e);
  38. }
  39. }
  40.  
  41. /**
  42. * 加载jar classpath。
  43. */
  44. public static void loadClasspath() {
  45. List<String> files = getJarFiles();
  46. if (files == null)
  47. return;
  48. for (String f : files) {
  49. loadClasspath(f);
  50. }
  51.  
  52. List<String> resFiles = getResFiles();
  53. if (resFiles == null)
  54. return;
  55. for (String r : resFiles) {
  56. loadResourceDir(r);
  57. }
  58. }
  59.  
  60. private static void loadClasspath(String filepath) {
  61. File file = new File(filepath);
  62. loopFiles(file);
  63. }
  64.  
  65. private static void loadResourceDir(String filepath) {
  66. File file = new File(filepath);
  67. loopDirs(file);
  68. }
  69.  
  70. /** */
  71. /**
  72. * 循环遍历目录,找出所有的资源路径。
  73. *
  74. * @param file
  75. * 当前遍历文件
  76. */
  77. private static void loopDirs(File file) {
  78. // 资源文件只加载路径
  79. if (file.isDirectory()) {
  80. addURL(file);
  81. File[] tmps = file.listFiles();
  82. for (File tmp : tmps) {
  83. loopDirs(tmp);
  84. }
  85. }
  86. }
  87.  
  88. /**
  89. * 循环遍历目录,找出所有的jar包。
  90. *
  91. * @param file
  92. * 当前遍历文件
  93. */
  94. private static void loopFiles(File file) {
  95. if (file.isDirectory()) {
  96. File[] tmps = file.listFiles();
  97. for (File tmp : tmps) {
  98. loopFiles(tmp);
  99. }
  100. } else {
  101. if (file.getAbsolutePath().endsWith(".jar") || file.getAbsolutePath().endsWith(".zip")) {
  102.  
  103. addURL(file);
  104. }
  105. }
  106. }
  107.  
  108. /**
  109. * 通过filepath加载文件到classpath。
  110. *
  111. * @param filePath
  112. * 文件路径
  113. * @return URL
  114. * @throws Exception
  115. * 异常
  116. */
  117. private static void addURL(File file) {
  118. try {
  119. addURL.invoke(classloader, new Object[] { file.toURI().toURL() });
  120. } catch (Exception e) {
  121. }
  122. }
  123.  
  124. /**
  125. *
  126. * 将当前classpath下jar.txt的清单jar明见加载到classpath中
  127. *
  128. * @return
  129. * @throws Exception
  130. */
  131. private static List<String> getJarFiles() {
  132. // TODO 从properties文件中读取配置信息 如果不想配置 可以自己new 一个List<String> 然后把 jar的路径加进去
  133. // 然后返回
  134. InputStream in = ClassLoader.getSystemResourceAsStream("jar.txt");
  135. BufferedReader br = new BufferedReader(new InputStreamReader(in));
  136. String line = null;
  137. List<String> list = new ArrayList<String>();
  138. try {
  139. line = br.readLine();
  140. while (line != null) {
  141. list.add(line);
  142. line = br.readLine();
  143. }
  144. } catch (IOException e) {
  145. e.printStackTrace();
  146. } finally {
  147. try {
  148. if (br != null)
  149. br.close();
  150. } catch (IOException e) {
  151. e.printStackTrace();
  152. }
  153. }
  154.  
  155. return list;
  156. }
  157.  
  158. /**
  159. * 从配置文件中得到配置的需要加载classpath里的资源路径集合
  160. *
  161. * @return
  162. */
  163. private static List<String> getResFiles() {
  164. // TODO 从properties文件中读取配置信息略 如果不想配置 可以自己new 一个List<String> 然后把
  165. // jar的路径加进去 然后返回 额 如果没有资源路径为空就可以了
  166. return null;
  167. }
  168.  
  169. }

使用示例:

  1. package org.apache.action;
  2.  
  3. import java.io.BufferedReader;
  4. import java.io.FileNotFoundException;
  5. import java.io.FileReader;
  6. import java.io.InputStream;
  7. import java.io.InputStreamReader;
  8. import java.net.URLClassLoader;
  9.  
  10. import org.apache.loadjar.ExtClassPathLoader;
  11.  
  12. /**
  13. *
  14. *
  15. * @date 2017年8月14日 下午9:13:40
  16. *
  17. */
  18. public class MainClassLoaderTest {
  19. public static void main(String[] args)
  20. throws InstantiationException, IllegalAccessException, ClassNotFoundException, Exception {
  21.  
  22. ExtClassPathLoader.loadClasspath();
  23.  
  24. System.out.println((URLClassLoader)ExtClassPathLoader.classloader);
  25.  
  26. // StringUtils su =new StringUtils();
  27. // su.sayHello();
  28. ////
  29. // System.out.println(su.getClass().getClassLoader());
  30.  
  31. }
  32.  
  33. }
  34.  
  35. // ExtClasspathLoader.loadClasspath();
  36. //
  37. //ExtClasspathLoader.loadClasspath("C:\\Users\\Daxin\\Desktop\\myjar.jar");
  38. //
  39. //StringUtils su = new StringUtils();
  40. //
  41. //su.sayHello();
  42. //
  43. //su.saySomeThing("I am daxin!");
  44.  
  45. //只会读取第一行
  46. //ClassLoader.getSystemResource("jar.txt");
  47. //InputStream in = ClassLoader.getSystemResourceAsStream("jar.txt");
  48. //BufferedReader br =new BufferedReader(new InputStreamReader(in));
  49. //System.out.println(br.readLine());

Java自定义类加载和ClassPath类加载器的更多相关文章

  1. [转载] Java高新技术第一篇:类加载器详解

    本文转载自: http://blog.csdn.net/jiangwei0910410003/article/details/17733153 首先来了解一下字节码和class文件的区别: 我们知道, ...

  2. Java虚拟机JVM学习05 类加载器的父委托机制

    Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...

  3. Java高新技术第一篇:类加载器详解

    首先来了解一下字节码和class文件的区别: 我们知道,新建一个Java对象的时候,JVM要将这个对象对应的字节码加载到内存中,这个字节码的原始信息存放在classpath(就是我们新建Java工程的 ...

  4. 【java虚拟机系列】JVM类加载器与ClassNotFoundException和NoClassDefFoundError

    在我们日常的项目开发中,会经常碰到ClassNotFoundException和NoClassDefFoundError这两种异常,对于经验足够的工程师而言,可能很轻松的就可以解决,但是却不一定明白为 ...

  5. Java内存管理-掌握虚拟机类加载器(五)

    勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇介绍虚拟机类加载机制,讲解了类加载机制中的三个阶段,分别是:加载.连接(验证.准 ...

  6. 深入理解java虚拟机(九)类加载器以及双亲委派模型

    虚拟机把类加载阶段中“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到虚拟机外部去实现,以便让程序自己决定如何去获取所需要的类.实现这个动作的代码模块称为“类加载器”. 类与类加载器 任 ...

  7. 深度分析:面试阿里,字节99%会被问到Java类加载机制和类加载器

    1. 类加载机制 所谓类加载机制就是JVM虚拟机把Class文件加载到内存,并对数据进行校验,转换解析和初始化,形成虚拟机可以直接使用的Jav类型,即Java.lang.Class. 2. 类加载的过 ...

  8. 8.6(java学习笔记)类加载过程及类加载器

    一.类加载 1.加载 将class字节码加载到内存中,同时在方法区形成改类运行时数据结构. 同时在堆中产生一个Class对象,反射就是获取这个对象并对其进行操作. 2.链接 2.1验证:验证加载的类信 ...

  9. jvm之java类加载机制和类加载器(ClassLoader),方法区结构,堆中实例对象结构的详解

    一.类加载或类初始化:当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载.连接.初始化3个步骤来对该类进行初始化.如果没有意外,JVM将会连续完成3个步骤. 二.类加载时机:  1 ...

随机推荐

  1. MySQLdump之single-transaction详解

    MySQLdump之single-transaction详解 single-transaction 开启general log选项 查看目前general log的情况 mysql> show ...

  2. MVC 的 Razor引擎显示代码表达式与隐式代码表达式

    隐式代码表达式 就是一个标识符,之后可以跟任意数量的方法调用("()").索引表达式("[]")及成员访问表达式(".").但是,除了在&q ...

  3. 多语言网站利器 rel="alternate" hreflang="x"

    下面是我在浏览网站时无意看到的,然后就搜了一下,感觉内容不错但我还没有测试,就转载过来做个备注,有时间了在翻过来看看 rel="alternate" hreflang=" ...

  4. sql server: 最短路径

    --------------------------------------------------------------------- -- Road System 道路 ------------ ...

  5. video 铺满父元素(object-fit: fill;)

    遇到这个属性,是在给video 嵌入一个div时,导致video播放器上下有灰色.在控制台查看video默认样式的时候看到了这个属性. 播放器上下的灰色,不是我们想要的样式,如果能完全覆盖就更好了. ...

  6. npm install权限问题,报错:permission denied。

    1.部署gulp项目时,nodeJs和gulp都已经正确安装,在项目内部执行npm install命令时,有些gulp的插件一直下载不成功,报错几种以下错误: “gulp-imagemin: Coul ...

  7. Loadrunner脚本开发-基于HTTP协议的流媒体视频在线播放服务器性能测试

    脚本开发-基于HTTP协议的流媒体视频在线播放服务器性能测试 by:授客 QQ:1033553122   目的 实现基于http协议的流媒体在线视频播放,服务器性能测试脚本,模拟用户浏览器方式在线播放 ...

  8. 《Inside C#》笔记(十五) 非托管代码 下

    二编写不安全代码 a)fixed关键字 代码中体现了fixed的用法:fixed (type* ptr= expression) { …}:type是类似int*这样的非托管类型或void类型,exp ...

  9. 13、多进程multiprocessing、进程池

    内容相关: multiprocessing: 进程的创建与运行 进程常用相关函数 进程池: 为什么要有进程池 进程池的创建与运行:串行.并行 回调函数 多进程multiprocessing: pyth ...

  10. weblogic系列漏洞整理 -- 4. weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271、CVE-2017-3506)

    目录 四. weblogic XMLDecoder 反序列化漏洞(CVE-2017-10271) 0. 漏洞分析 1. 利用过程 2. 修复建议 一.weblogic安装 http://www.cnb ...