方法

  • 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)

双亲委托

  1. 当前 classloader 首先从自己已经加载的类中查询是否此类已经加载,如果已经加载了则直接返回原来已经加载的类
  2. 当前 classloader 的缓存中没有找到被加载的类的时候,委托父类加载器去加载,父类加载器采用同样的策略,首先查下自己的缓存,然后委托父类去加载,一直到 bootstrap classloader
  3. 当所有的父类加载器都没有加载的时候,再由当前的类加载器加载,并将其放入自己的缓存中,下次请求的时候直接返回
  4. 一直循环重复

作用

  • 各个类加载器的基础类统一

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 类加载器

目的

  1. 保证每个应用的类库独立隔离(即使同限定名不同版本的)
  2. 保证相同类库相同版本的类库共享
  3. 保证容器自身的类库和程序独立

加载顺序

  1. bootstrap 引导类加载器
  2. system 系统类加载器
  3. 应用类加载器 WEB-INF/classes
  4. 应用类加载器 WEB-INF/lib
  5. common 类加载器 CATALINA/lib

【深入浅出-JVM】(76):classloader的更多相关文章

  1. JVM的ClassLoader过程分析

    本文来自网络:深入分析Java ClassLoader原理 http://my.oschina.net/zhengjian/blog/133836 一. JVM的ClassLoader过程以及装载原理 ...

  2. java虚拟机学习-慢慢琢磨JVM(2-1)ClassLoader的工作机制

    ClassLoader的工作机制 java应用环境中不同的class分别由不同的ClassLoader负责加载. 一个jvm中默认的classloader有Bootstrap ClassLoader. ...

  3. JVM思考-ClassLoader.loadClasshe和Class.forName区别

    JVM思考-ClassLoader.loadClasshe和Class.forName区别 目录:JVM总括:目录 见博客第四节:JVM总括四-类加载过程.双亲委派模型.对象实例化过程

  4. 深入浅出 JVM GC(3)

    # 前言 在 深入浅出 JVM GC(2) 中,我们介绍了一些 GC 算法,GC 名词,同时也留下了一个问题,就是每个 GC 收集器的具体作用.有哪些 GC 收集器呢? Serial 串行收集器(只适 ...

  5. 深入浅出 JVM GC(2)

    # 前言 在 深入浅出 JVM GC(1) 中,限于上篇文章的篇幅,我们留下了一个问题 : 如何回收? 这篇文章将重点讲述这个问题. 在上篇文章中,我们也列出了一些大纲,今天我们就按照那个大纲来逐个讲 ...

  6. JVM和ClassLoader

    JVM和ClassLoader 2019-11-08 目录 1 JVM架构整体架构 1.1 类加载器子系统 1.1.1 加载 1.1.2 链接 1.1.3 初始化 1.2 运行时数据区(Runtime ...

  7. 深入浅出 JVM ClassLoader

    # 前言 在 JVM 综述里面,我们说,JVM 做了三件事情,Java 程序的内存管理, Java Class 二进制字节流的加载(ClassLoader),Java 程序的执行(执行引擎).我们也说 ...

  8. JVM的classloader(转)

    Java中一共有四个类加载器,之所以叫类加载器,是程序要用到某个类的时候,要用类加载器载入内存.    这四个类加载器分别为:Bootstrap ClassLoader.Extension Class ...

  9. 关于JVM的ClassLoader(转)

    众所周知,java是编译型的语言,写的是java文件,最后运行的是class文件,class文件是运行在JVM之中的,这时候就有一个问题,JVM如何装载class文件的?是通过ClassLoader来 ...

随机推荐

  1. 如何搭建环境---初识mybatis

    一:mybatis概念1:简介       MyBatis本是apache的一个开源项目iBatis,2010年改名为 MyBatis,       MyBatis 是一个基于Java的持久层框架.( ...

  2. NLP(十五)让模型来告诉你文本中的时间

    背景介绍   在文章NLP入门(十一)从文本中提取时间 中,笔者演示了如何利用分词.词性标注的方法从文本中获取时间.当时的想法比较简单快捷,只是利用了词性标注这个功能而已,因此,在某些地方,时间的识别 ...

  3. 消息中间件——RabbitMQ(二)各大主流消息中间件综合对比介绍!

    前言 消息队列已经逐渐成为企业IT系统内部通信的核心手段.它具有低耦合.可靠投递.广播.流量控制.最终一致性等一系列功能,成为异步RPC的主要手段之一.当今市面上有很多主流的消息中间件,如老牌的Act ...

  4. Tomcat源码分析 (六)----- Tomcat 启动过程(一)

    说到Tomcat的启动,我们都知道,我们每次需要运行tomcat/bin/startup.sh这个脚本,而这个脚本的内容到底是什么呢?我们来看看. 启动脚本 startup.sh 脚本 #!/bin/ ...

  5. 零拷贝Zero copy-linux and java

    背景-几种拷贝方式 方式1:Copying in Two Sample System Calls read(file, tmp_buf, len); write(socket, tmp_buf, le ...

  6. 使用executor、callable以及一个Future 计算欧拉数e

    package test; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMo ...

  7. 解决ionic 启动页面图片没有显示及启动页出现黑白屏

    1.ionic 正确打包完app, 并且按照正常的步骤配置config.xml文件之后 ,启动页面还是不能正常的显示出来,而是黑了一下之后,就进入首页了 原因很有可能就是你没有装cordova-plu ...

  8. unity_实用小技巧(const)

    const:声明某个常量字段或常量局部变量. 注意:常量字段和常量局部变量不是变量并且不能修改 利用const管理游戏标签 例如: //管理所有标签    public const string Pl ...

  9. 红黑树以及与AVL树的区别

    http://blog.csdn.net/zwan0518/article/details/12219055 http://blog.csdn.net/v_july_v/article/details ...

  10. QFramework 使用指南 2020(三):脚本生成(1)基本使用

    在上一篇,我们对 QFramework 的两个主要版本提供了介绍,并且写下了第一个 QFramework 脚本. 在这一篇,我们学习 QFramework 中几乎每个项目都要用到并且从中受益的功能:自 ...