【深入浅出-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来 ...
随机推荐
- alluxio源码解析-层次化存储(4)
层次化存储-特性介绍: https://www.alluxio.org/docs/1.6/cn/Tiered-Storage-on-Alluxio.html 引入分层存储后,Alluxio管理的数据块 ...
- MVC+EF Core 完整教程20--tag helper详解
之前我们有一篇:“动态生成多级菜单”,对使用Html Helper做了详细讲述,并且自定义了一个菜单的 Html Helper: https://www.cnblogs.com/miro/p/5541 ...
- JSmooth 将java代码打包成exe
JSmooth 将java代码打包成exe 前言 java代码写了这么多了,但由于jdk的限制,我只能在jdk电脑上运行项目.所以最近在研究打包exe这个问题,今天终于实现了. JSmooth下载 前 ...
- Markdown 基本语法(后面继续补充)
1.1 Markdown 基础语法 有序内容和无序内容 有序内容:输入1.然后按tab键 无序内容:输入' * ' 或 ' - ' 然后后按tab键 字体的样式 *** 内容 *** 加粗加斜(中间没 ...
- 服务注册组件——Eureka高可用集群搭建
服务注册组件--Eureka高可用集群搭建 什么是Eureka? 服务注册组件:将微服务注册到Eureka中. 为什么需要服务注册? 微服务开发重点在一个"微"字,大型应用拆分成微 ...
- set集合的常用方法
set集合是一种无序不重复的集合 add (self, *args, **kwargs) ...
- [luogu4886] 快递员(点分治,树链剖分,lca)
dwq推的火题啊. 这题应该不算是点分治,但是用的点分治的思想. 每次找重心,算出每一对询问的答案找到答案最大值,考虑移动答案点,使得最大值减小. 由于这些点一定不能在u的两颗不同的子树里,否则你怎么 ...
- CF553C Love Triangles(二分图)
Tyher推的好题. 题意就是给你一些好边一些坏边,其他边随意,让你求符合好坏坏~,或者只包含好好好的三元环的无向图个数. 坏坏的Tyher的题意是这样的. 再翻译得更加透彻一点就是:给你一些0(好边 ...
- Springboot + Stopping service [Tomcat]+ Process finished with exit code 0
在Springboot 的版本为: <version>1.5.10.RELEASE</version> 原因:代码中有非法格式的结构,及代码写错啦,例如: <result ...
- 打包一沓开源的 C/C++ 包管理工具送给你!
本文作者:HelloGitHub-ChungZH 博客地址:https://chungzh.cn/ 包管理器可以帮助你更方便地安装依赖关系,并决定所安装的版本,提高你的开发幸福感.许多语言都有自己的包 ...