java ClassLoader(复习,上课笔记)

ClassLoader

类加载器(class loader)用来加载 Java 类到 Java 虚拟机中
1.8以前,ClassLoader为双亲委派模型

双亲委派模型
Bootstrap ClassLoader 启动类加载器 hostport部分(C语言写的)
它用来加载 Java 的核心库,是用原生代码来实现的,并不继承自 java.lang.ClassLoader

Extension ClassLoader 扩展类加载器 jre部分(java写的)
它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类

Application ClassLoader 应用程序类加载器 jre部分(写代码的)
它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader() 来获取它。

ClassLoader 中与加载类相关的方法
getParent() 返回该类加载器的父类加载器。
loadClass(String name) 加载名称为 name 的类,返回的结果是 java.lang.Class 类的实例。
findClass(String name) 查找名称为 name 的类,返回的结果是 java.lang.Class 类的实例。
findLoadedClass(String name) 查找名称为 name 的已经被加载过的类,返回的结果是 java.lang.Class 类的实例。
defineClass(String name, byte[] b, int off, int len) 把字节数组 b 中的内容转换成 Java 类,返回的结果是 java.lang.Class 类的实例。这个方法被声明为 final 的。
resolveClass(Class<?> c) 链接指定的 Java 类。

自定义Classloader

自定义步骤
编写一个类继承自ClassLoader抽象类。
复写它的findClass()方法。
在findClass()方法中调用defineClass()。

自定义ClassLoader的要点:
1.继承原ClassLoader
2.创建一个FindClass方法

原ClassLoader从App ClassLoader向父类询问是否加载过类,从AppClassLoader到ExtClass;再到BootstapLoader,父类均未加载过,就由自己加载ClassInfo,父类加载过就向父类讨要ClassInfo

类加载加载需要调用ClassLoader的LoaderClass方法,LoadClass中需要传一个类路劲 XXX.LoadClass(xxxx);

网络类加载器
下面将通过一个网络类加载器来说明如何通过类加载器来实现组件的动态更新。即基本的场景是:Java 字节代码(.class)文件存放在服务器上,客户端通过网络的方式获取字节代码并执行。当有版本更新的时候,只需要替换掉服务器上保存的文件即可。通过类加载器可以比较简单的实现这种需求。
类 NetworkClassLoader 负责通过网络下载 Java 类字节代码并定义出 Java 类。它的实现与 FileSystemClassLoader 类似。
在通过 NetworkClassLoader 加载了某个版本的类之后,一般有两种做法来使用它。第一种做法是使用 Java 反射 API。另外一种做法是使用接口。需要注意的是,并不能直接在客户端代码中引用从服务器上下载的类,因为客户端代码的类加载器找不到这些类。使用 Java 反射 API 可以直接调用 Java 类的方法。而使用接口的做法则是把接口的类放在客户端中,从服务器上加载实现此接口的不同版本的类。在客户端通过相同的接口来使用这些实现类。网络类加载器的具体代码见 下载 。

首次使用

TT() extend T1();
TT t=new TT();
子类触发首次使用时,父类会先使用
子类首次使用时,父类就一定会首次使用

int c = TT.a;
调用父类的静态,只有父类首次使用,子类不会首次使用

classloader的首次使用
static只在首次使用的时候打印
class.forname(“xxx”); 也能引发首次使用
T1 t=new T1(); 会造成首次使用是因为调用了class.forname方法;
T1.xxx(); 静态方法调用也会造成首次使用
T1.a=2; 静态变量也能引发首次使用
int c=T1.b; 静态常量不会引发首次使用
int c=T1.c; c=new rendom.nextInt(); 静态常量,调用函数一切以变量考虑
静态常量运行后能给出结果的,是变量;不运行就给出结果的就是常量

动态块
调用方法时必执行,只用调用方法时才执行,不执行首次使用

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值