Commit 4a43c04f by ClassmateWang

2021-11-11 15:59 /Netty/黑马/4)NettyApi.md

parent 224f0c00
# 1)类加载器
# 1)类加载器
## 一、定义
`什么是类加载器?`
**Java 编译器**会将Java **代码**转化为**Java 虚拟机的源指令**,并将源指令**存储到.class文件**中,这里每个类文件都会包含某个类或者接口的定义和实现代码。
**Java 类加载器**会处理这些**虚拟机指令**,并将其翻译为**目标机器的机器语言**
## 二、类加载过程
类加载器的分类:
- 引导类加载器
- 加载系统类(往往从rt.jar 文件中进行加载)
- 通常使用C语言来编写,是虚拟机不可分割的一部分
- 没有ClassLoader 对象
- 扩展类加载器
- 从jre/lib/ext 加载标准的扩展jar
- 系统类加载器
- 用于加载应用类
- 从系统环境变量或者-classpath 命令行参数中指定的目录中查找类
在Oracle 的Java 语言实现中,扩展类加载器和系统类加载器都是通过Java来实现的,他们都是URLClassLoader 类的实例
`过程:`
> 注意:虚拟机只加载程序执行时需要的类文件
1. 虚拟机通过文件读取机制从磁盘或者网络加载MyProgram 类文件中的内容
2. 类的解析(加载某个类依赖的所有类):如果MyProgram 类拥有类型为另一个类的域,或者是拥有超类,则这些类文件也会被加载
3. 接着 虚拟机执行MyProgram 中的main 方法
4. 如果mai 方法或者main 调用的方法要用到更多的类,那么接下来就会加载这些类
## 三、类加载器的层次结构
类加载器都有一种父——子的层次结构,**除了引导类加载器外,每个类都有一个父类加载器**。且类加载器会为它的父类加载器提供给一个机会,以便加载任何给定的类,**并且只有其父类加载器加载失败时,它才会执行并加载该类**
> 比如说:
>
> ​ 如果要求系统类加载器加载一个系统类(java.util.ArrayList),它首先会要求扩展类加载器去加载,而扩展类加载器会要求引导类加载器去加载。
>
> 此时引导类加载器会找到并加载rt.jar 中的这个类,而不需要其他类加载器做更多的处理。
如果说对应的类被达成了jar包,那么可以直接的通过URLClassLoader 类的实例去加载这些类:
```java
URL url = new URL("file://path/to/plugin.jar");
URLClassLoader pluginLoader = new URLClassLoader(new URL[]{url});
Class<?> cl = pluginLoader.loadClass("mypackage.MyClass");
```
因为URLClassLoader 中并没有指定父类加载器,所以pluginLoader的父类加载器就是系统类加载器
每个线程都有一个类加载器的引用,称为上下文类加载器,主线程的上下文类加载器是系统类加载器,当新的线程创建时,这些新线程的类加载器就会被设置为创建他们的线程的类加载器,所以如果不做任何操作的话**所有线程的类加载器都将是系统类加载器**
`设置类加载器:`
```java
Thread t = Thread.currentThread();
t.setContextClassLoader(loader);
```
`获取类加载器:`
```java
Thread t = Thread.currentThread();
ClassLoader loader = t.getContextClassLoader();
/*通过获取的类加载器加载类*/
Class cl = loader.loadClass(className);
```
## 四、类加载器作为命名空间
在同一个虚拟机中其实是允许两个包名和类名都相同的类存在,因为类是由它的类全名和类加载器确定的,这项技术在加载来自多出的代码时非常有用。
可以通过不同的类加载器的实例去加载,就可以避免因为类名重复的情况引发的问题。**也就是说即使包名类名相同若使用不同的类加载器也能保证不冲突。**
# Java 虚拟机结构
# Java 虚拟机结构
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment