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解析 ...
随机推荐
- 一份不错的vue.js基础笔记!!!!
第一章 Vue.js是什么? Vue(法语)同view(英语) Vue.js是一套构建用户界面(view)的MVVM框架.Vue.js的核心库只关注视图层,并且非常容易学习,非常容易与其他库或已有的项 ...
- x-requested-with 请求头 区分ajax请求还是普通请求(转)
在服务器端判断request来自Ajax请求(异步)还是传统请求(同步): 两种请求在请求的Header不同,Ajax 异步请求比传统的同步请求多了一个头参数 1.传统同步请求参数 accept t ...
- JMeter - 参数化
方法一:使用"函数助手"添加从文件中读取参数的函数 (a)__StringFromFile函数:[读取整行数据]1.新建参数文件:
- ajax跨域往php程序post数据时,php程序总是执行两次的解决方法
php程序是部署在IIS7上面,ajax提交数据时,遇到了两个问题,一个就是跨域,一个php程序总会被执行两次. 第一个问题的解决方法,是百度出来的,添加下面几行代码就可以了: header('Acc ...
- js和php对bool值的判断区别
一.将一种数据类型转换为bool值时,PHP和JS的转换规则不同 PHP中 当转换为 boolean 时,以下值被认为是 FALSE : 布尔值 FALSE 本身 整型值 0(零) 浮点型值 0.0( ...
- iOS.ReactNative-3-about-viewmanager-uimanager-and-bridgemodule
RCTViewManager and RCTUIManager 1. RCTViewManager 1.1 RCTViewManager 实现了接口RCTBridgeModule @interface ...
- 【如何快速的开发一个完整的iOS直播app】(美颜篇)
原文转自:袁峥Seemygo 感谢分享.自我学习 前言 在看这篇之前,如果您还不了解直播原理,请查看这篇文章如何快速的开发一个完整的iOS直播app(原理篇) 开发一款直播app,美颜功能是很重 ...
- 沉浸式状态栏_boolean hasTopLine = a.getBoolean(1, false);//AS会在"1"下显示错误红线
TypedArray a = mContext.obtainStyledAttributes(attrs); boolean hasBottomLine = a.getBoolean(0, false ...
- sqlite本地保存数据
package com.cesecsh.ics.database; import android.content.Context; import android.database.Cursor; im ...
- javascript学习面向对象(二)
主要内容: prototype扩展应用示例: 对比如下: 数组中forEach用法示例: 从上面示例可以看出,forEach只适合遍历一维数组: 应用prototype扩展实现全部元素遍历如下: 简单 ...