【深入浅出-JVM】(76):classloader
方法
- public Class<?> loadClass(String name) throws ClassNotFoundException
通过类名发挥这个类的Class实例 - protected final Class<?> defineClass(byte[] b,int off,int len)
根据给定的字节码流 b,off 和 len 参数表示实际的 class 信息在byte 数组中的位置和长度,其中 byte 数组 b是 classloader 从外部获取的 - protected Class<?> findClass(String name)throws ClassNotFoundException
查看一个类 - protected final Class<?> findLoadedClass(String name)
分类
- BootStrap ClassLoader
- Extension ClassLoader
- AppClassLoader
启动类加载器负责加载系统的核心类(rt.jar的java类),扩展类加载器加载 %JAVA_HOME/lib/ext/*.jar中的类,应用类加载器用于加载用户类 (classpath),自定义类加载器加载一些特殊路径的类(自定义classloader)
双亲委托
- 当前 classloader 首先从自己已经加载的类中查询是否此类已经加载,如果已经加载了则直接返回原来已经加载的类
- 当前 classloader 的缓存中没有找到被加载的类的时候,委托父类加载器去加载,父类加载器采用同样的策略,首先查下自己的缓存,然后委托父类去加载,一直到 bootstrap classloader
- 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,并将其放入自己的缓存中,下次请求的时候直接返回
- 一直循环重复
作用
- 各个类加载器的基础类统一
jar -cvf test.jar HelloLoader.class 把class打包成jar
Extension ClassLoader
例子:在 ext 路径下放一个自己 jar 包并加载
package com.mousycoder.server;
public class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
idea 通过 structs->artifacts->jar 然后 build-> build artifacts->build 生成 helloworld.jar
放到 /Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/ext
package com.mousycoder.mycode.thinking_in_jvm;
import java.lang.reflect.Method;
/**
* @version 1.0
* @author: mousycoder
* @date: 2019-09-06 10:35
*/
public class ExtClassLoader {
public static void main(String[] args) throws ClassNotFoundException {
System.out.println(System.getProperty("java.ext.dirs"));
Class<?> helloClass = Class.forName("com.mousycoder.server.HelloWorld");
System.out.println(helloClass.getClassLoader());
}
}
输出
/Users/mousycoder/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java
sun.misc.Launcher$ExtClassLoader@610455d6
可以看出是 ExtClassLoader 加载 java.ext.dirs 目录
自定义类加载器
package com.mousycoder.mycode.thinking_in_jvm;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
/**
* @version 1.0
* @author: mousycoder
* @date: 2019-09-06 11:13
*/
public class MyClassLoader extends ClassLoader {
private final static Path DEFAULT_CLASS_PATH = Paths.get("","/Users/mousycoder/My");
private final Path classDir;
public MyClassLoader(){
super();
this.classDir = DEFAULT_CLASS_PATH;
}
public MyClassLoader(String classDir){
super();
this.classDir = Paths.get(classDir);
}
public MyClassLoader(String classDir, ClassLoader parent){
super(parent);
this.classDir = Paths.get(classDir);
}
@Override
protected Class<?> findClass(String name) throws ClassNotFoundException {
try {
byte[] classBytes = this.readClassBytes(name);
if (null == classBytes || 0 == classBytes.length){
throw new ClassNotFoundException("can not load the class" + name);
}
return this.defineClass(name,classBytes,0,classBytes.length);
} catch (IOException e){
e.printStackTrace();
}
return null;
}
private byte[] readClassBytes(String name) throws ClassNotFoundException, IOException {
String classPath = name.replace(".","/");
Path classFullPath = classDir.resolve( "HelloWorld1.class");
if (!classFullPath.toFile().exists()){
throw new ClassNotFoundException("The class" + name + "mpt found");
}
try (ByteArrayOutputStream baos = new ByteArrayOutputStream()){
Files.copy(classFullPath,baos);
return baos.toByteArray();
} catch (IOException e){
throw new ClassNotFoundException("load the class " + name + "occur error",e);
}
}
@Override
public String toString() {
return "My ClassLoader";
}
}
package com.mousycoder.mycode.thinking_in_jvm;
/**
* @version 1.0
* @author: mousycoder
* @date: 2019-09-06 11:34
*/
public class MyClassLoaderTest {
public static void main(String[] args) throws ClassNotFoundException {
MyClassLoader classLoader = new MyClassLoader();
Class<?> class1 = classLoader.loadClass("com.mousycoder.mycode.thinking_in_jvm.HelloWorld1");
System.out.println(class1.getClassLoader());
}
}
package com.mousycoder.mycode.thinking_in_jvm;
/**
* @version 1.0
* @author: mousycoder
* @date: 2019-09-06 11:46
*/
public class HelloWorld1 {
public static void main(String[] args) {
System.out.println("Hello world1 ");
}
}
把helloword1变成class放到/Users/mousycoder/My目录下即可
输出 My ClassLoader 代表 自定义类加载器加载了该类
上下文类加载器
作用
打破双亲委托机制,让上层父类加载器可以使用子类的加载器加载对象,比如Spi中的接口类在系统加载器中,但是实现类在应用加载器中
Tomcat 类加载器
目的
- 保证每个应用的类库独立隔离(即使同限定名不同版本的)
- 保证相同类库相同版本的类库共享
- 保证容器自身的类库和程序独立
加载顺序
- bootstrap 引导类加载器
- system 系统类加载器
- 应用类加载器 WEB-INF/classes
- 应用类加载器 WEB-INF/lib
- common 类加载器 CATALINA/lib
【深入浅出-JVM】(76):classloader的更多相关文章
- JVM的ClassLoader过程分析
本文来自网络:深入分析Java ClassLoader原理 http://my.oschina.net/zhengjian/blog/133836 一. JVM的ClassLoader过程以及装载原理 ...
- java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制
ClassLoader的工作机制 java应用环境中不同的class分别由不同的ClassLoader负责加载. 一个jvm中默认的classloader有Bootstrap ClassLoader. ...
- JVM思考-ClassLoader.loadClasshe和Class.forName区别
JVM思考-ClassLoader.loadClasshe和Class.forName区别 目录:JVM总括:目录 见博客第四节:JVM总括四-类加载过程.双亲委派模型.对象实例化过程
- 深入浅出 JVM GC(3)
# 前言 在 深入浅出 JVM GC(2) 中,我们介绍了一些 GC 算法,GC 名词,同时也留下了一个问题,就是每个 GC 收集器的具体作用.有哪些 GC 收集器呢? Serial 串行收集器(只适 ...
- 深入浅出 JVM GC(2)
# 前言 在 深入浅出 JVM GC(1) 中,限于上篇文章的篇幅,我们留下了一个问题 : 如何回收? 这篇文章将重点讲述这个问题. 在上篇文章中,我们也列出了一些大纲,今天我们就按照那个大纲来逐个讲 ...
- JVM和ClassLoader
JVM和ClassLoader 2019-11-08 目录 1 JVM架构整体架构 1.1 类加载器子系统 1.1.1 加载 1.1.2 链接 1.1.3 初始化 1.2 运行时数据区(Runtime ...
- 深入浅出 JVM ClassLoader
# 前言 在 JVM 综述里面,我们说,JVM 做了三件事情,Java 程序的内存管理, Java Class 二进制字节流的加载(ClassLoader),Java 程序的执行(执行引擎).我们也说 ...
- JVM的classloader(转)
Java中一共有四个类加载器,之所以叫类加载器,是程序要用到某个类的时候,要用类加载器载入内存. 这四个类加载器分别为:Bootstrap ClassLoader.Extension Class ...
- 关于JVM的ClassLoader(转)
众所周知,java是编译型的语言,写的是java文件,最后运行的是class文件,class文件是运行在JVM之中的,这时候就有一个问题,JVM如何装载class文件的?是通过ClassLoader来 ...
随机推荐
- 全球十大OTA 谁能有一席之地?
全球十大OTA 谁能有一席之地? http://www.traveldaily.cn/article/78381/1 2014-03-05 来源:i黑马 随着旅游行业日新月异的发展,在线旅游网站的出现 ...
- Liunx之nginx代理
一.代理 正向代理 正向代理,也就是传说中的代理,他的工作原理就像一个跳板(VPN),简单的说: 我是一个用户,我访问不了某网站,但是我能访问一个代理服务器,这个代理服务器呢,他能访问那个我不能访问的 ...
- TP5使用API时不可预知的内部异常
最常见的错误形式例如 controller不存在或者 action不存在之类的 我们第一时间想到的 就是 使用 try{}catch(){} 来捕获 例如: /** * show方法在common里定 ...
- LSTM+CRF维特比解码过程
题目:给定长度为n的序列,标签数为m(标签值表示为1,2,....,m),发射概率矩阵E(n * m),其中E[i][j]表示第i个词预测为标签j的发射概率,转移概率矩阵T(m*m),其中T[i][j ...
- Javascript中,实现十大排序方法之一(冒泡排序及其优化设想)
冒泡排序的Javascript实现 首先定义一个取值范围在(0~100000)之间的随机值的长度为10万的数组, function bubbleSort(arr) { console.time('冒泡 ...
- QMS 的趨勢概述
自泰勒Taylor提出的科学管理被奉行后,制造业的分工已然成形,而产品不再是由工匠单独负责完成.为确保产品的质量,产品在完工后的检验为确保瑕疵品不外流出给客户的必要关卡.然而当产品依靠检验结果并无法减 ...
- 委托和lambda表达式,Action和Func
1.为什么要用委托 我们为什么要有委托?任何东西存在即合理,不合理的也会被时间淘汰掉,委托既然存在肯定有存在的必要,我们来看一下什么时候可以用到委托. 接下来我们有个需求,就是调用一个方法,取出1-1 ...
- iView表格行验证问题
iView Table 3.2.0 版本 需求: 验证前两行的姓名不能为空: 解决方案: 判断是否前两行,如是则增加校验规则: 需在<FormItem>前加<Form>标签否则 ...
- 服务链路跟踪 && 服务监控
服务链路跟踪 背景 微服务以微出名,在实际的开发过程中,涉及到成百上千个服务,网络请求引起服务之间的调用极其复杂. 当请求不可用或者变慢时,需要及时排查出故障服务点成为了微服务维护的一大难关. 服务链 ...
- [系列] 使用 go modules 包管理工具(一)
目录 概述 初始化 添加依赖包 go mod 命令 小结 源码地址 概述 我想实现一个开箱即用的 API 框架的轮子,这个轮子是基于 Gin 基础上开发的. 为什么是开箱即用,它会集成哪些功能? 以上 ...