java-类加载器
类加载器
用来加载Java类到Java虚拟机中。一般来说,Java虚拟机使用Java类的方式如下:Java 源程序(.java 文件)在经过Java编译器编译之后就被转换成字节码(.class 文件)。类加载器就是负责读取Java字节代码,并转换成 java.lang.Class类的一个实例。
Java应用环境中不同的class分别由不同的ClassLoader负责加载。
一个jvm中默认的类加载器有Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader:
- 引导类加载器Bootstrap ClassLoader 负责加载Java基础类,主要是 %JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等。
- 扩展类加载器Extension ClassLoader 负责加载Java扩展类,主要是 %JRE_HOME/lib/ext 目录下的jar和class。
- 应用类加载器App ClassLoader 负责加载当前Java应用的classpath中的所有类。
类加载器的委托机制
当Java虚拟机要加载一个类时,到底派出哪个类加载器去加载呢?每个ClassLoader本身只能分别加载特定位置和目录中的类,但它们可以委托其他的类装载器去加载类,这就是类加载器的委托模式。
加载过程中会先检查类是否被已加载,检查顺序是自底向上,从Custom ClassLoader到BootStrap ClassLoader逐层检查,只要某个classloader已加载就视为已加载此类,保证此类只所有ClassLoader加载一次。
而加载的顺序是自顶向下,也就是由上层来逐层尝试加载此类。类装载器一级级委托到BootStrap类加载器,当BootStrap无法加载当前所要加载的类时,然后才一级级回退到子孙类装载器去进行真正的加载。当回退到最初的类装载器时,如果它自己也不能完成类的装载,那就应报告ClassNotFoundException异常。
JVM的类加载是通过ClassLoader及其子类来完成的,类的层次关系和加载顺序可以由下图来描述:

