方法

  • 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. U盘重装MacOS-Sierra系统

    Mac系统重新安装两种方法: 1.在线远程重装. 2.制作启动U盘进行重装. 理论上第一种比较简单,但是会比较耗时,实际操作中,由于网上下载的系统版本低于我现在MacOS的版本,导致无法安装,因此只能 ...

  2. 利用tensorboard可视化checkpoint模型文件参数分布

    写在前面: 上周微调一个文本检测模型seglink,将特征提取层进行冻结,只训练分类回归层,然而查看tensorboard发现里面有histogram显示模型各个参数分布,看了目前这个训练模型参数分布 ...

  3. myeclipse源码相关操作

    做web开发经常要看别人的jar里的源码才能搞懂别人的想法,但是源码有的时候需要单独下载很麻烦,甚至有的新的jar根本就是没有源码的,那么我们能不能自己制作源码呢. 从jar中提取源码 说白了,提取源 ...

  4. jjyq app登录接口报:“内容类型不支持”???已解决

    1.在 app上进行登录操作,成功. 2.通过fiddler抓包得到jjyq登录接口的url.param.header. 3.在pycharm中使用requests发起请求,运行报错:内容类型不支持?

  5. 使用文本框TextView/EditText的开源库清单

    在实际的开发中TextView和EditText是非常基本的控件.这两个控件的使用也是十分简单.而TextView/EditText的功能其实也是非常强大,例如简单的图文就可以使用TextView配合 ...

  6. U盘制作启动盘后空间容量变小解决方法

    WinAll的快速恢复方式: 0.windows键+R(调出运行窗口)输入:diskpart回车(调出磁盘管理器) 1.输入:list disk回车(从大小容量确定目标U盘的盘符X) 2.输入:sel ...

  7. .netcore consul实现服务注册与发现-集群部署

    一.Consul的集群介绍 Consul Agent有两种运行模式:Server和Client.这里的Server和Client只是Consul集群层面的区分,与搭建在Cluster之上的应用服务无关 ...

  8. 100天搞定机器学习|day45-53 推荐一本豆瓣评分9.3的书:《Python数据科学手册》

    <Python数据科学手册>共五章,每章介绍一到两个Python数据科学中的重点工具包.首先从IPython和Jupyter开始,它们提供了数据科学家需要的计算环境:第2章讲解能提供nda ...

  9. Android Studio启动模拟器失败

    启动Android Studio的模拟器报“Emulator: Process finished with exit code -1073741819 (0xC0000005)”错误教程: 1.进入该 ...

  10. ionic 技术要点

    1.当遇到数据模型改变了,但是页面渲染的数据却没有改变的时候,尝试执行 $scope.$apply(): 2.时间的定义及监听: 定义事件 showNewMsg并从scope往下广播: $scope. ...