diff --git a/docs/java/jvm/类加载器.md b/docs/java/jvm/类加载器.md index 37394a92..9b6f46ac 100644 --- a/docs/java/jvm/类加载器.md +++ b/docs/java/jvm/类加载器.md @@ -16,7 +16,7 @@ ## 回顾一下类加载过程 -类加载过程:**加载->连接->初始化**。连接过程又可分为三步:**验证->准备->解析**。 +类加载过程:**加载->连接->初始化**。连接过程又可分为三步:**验证->准备->解析**。 ![类加载过程](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/类加载过程.png) @@ -30,7 +30,7 @@ JVM 中内置了三个重要的 ClassLoader,除了 BootstrapClassLoader 其他 1. **BootstrapClassLoader(启动类加载器)** :最顶层的加载类,由C++实现,负责加载 `%JAVA_HOME%/lib`目录下的jar包和类或者或被 `-Xbootclasspath`参数指定的路径中的所有类。 2. **ExtensionClassLoader(扩展类加载器)** :主要负责加载目录 `%JRE_HOME%/lib/ext` 目录下的jar包和类,或被 `java.ext.dirs` 系统变量所指定的路径下的jar包。 -3. **AppClassLoader(应用程序类加载器)** :面向我们用户的加载器,负责加载当前应用classpath下的所有jar包和类。 +3. **AppClassLoader(应用程序类加载器)** :面向我们用户的加载器,负责加载当前应用classpath下的所有jar包和类。 ## 双亲委派模型 @@ -60,7 +60,7 @@ The Parent of ClassLodarDemo's ClassLoader is sun.misc.Launcher$ExtClassLoader@1 The GrandParent of ClassLodarDemo's ClassLoader is null ``` -`AppClassLoader`的父类加载器为`ExtClassLoader` +`AppClassLoader`的父类加载器为`ExtClassLoader`, `ExtClassLoader`的父类加载器为null,**null并不代表`ExtClassLoader`没有父类加载器,而是 `BootstrapClassLoader`** 。 其实这个双亲翻译的容易让别人误解,我们一般理解的双亲都是父母,这里的双亲更多地表达的是“父母这一辈”的人而已,并不是说真的有一个 Mother ClassLoader 和一个 Father ClassLoader 。另外,类加载器之间的“父子”关系也不是通过继承来体现的,是由“优先级”来决定。官方API文档对这部分的描述如下: diff --git a/docs/java/jvm/类加载过程.md b/docs/java/jvm/类加载过程.md index d2dacdb1..cd04e42a 100644 --- a/docs/java/jvm/类加载过程.md +++ b/docs/java/jvm/类加载过程.md @@ -23,7 +23,7 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚拟机是如何加载这些 Class 文件呢? -系统加载 Class 类型的文件主要三步:**加载->连接->初始化**。连接过程又可分为三步:**验证->准备->解析**。 +系统加载 Class 类型的文件主要三步:**加载->连接->初始化**。连接过程又可分为三步:**验证->准备->解析**。 ![](https://my-blog-to-use.oss-cn-beijing.aliyuncs.com/2019-6/类加载过程.png) @@ -33,7 +33,7 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚 1. 通过全类名获取定义此类的二进制字节流 2. 将字节流所代表的静态存储结构转换为方法区的运行时数据结构 -3. 在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口 +3. 在内存中生成一个代表该类的 Class 对象,作为方法区这些数据的访问入口 虚拟机规范上面这3点并不具体,因此是非常灵活的。比如:"通过全类名获取定义此类的二进制字节流" 并没有指明具体从哪里获取、怎样获取。比如:比较常见的就是从 ZIP 包中读取(日后出现的JAR、EAR、WAR格式的基础)、其他文件生成(典型应用就是JSP)等等。 @@ -70,7 +70,7 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚 初始化是类加载的最后一步,也是真正执行类中定义的 Java 程序代码(字节码),初始化阶段是执行初始化方法 ` ()`方法的过程。 -对于`()` 方法的调用,虚拟机会自己确保其在多线程环境中的安全性。因为 `()` 方法是带锁线程安全,所以在多线程环境下进行类初始化的话可能会引起死锁,并且这种死锁很难被发现。 +对于` ()` 方法的调用,虚拟机会自己确保其在多线程环境中的安全性。因为 ` ()` 方法是带锁线程安全,所以在多线程环境下进行类初始化的话可能会引起死锁,并且这种死锁很难被发现。 对于初始化阶段,虚拟机严格规范了有且只有5种情况下,必须对类进行初始化(只有主动去使用类才会初始化类): @@ -79,7 +79,7 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚 - 当jvm执行getstatic指令时会初始化类。即程序访问类的静态变量(不是静态常量,常量会被加载到运行时常量池)。 - 当jvm执行putstatic指令时会初始化类。即程序给类的静态变量赋值。 - 当jvm执行invokestatic指令时会初始化类。即程序调用类的静态方法。 -2. 使用 `java.lang.reflect` 包的方法对类进行反射调用时如Class.forname("..."),newInstance()等等。 ,如果类没初始化,需要触发其初始化。 +2. 使用 `java.lang.reflect` 包的方法对类进行反射调用时如Class.forname("..."), newInstance()等等。如果类没初始化,需要触发其初始化。 3. 初始化一个类,如果其父类还未初始化,则先触发该父类的初始化。 4. 当虚拟机启动时,用户需要定义一个要执行的主类 (包含 main 方法的那个类),虚拟机会先初始化这个类。 5. MethodHandle和VarHandle可以看作是轻量级的反射调用机制,而要想使用这2个调用, @@ -100,7 +100,7 @@ Class 文件需要加载到虚拟机中之后才能运行和使用,那么虚 所以,在JVM生命周期类,由jvm自带的类加载器加载的类是不会被卸载的。但是由我们自定义的类加载器加载的类是可能被卸载的。 -只要想通一点就好了,jdk自带的BootstrapClassLoader,ExtClassLoader,AppClassLoader负责加载jdk提供的类,所以它们(类加载器的实例)肯定不会被回收。而我们自定义的类加载器的实例是可以被回收的,所以使用我们自定义加载器加载的类是可以被卸载掉的。 +只要想通一点就好了,jdk自带的BootstrapClassLoader, ExtClassLoader, AppClassLoader负责加载jdk提供的类,所以它们(类加载器的实例)肯定不会被回收。而我们自定义的类加载器的实例是可以被回收的,所以使用我们自定义加载器加载的类是可以被卸载掉的。 **参考** diff --git a/docs/system-design/authority-certification/basis-of-authority-certification.md b/docs/system-design/authority-certification/basis-of-authority-certification.md index 12a0fd91..22055861 100644 --- a/docs/system-design/authority-certification/basis-of-authority-certification.md +++ b/docs/system-design/authority-certification/basis-of-authority-certification.md @@ -37,7 +37,7 @@ Cookie 和 Session都是用来跟踪浏览器用户身份的会话方式,但 ### 2.2 如何在服务端使用 Cookie 呢? -这部分内容参考:https://attacomsian.com/blog/cookies-spring-boot, 更多如何在Spring Boot中使用Cookie 的内容可以查看这篇文章。 +这部分内容参考:https://attacomsian.com/blog/cookies-spring-boot, 更多如何在Spring Boot中使用Cookie 的内容可以查看这篇文章。 **1)设置cookie返回给客户端**