一、类加载体系

类加载方式:代理模式 或 双亲委托

例1:

 1 package classloader.system;
2
3 public class Example {
4 public static void main(String[] args) {
5 /*应用的类加载器是AppClassLoader,首先委托父ClassLoder(ExtClassLoder)从他自己的资源池中(jre/lib/ext)找这个类,
6 * 在这之前,ExtClassLoder又委托父ClassLoader(BootStrapClassLoader)从jre/lib找这个类;
7 * BootStrapClassLoader在jre/lib没找到需要的类,返回到ExtClassLoder;ExtClassLoder在jre/lib/ext没找到需要的类,返回到AppClassLoader
8 *AppClassLoader从自己的资源池中查找 c = findClass(name);
9 *
10 */
11 ClassLoader cl = Example.class.getClassLoader();
12 while (cl != null) {
13 System.out.println(cl.toString());
14 cl = cl.getParent();
15 }
16 }
17 }

结果:

sun.misc.Launcher$AppClassLoader@425224ee
sun.misc.Launcher$ExtClassLoader@1ef6a746

例2:在eclipse中点击例1中的11行ClassLoader,进入ClassLoader类的代码,找到loadClass方法,里面就是详细的类加载代码

 1  protected synchronized Class<?> loadClass(String name, boolean resolve)
2 throws ClassNotFoundException
3 {
4 // First, check if the class has already been loaded
5 Class c = findLoadedClass(name);
6 if (c == null) {
7 try {
8 if (parent != null) {
9 c = parent.loadClass(name, false); //递归通过父加载器加载
10 } else {
11 c = findBootstrapClassOrNull(name); //从根加载器的资源池中查找这个类
12 }
13 } catch (ClassNotFoundException e) {
14 // ClassNotFoundException thrown if class not found
15 // from the non-null parent class loader
16 }
17 if (c == null) {
18 // If still not found, then invoke findClass in order
19 // to find the class.
20 c = findClass(name); //应用加载器从自己的资源池中查找这个类
21 }
22 }
23 if (resolve) {
24 resolveClass(c);
25 }
26 return c;
27 }
为什么要这么做呢?(即为什么要用 代理模式 或 双亲委托)
安全考虑:直接在AppClassLoader写一个String这样的类,如果不是委托父类加载,这个类可能性能不高、有问题,导致加载类的时候出现一些意想不到的错误   通过这样的委托模式,使得JDK自己的类能够优先加载,保证这些类的安全等
 
注意:
ExtClassLoader  ——这个加载器对应的资源池(目录)建议一般不要改,比如jboss的数据库加密安全算法在这里面
自定义的classLoader——配置相关的加载地方
 
二、自定义的classLoader配置相关的资源池(从什么地方加载相关类),模拟了从classpath之外的地方加载类
 
例3:Example.java
 1 package classloader.system2;
2
3 import java.lang.reflect.Method;
4 import java.net.MalformedURLException;
5 import java.net.URL;
6 import java.net.URLClassLoader;
7 import java.io.File;
8
9 public class Example {
10 public static void main(String[] args) throws Exception {
11 /*前面假设是一个web容器,web容器通过前面的方式启动起来了;当你扔一个war包进去,war包有自己的ClassLoader以及自己的url,url指向war包里面的lib目录
12 * 相当于可以从url里面加载类 用web应用的classloader去加载相关的类,并且调它的初始化方法,就可以让我自己的war包运行起来
13 * war包里面都有一个web.xml,web.xml描述了Servlet,相当于描述了全称类名叫什么,我就可以启动相关的Servlet;相关的Servlet启动以后,我就可以接受请求并进行分发,web容器就基本上运行起来了
14 *
15 *
16 */
17 URL url = new File(args[0]).toURL();
18 ClassLoader cl = new URLClassLoader(new URL[]{url});
19 Class<?> tvClass = cl.loadClass("classloader.system2.Television");
20 Object tv = tvClass.newInstance(); //因为我们当前classpath下是没有Television类的,所以这里定义为Object tv
21
22 Object panel = cl.loadClass("classloader.system2.Panel").newInstance(); //load一个面板并实例化
23 Method setPanelMethod = tvClass.getMethod("setPanel", Object.class);
24 setPanelMethod.invoke(tv, panel);
25 Method playVideoMethod = tvClass.getMethod("playVideo", new Class[]{});
26 playVideoMethod.invoke(tv, new Object[]{});
27
28 System.out.println("不同的ClassLoader加载。。。");
29 ClassLoader cl2 = new URLClassLoader(new URL[]{url});
30 Object panel2 = cl2.loadClass("classloader.system2.Panel").newInstance();
31 setPanelMethod.invoke(tv, panel2); //tv是cl加载的,panel2是cl2加载的,两个不同的classload,它们之间的对象是不能直接进行装配的,会认为不一样的
32 }
33 }
34
35 //将Panel和Televison两个类拷贝到特定目录并编译,并删除当前classpath下的两个类

