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类加载器的更多相关文章
- [转载] Java高新技术第一篇:类加载器详解
本文转载自: http://blog.csdn.net/jiangwei0910410003/article/details/17733153 首先来了解一下字节码和class文件的区别: 我们知道, ...
- Java虚拟机JVM学习05 类加载器的父委托机制
Java虚拟机JVM学习05 类加载器的父委托机制 类加载器 类加载器用来把类加载到Java虚拟机中. 类加载器的类型 有两种类型的类加载器: 1.JVM自带的加载器: 根类加载器(Bootstrap ...
- Java高新技术第一篇:类加载器详解
首先来了解一下字节码和class文件的区别: 我们知道,新建一个Java对象的时候,JVM要将这个对象对应的字节码加载到内存中,这个字节码的原始信息存放在classpath(就是我们新建Java工程的 ...
- 【java虚拟机系列】JVM类加载器与ClassNotFoundException和NoClassDefFoundError
在我们日常的项目开发中,会经常碰到ClassNotFoundException和NoClassDefFoundError这两种异常,对于经验足够的工程师而言,可能很轻松的就可以解决,但是却不一定明白为 ...
- Java内存管理-掌握虚拟机类加载器(五)
勿在流沙筑高台,出来混迟早要还的. 做一个积极的人 编码.改bug.提升自己 我有一个乐园,面向编程,春暖花开! 上一篇介绍虚拟机类加载机制,讲解了类加载机制中的三个阶段,分别是:加载.连接(验证.准 ...
- 深入理解java虚拟机(九)类加载器以及双亲委派模型
虚拟机把类加载阶段中“通过一个类的全限定名来获取描述此类的二进制字节流”这个动作放到虚拟机外部去实现,以便让程序自己决定如何去获取所需要的类.实现这个动作的代码模块称为“类加载器”. 类与类加载器 任 ...
- 深度分析:面试阿里,字节99%会被问到Java类加载机制和类加载器
1. 类加载机制 所谓类加载机制就是JVM虚拟机把Class文件加载到内存,并对数据进行校验,转换解析和初始化,形成虚拟机可以直接使用的Jav类型,即Java.lang.Class. 2. 类加载的过 ...
- 8.6(java学习笔记)类加载过程及类加载器
一.类加载 1.加载 将class字节码加载到内存中,同时在方法区形成改类运行时数据结构. 同时在堆中产生一个Class对象,反射就是获取这个对象并对其进行操作. 2.链接 2.1验证:验证加载的类信 ...
- jvm之java类加载机制和类加载器(ClassLoader),方法区结构,堆中实例对象结构的详解
一.类加载或类初始化:当程序主动使用某个类时,如果该类还未被加载到内存中,则JVM会通过加载.连接.初始化3个步骤来对该类进行初始化.如果没有意外,JVM将会连续完成3个步骤. 二.类加载时机: 1 ...
随机推荐
- 【NET CORE微服务一条龙应用】开始篇与目录
简介 随着业务的发展和变更,项目原先的分布式框架应用业务发展已有些不适应,所以18年初开始准备使用微服务框架,当时正好看到了ocelot项目,特意翻看了源码,发现很灵活和易扩展 于是就开始了微服务的开 ...
- ELK(elasticsearch+kibana+logstash)搜索引擎(二): elasticsearch基础教程
1.elasticsearch的结构 首先elasticsearch目前的结构为 /index/type/id id对应的就是存储的文档ID,elasticsearch一般将数据以JSON格式存储. ...
- 多继承之MRO
一,python2和python3的区别 在python2中存在两种类:一个叫经典类,在python2.2之前,一直用的是经典类,经典类如果在基类的根什么都不写,那么它就是根:还有一个叫新式类,在py ...
- springboot:Java模板引擎Thymeleaf介绍
Thymeleaf是一款用于渲染XML/XHTML/HTML5内容的模板引擎.类似JSP,Velocity,FreeMaker等,它也可以轻易的与Spring MVC等Web框架进行集成作为Web应用 ...
- 以前没有写笔记的习惯,现在慢慢的发现及时总结是多么的重要。 这一篇文章主要关于java多线程一些常见的疑惑点。因为讲解多线程的书籍和文章已经很多了,所以我也不好意思多说,嘻嘻嘻、大家可以去参考一些那些书籍。我这个文章主要关于实际的一些问题。同时也算是我以后复习的资料吧,。还请大家多多指教。 同时希望多结交一些技术上的朋友。谢谢。
在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口. 以下就是我们常见的问题了: 1. 为什么我们不能直接调用run()方法呢? 我的理解是:线程的运行 ...
- ubuntu安装ftp server服务
原文地址: https://jingyan.baidu.com/article/7908e85c988b23af481ad2ae.html 首先,更新软件源,保证源是最新的,这样有利于下面在线通过ap ...
- Java集合的选择
我们在使用集合时应该使用哪个集合呢? 具体还是要看需求, 当然, Java中不只是有这几个, 还有一些没有给出, 具体情况具体分析吧, 仅给出一个小思路. 进行集合的选择: 是否是键值对象形式: 一 ...
- python之初识网络
一. C/S架构:客户端(client)/服务端(server)架构 B/S架构:浏览器(browser) / 服务端(server)架构 软件cs架构: 浏览器,qq,微信等等 硬件cs架构:打印机 ...
- base64加密和解码原理和代码
Base64编码,是我们程序开发中经常使用到的编码方法.它是一种基于用64个可打印字符来表示二进制数据的表示方法.它通常用作存储.传输一些二进制数据编码方法!也是MIME(多用途互联网邮件扩展,主要用 ...
- windows 2012 r2企业版没有界面
windows 2012 R2系统进去以后只有CMD命令窗口,没有图形化界面,除了cmd其余的全部是黑的.在网上搜了很多,都是大同小异的解决方法,但根本解决不了.今天再这里分享的这个方法很简单,不用重 ...