自定义类加载器
由于一些特殊的需求,我们可能需要定制ClassLoader的加载行为,这时候就需要自定义ClassLoader了。自定义ClassLoader需要继承ClassLoader抽象类,重写findClass方法。这个方法定义了ClassLoader查找class的方式。因为类加载器是基于委托机制,它会自动向父类加载器委托,如果父类没有找到,就会再去调用我们重写的findClass方法加载。
1.定义一个需要被加载的类
import java.util.Date;
public class ClassTest extends Date{
public Sting toSring() {
return"hello,java!";
}
}
2.定义一个用来加密字节码的类
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; public class ClassEncrypt extends MyClassLoader{
public static void main(String[] args) throws IOException {
//要加密的字节码文件路径
String srcPath="F:\\Workspaces\\MyEclipse 10\\classload\\bin\\test_classload\\ClassTest.class";
//加密之后输出的字节码文件路径
String destPath="F:/ClassTest.class";
FileInputStream fis=new FileInputStream(srcPath);
FileOutputStream ofs=new FileOutputStream(destPath);
cypher(fis, ofs);
fis.close();
ofs.close();
}
//按字节异或
private static void cypher(InputStream in,OutputStream out) throws IOException{
int b=-1;
while((b=in.read())!=-1){
out.write(b^0xff);
}
}
}
3.自定义类加载器
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream; public class MyClassLoader extends ClassLoader{ @SuppressWarnings("deprecation")
@Override
protected Class findClass(String name) throws ClassNotFoundException {
try {
//需要加载的.class字节码的位置
String classPath="D:/ClassTest.class"; FileInputStream fis=new FileInputStream(classPath);
ByteArrayOutputStream bos=new ByteArrayOutputStream();
cypher(fis, bos);
fis.close();
byte[] bytes=bos.toByteArray();
return defineClass(bytes, 0, bytes.length);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return super.findClass(name);
} private static void cypher(InputStream in,OutputStream out) throws IOException{
int b=-1;
while((b=in.read())!=-1){
out.write(b^0xff);
}
}
}
4.测试类
import java.lang.reflect.Method;
import java.util.Date; public class Test {
public static void main(String[] args) throws Exception {
Class clazz=new MyClassLoader().loadClass("test_classload.ClassTest");
//父类引用
Date d1 = (Date)clazz.newInstance();
System.out.println(d1);
//反射调用
Method m1 = Class.forName("test_classload.ClassTest").getMethod("toString", null);
System.out.println(m1.invoke(Class.forName("test_classload.ClassTest").newInstance(), null)); }
}
java-类加载器的更多相关文章
- java笔记--理解java类加载器以及ClassLoader类
类加载器概述: java类的加载是由虚拟机来完成的,虚拟机把描述类的Class文件加载到内存,并对数据进行校验,解析和初始化,最终形成能被java虚拟机直接使用的java类型,这就是虚拟机的类加载机制 ...
- java类加载器深入研究
看了下面几篇关于类的加载器的文章,豁然开朗.猛击下面的地址开始看吧. Java类加载原理解析 深入探讨 Java 类加载器 分析BootstrapClassLoader/ExtClassLo ...
- 深入探讨 Java 类加载器
转自:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 类加载器(class loader)是 Java™中的一个很重要的概念.类 ...
- JAVA 类加载器 第14节
JAVA 类加载器 第14节 今天我们将类加载机制5个阶段中的第一个阶段,加载,又叫做装载.为了阅读好区分,以下都叫做装载. 装载的第一步就是要获得二进制的字节流,它可以从读.class文件获得,也可 ...
- 深入探讨 Java 类加载器[转]
原文地址:http://www.ibm.com/developerworks/cn/java/j-lo-classloader/index.html 类加载器(class loader)是 Java™ ...
- 转载:深入探讨 Java 类加载器
转载地址 : http://www.ibm.com/developerworks/cn/java/j-lo-classloader/ 深入探讨 Java 类加载器 类加载器(class loader) ...
- Java类加载器详解
title: Java类加载器详解date: 2015-10-20 18:16:52tags: JVM--- ## JVM三种类型的类加载器- 我们首先看一下JVM预定义的三种类型类加载器,当一个 J ...
- 一篇文章读懂Java类加载器
Java类加载器算是一个老生常谈的问题,大多Java工程师也都对其中的知识点倒背如流,最近在看源码的时候发现有一些细节的地方理解还是比较模糊,正好写一篇文章梳理一下. 关于Java类加载器的知识,网上 ...
- Java类加载器的工作原理
Java类加载器的作用就是在运行时加载类.Java类加载器基于三个机制:委托.可见性和单一性.委托机制是指将加载一个类的请求交给父类加载 器,如果这个父类加载器不能够找到或者加载这个类,那么再加载它. ...
- 深入理解Java类加载器(ClassLoader)
深入理解Java类加载器(ClassLoader) Java学习记录--委派模型与类加载器 关于Java类加载双亲委派机制的思考(附一道面试题) 真正理解线程上下文类加载器(多案例分析) [jvm解析 ...
随机推荐
- Linux系统中配置jdk
在Linux系统下安装jdk 1.到Oracle公司的官网里下载好jdk,网址 http://www.oracle.com/technetwork/java/javase/downloads/jdk8 ...
- php入门,配置wampserver
wamp安装过程中将网站的根目录设置在www目录下,这里记录如何定义自己的根目录,以便以后需要是查看 1.启动wampserver,左键选择apache下的httpd.conf,将文件中Documen ...
- vs2015 现用插件
1.abphelper abp app自动生成接口和input output 2.ankhsvn svn插件 3.c#outline2015 大括号折叠 4.codemaid 格式化 5.go to ...
- IIS上虚拟目录下站点的web.config与根站点的web.config冲突解决方法
IIS7.5上在站点下部署虚拟目录,访问虚拟目录下的项目提示与父节点配置冲突.,节点与的<system.web>节点与主站点的<system.web>冲突解决方法: 在站点下的 ...
- 模糊测试(Fuzz testing)
模糊测试(fuzz testing)是一种安全测试方法,他介于完全的手工测试和完全的自动化测试之间.为什么是介于那两者之间?首先完全的手工测试即是渗透测试,测试人员可以模拟黑客恶意进入系统.查找漏洞, ...
- python 正则re模块
re.match re.match 尝试从字符串的开始匹配一个模式,如:下面的例子匹配第一个单词. import re text = "JGood is a handsome boy, he ...
- Nginx+tomcat负载均衡时静态页面报404
百度到的问题解决BLOG http://os.51cto.com/art/201204/326843.htm nginx+2台tomcat负载均衡,应用程序已部署,单独访问tomcat时,可以访问到所 ...
- iOS.ReactNative-5-make-react-native-to-support-dynamically-update
基于React Native来实现App的热更新 热更新: 类似Hot-Patching,在程序不发布版本的前提下,对部分功能或者全部功能进行修改或者升级. JSX 1. JSX简介 1.1 http ...
- 等宽字体延伸到的 ch 长度单位和动画 animation-timing-function
新知识点get! 等宽字体(monospaced font)是指字符宽度相同的电脑字体.与此相对,字符宽度不尽相同的电脑字体称为比例字体(proportional font). 东亚字体基本都是等宽字 ...
- textField和textView限制输入条件
以下两法方法都是实现textfield和textView的代理方法 需要先遵循代理 一:textField限制只能输入数字和小数点 且小数点后只能保留两位 小数点前最多5位 - (BOOL)text ...