//Television.java

 1 package classloader.system2;
2
3 public class Television {
4 private Panel panel; //面板
5
6 public void playVideo() {
7 panel.display();
8 }
9
10 public void setPanel(Object panel) {
11 this.panel = (Panel)panel;
12 }
13 }

//Panel.java

1 package classloader.system2;
2
3 public class Panel {
4 public void display() {
5 System.out.println("In Panel: display()");
6 }
7 }

运行:

编译好后,将Panel和Televison两个类class文件拷贝到特定目录(如下),并删除当前classpath下的两个类(main的参数String[] args为d:\tmp)

1、ClassLoader cl = new URLClassLoader(new URL[]{url}); 这个classLoader所指向的url在d:\,d:\下Class<?> tvClass = cl.loadClass("classloader.system2.Television");时找不到,所以就报错了

2、填写正确的路径

 classloader.system2.Panel cannot be cast to classloader.system2.Panel报错原因如下:
tv是cl加载的,panel2是cl2加载的,两个不同的classload,它们之间的对象是不能直接进行装配的,会认为不一样的

对象与类的加载 小结:
1、并非所有的类都需要在CLASSPATH中
2、对象的赋值与转换与其ClassLoader相关
3、类在一个ClassLoader中只加载一次

三、与类加载相关的异常

1、ClassNotFoundException
2、NoClassDefFoundError
 1 package classloader.exception;
2
3
4 public class Example {
5 public static void main(String[] args) throws Exception {
6 Television tv = (Television) Example.class.getClassLoader()
7 .loadClass("classloader.exception.Television").newInstance(); //loadClass("classloader.exception.Television1") 就会抛java.lang.ClassNotFoundException:
8 //exception
9 tv.playVideo();
10 }
11 }
12
13 class Television {
14 //private Panel panel; 会报错at classloader.exception.Television.playVideo(Example.java:17)
15 private Panel panel = new Panel(); //Televison编译强依赖于Panel,如果编译好后再删除Panel.class,运行时会报java.lang.NoClassDefFoundError: classloader/exception/Panel
16 //error
17 public void playVideo() {
18 panel.display();
19 }
20
21 public void setPanel(Object panel) {
22 this.panel = (Panel)panel;
23 }
24 }
25
26
27 class Panel {
28 public void display() {
29 System.out.println("In Panel: display()");
30 }
31 }

四、类的回收
1、ClassLoader加载类,类实例化对象
2、当某个ClassLoader加载的所有类实例化的所有对象都被回收了,则该CL会被回收

类对象实例化业务对象

 web容器放了个war包,当war包被应用服务器加载起来后,应用服务器会为这个war包分配classloader,classloader负责加载这个war包里面的

所有资源,加载完了后开始运行,直到某一时刻,我们觉得这些所有对象都不需要了,里面的所有资源要被回收掉,如Servlet要被销毁等一系列步骤;

当这些类加载出来的对象都被回收后,这个classloader就可以被回收掉了


classloaderA   A1

classloaderB   B1   B1持有A1对象,classloaderA不能被回收


五、类的热替换思路

参考:
 

