JYM大家好,这里是布洛妮娅, 鸭鸭的更文频道😎,本篇文章是对
JVM
的一个学习记录和总结!!
一、类加载的机制
类加载的过程可分为:
- 装载
- 通过一个类的全限定名,获取此类定义的二进制字节流
- 将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
- 在Java堆中生成一个代表这个类的java.lang.Class对象,作为方法区中这些数据的访问入口
- 链接
- 验证:保证被加载类的正确性
- 文件格式验证,元数据验证,字节码验证,符号引用验证
- 准备
- 为类的静态变量分配内存,并初始化默认值
- 解析
- 把类中的符号引用转化为直接引用
- 初始化
- 使用
- 卸载
二、类加载器
- 启动类加载器 Bootstrap ClassLoader
- 负责Java核心类库的加载,也就是
%{JDK_HOME}\lib
下面的rt.jar
和resources.jar
等.
- 扩展类加载器 Extension ClassLoader
- 负责
%{JDK_HOME}\lib\ext
目录下的一个jar包和class文件
- 应用类加载器 Application ClassLoader
- 负责当前应用里面
classpath
下面的所有jar包和类文件
- 自定义类加载器 Custom ClassLoader
- 通过ClassLoader类来实现自定义加载器
三、双亲委派
我们要加载一个class文件时,会先把这个文件的查询和加载逐级的委派给父加载器执行,如果父加载器都无法加载,最后我们在自己尝试加载. 优点:避免核心类库中的类被覆盖加载,这样做的目的就是优先加载核心类库,避免重复加载导致程序混乱.
四、JVM 如何判断一个对象可以被回收
在 JVM 里面,要判断一个对象是否可以被回收,最重要的是判断这个对象是否还在被使用,只有没被使用的对象才能回收.
- 引用计数器,也就是为每一个对象添加一个引用计数器,用来统计指向当前对象的引用次数,如果当前对象存在应用的更新,那么就对这个引用计数器进行增加,一旦这个引用计数器变成 0,就意味着它可以被回收了.
-
优点:这种方法需要额外的空间来存储引用计数器,但是它的实现很简单,而且效率也比较高.
-
缺点:不过主流的 JVM 都没有采用这种方式,因为引用计数器在处理一些复杂的循环引用或者相互依赖的情况时,可能会出现一些不再使用但是又无法回收的内存,造成内存泄露的问题.
- 可达性分析,它的主要思想是,首先确定一系列肯定不能回收的对象作为GC root,比如虚拟机栈里面的引用对象、本地方法栈引用的对象等,然后以 GC ROOT作为起始节点,从这些节点开始向下搜索,去寻找它的直接和间接引用的对象,当遍历完之后如果发现有一些对象不可到达,那么就认为这些对象已经没有用了,需要被回收。在垃圾回收的时候,JVM 会首先找到所有的 GC root,这个过程会暂停所有用户线程,然后再从 GC Roots 这些根节点向下搜索,可达的对象保留,不可达的就会回收掉.可达性分析是目前主流 JVM 使用的算法.
- GC Root:类加载器、Thread、本地变量表、static成员、常用引用、本地方法栈中的变量