JVM,最强的软件虚拟机

Java Virtual Machine,被称为目前最强的软件虚拟机,然而此虚拟机不是VM box跑的那种win10、linux虚拟机,这里的虚拟机是跑在操作系统之上的。

025_001.jpg

JVM的体系结构图:

字节码文件—-类加载器—->运行时数据区——>执行引擎

025_002.jpg

类的加载、连接与初始化

类的这三个步骤都是在程序运行期间完成的

加载:顾名思义,就是加载类的二进制数据到虚拟机中

连接:首先先验证一下类的正确性,然后给类的静态变量分配内存并初始化,最后一步是吧类中的符号引用转化为真正的地址!

初始化:给静态变量赋予正确的初始值

类的实例化:

为新的对象分配内存、为实例变量赋默认值、为实例变量赋予正确的初始值

双亲委派机制:

在类加载的过程中,如果遇到了一个类名,他会先请示应用类加载器,如果存在的化,再往上请示扩展类加载器,如果存在的话,再往上请示启动类加载器。

其实相当于是加载类的时候,有分权重的,高权重的优先加载,同一个类如果在高权重的类加载器中存在,那么他肯定是没办法加载低权重的类加载器

025_003.jpg

垃圾回收(GC):

垃圾回收主要针对的是堆和方法区,因为java栈那块用完就弹走了,不存在垃圾,本地方法栈也是同理

堆中的垃圾就是那些用不着的对象,方法区也是meta区也有一些用不着的对象

如何判断这些对象是不是垃圾呢?有几种算法

1、引用计算算法

为对象添加一个引用计数器,引用了++,引用失效了–,清除那些引用计数是0的对象

这显然不好,如果两个垃圾互相引用,他们就永远不可能清除了

2、可达性分析算法

定义一个GC root,根据这个搜索,能到的obj就不是垃圾,搜不到的就算垃圾

Java 虚拟机使用该算法来判断对象是否可被回收,GC Roots 一般包含以下内容:

  • 虚拟机栈中局部变量表中引用的对象
  • 本地方法栈中 JNI 中引用的对象
  • 方法区中类静态属性引用的对象
  • 方法区中的常量引用的对象

025_004.jpg

现在问题又来了,如果这个对象,被jvm认为是垃圾了,但是我不认为是垃圾啊,那该怎么办呢?

调用finalize()方法!

当一个对象可被回收时,如果需要执行该对象的 finalize() 方法,那么就有可能在该方法中让对象重新被引用,从而实现自救。自救只能进行一次,如果回收的对象之前调用了 finalize() 方法自救,后面回收时不会再调用该方法。

之后呢,如何清除这些垃圾呢?

又有几种不同的算法:

1、标记-清除

顾名思义,先扫描一波,把垃圾标上,然后再第二波扫描清除

2、标记-整理

和1差不多,让所有存活的对象都向一堆移动,清理掉边界以外的内存

3、复制

025_005.jpg

把内存划分为两块,每次只使用其中之一,然后这一块内存用完了,就将存活的对象复制到另一边,然后再把使用过的空间清理一些,这是主要的算法!

4、分代收集

一般将堆分为新生代和老年代。

  • 新生代使用:复制算法
  • 老年代使用:标记 - 清除 或者 标记 - 整理 算法

JVM,最强的软件虚拟机
https://yiyuwang.be/2021/04/05/2021-04-05-362457275/
作者
StevenWong
发布于
2021年4月5日
许可协议