JAVA类的加载(4) ——类之间能够隔离&类占用的资源能回收的更多相关文章

  1. JAVA类的加载、连接与初始化

    JAVA类的加载.连接与初始化 类的声明周期总共分为5个步骤1.加载2.连接3.初始化4.使用5.卸载 当java程序需要某个类的时候,java虚拟机会确保这个类已经被加载.连接和初始化,而连接这个类 ...

  2. jvm系列(一):java类的加载机制

    java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang.Class对象,用来封装 ...

  3. [Java]类的生命周期(上)类的加载和连接[转]

    本文来自:曹胜欢博客专栏.转载请注明出处:http://blog.csdn.net/csh624366188 类加载器,顾名思义,类加载器(class loader)用来加载 Java 类到 Java ...

  4. java类生命周期,类的“加载,连接,初始化,使用,卸载过程”详解

    “ 如果说核心类库的 API 比做数学公式的话,那么 Java 虚拟机的知识就好比公式的推导过程” 每本Java入门书籍在介绍Java这门语言的时候都会提到Java跨平台,“一次解释,到处运行的特点“ ...

  5. JVM(1):Java 类的加载机制

    原文出处: 纯洁的微笑 java类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内存中,将其放在运行时数据区的方法区内,然后在堆区创建一个java.lang. ...

  6. Java 类的加载与初始化

    本文结构: 1.先看几道题 2.类的加载于初始化 (1)类的加载 (2)类的初始化 (a)会发生类的初始化的情况 (b)不会发生类的初始化的情况 首先看几道题. 解析可在看完讲解后再看 Demo1 p ...

  7. <JVM中篇:字节码与类的加载篇>03-类的加载过程(类的生命周期)详解

    笔记来源:尚硅谷JVM全套教程,百万播放,全网巅峰(宋红康详解java虚拟机) 同步更新:https://gitee.com/vectorx/NOTE_JVM https://codechina.cs ...

  8. JVM 1.类的加载、连接、初始化

    Java类的加载是由类加载器来完成的,过程如下: 首先,加载是把硬盘.网络.数据库等的class文件中的二进制数据加载到内存的过程,然后会在Java虚拟机的运行时数据区的堆区创建一个Class对象,用 ...

  9. JVM-01:类的加载机制

    本文从 纯洁的微笑的博客 转载 原地址:http://www.ityouknow.com/jvm.html 类的加载机制 1.什么是类的加载 类的加载指的是将类的.class文件中的二进制数据读入到内 ...

  10. 24.类的加载机制和反射.md

    目录 1类的加载连接和初始化 1.1类的加载过程 1.2类的加载器 1.2.1类的加载机制 1类的加载连接和初始化 1.1类的加载过程 类的加载过程简单为分为三步:加载->连接->初始化 ...

随机推荐

  1. react项目中使用plop

    第一步,安装依赖 npm install plop --dev //或者用yarn yarn add plop --dev 第二步,在package同级目录下新建plopfile.js 这是plop的 ...

  2. Blazor如何跟随“系统主题”?

    1. 前言 跟随系统主题已经是绝大多数App和网站的标配 但是如何在Blazor中跟随系统主题? 只找到Masa Blazor技术团队发的 MAUI + Masa Blazor 开发界面跟随系统主题切 ...

  3. 深入Scikit-learn:掌握Python最强大的机器学习库

    本篇博客详细介绍了Python机器学习库Scikit-learn的使用方法和主要特性.内容涵盖了如何安装和配置Scikit-learn,Scikit-learn的主要特性,如何进行数据预处理,如何使用 ...

  4. pyinstaller 安装报错,环境是python3.7

    在pycharm中安装,和直接输入pip install pyinstaller 均报错, 最后,输入pip install -i https://pypi.douban.com/simple/ py ...

  5. 建设数字工厂:MRP物料需求计划的逻辑原理与配置方法

    本文分享自华为云社区<数字工厂深入浅出系列(七): MRP物料需求计划的逻辑原理与配置方法>,作者:云起MAE. MRP是生产制造企业"管好"物料的核心工具方法,基本思 ...

  6. 部署基于etcd的coredns集群

    前言 现需要为公司搭建私有DNS,私有服务器都使用私有DNS的地址,便于访问内部自定义的域名.采用CoreDNS + ETCD方案部署,coredns和etcd都以三实例运行,etcd为集群模式,使用 ...

  7. debian11编译安装freeswitch

    前言 环境: 系统版本:debian 11 x86_64 FreeSWITCH版本:1.10.6 安装步骤 安装依赖(安装之前最好换apt软件源为国内的) apt install -y gnupg2 ...

  8. typora使用教程&高级用法&Markdown

    typora使用教程&高级用法&Markdown typora介绍 哇啦哇啦哇啦哇,,,,,,,,,,,,, 提示:小白看不懂的话,建议哔哩哔哩搜索"遇见狂神说", ...

  9. WPF-封装自定义雷达图控件

    源码地址:https://gitee.com/LiuShuiRuoBing/code_blog 雷达图用于表示不同内容的占比关系,在项目中有广泛的应用,但是目前未曾有封装良好的雷达图控件,鉴于最近项目 ...

  10. 《SQL与数据库基础》22. 分库分表(二)

    目录 分库分表(二) MyCat分片规则 范围分片 取模分片 一致性hash分片 枚举分片 应用指定算法 固定分片hash算法 字符串hash解析 按天分片 自然月分片 MyCat原理 MyCat管理 ...