jvm-题库

1、JVM内存模型

在这里插入图片描述

JVM内存区域总共分为两种类型
线程私有区域:程序计数器、本地方法栈和虚拟机栈
线程共享区域:堆(heap)和方法区

特征
线程私有区域:依赖用户的线程创建而创建、销毁而销毁,因用户每次访问都会独立开启一个线程,跟本地的线程相对应(用白话文讲就是同生共死或朝生夕死);
线程共享区域:它是随着虚拟机的开启而创建,关闭而销毁;

名词解释
程序计数器
用户每次访问都会独立开启一个线程,程序计数器会记录每次当前执行代码的行号指示器

本地方法栈
本地方法栈是用来区别虚拟机调用外部的执行方法,而本地方法栈则为Native修饰,那么该方法是一个C栈,Sun HotSpot将本地方法栈与虚拟机栈合二为一

堆(heap)
创建的数组和对象都放入java堆中,当然也是垃圾收集器重要回收的地方, VM主要采用分代收集算法,主要产生在新生代(Yong GC)(Eden 区From 和To)和 老年代

方法区
用来存储于类、运行常量池、静态的变量和编译编译后的代码等数据,java VM会把这些信息收集到方法区,即用java堆的永久代来实现方法区,这样就可以实现VM 像堆内存一样管理方法区的内存

在这里插入图片描述
在这里插入图片描述

2、JVM运行时内存分配

Java堆内存可以分为:新生代(Enden、SurvivorFrom和SurvivorTo)老年代、元空间
新生代与老年代默认比例是1:2
新生代中Enden SurvivorFrom SurvivorTo 默认比例是:8:1:1

新生代
是用来存放new的对象。一般占据堆的1/3空间。由于频繁创建对象,所以新生代会频繁触发MinorGC 进行垃圾回收。新生代又分为 Eden 区、ServivorFrom、ServivorTo 三个区。

Enden
用来存放新的对象出生地(当新创建对象很大时,会直接分配到老年代),当新生代内存不够时会触动MinorGc,会对新生产生垃圾回收

SurvivorFrom
上一次 GC 的幸存者,作为这一次 GC 的被扫描者

SurvivorTo
保留了一次 MinorGC 过程中的幸存者

采用的算法
MinorGC 的过程(复制->清空->互换)

复制算法
执行流程
eden 和SurvivorFrom 复制到 SurvivorTo,年龄+1
首先,把 Eden和 SurvivorFrom区域中存活的对象复制到 SurvicorTo区域(如果有对象的年龄以及达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 够位置了就放到老年区);
清空 Eden 和 ServicorFrom 中的对象;
ServicorTo 和 ServicorFrom 互换最后,ServicorTo 和 ServicorFrom 互换,原 ServicorTo 成为下一次 GC 时的 ServicorFrom区。

老年代
主要存放应用程序中生命周期长的内存对象。
老年代的对象比较稳定,所以 MajorGC 不会频繁执行。在进行 MajorGC 前一般都先进行
了一次 MinorGC,使得有新生代的对象晋身入老年代,导致空间不够用时才触发。当无法找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次 MajorGC 进行垃圾回收腾出空间。
MajorGC 采用标记清除算法:首先扫描一次所有老年代,标记出存活的对象,然后回收没有标记的对象。MajorGC 的耗时比较长,因为要扫描再回收。MajorGC 会产生内存碎片,为了减少内存损耗,我们一般需要进行合并或者标记出来方便下次直接分配。当老年代也满了装不下的时候,就会抛出 OOM(Out of Memory)异常。

永久代
指内存的永久保存区域,主要存放 Class 和 Meta(元数据)的信息,Class 在被加载的时候被放入永久区域,它和和存放实例的区域不同,GC 不会在主程序运行期对永久区域进行清理。所以这也导致了永久代的区域会随着加载的 Class 的增多而胀满,最终抛出 OOM 异常。

JAVA8 与元数据

在Java8中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入 native memory, 字符串池和类的静态变量放入 java 堆中,这样可以加载多少类的元数据就不再由MaxPermSize 控制, 而由系统的实际可用空间来控制。

3、如何确定当前对象是个垃圾

引用计数法
在 Java 中,引用和对象是有关联的。如果要操作对象则必须用引用进行。因此,很显然一个简单的办法是通过引用计数来判断一个对象是否可以回收。简单说,即一个对象如果没有任何与之关联的引用,即他们的引用计数都不为 0,则说明对象不太可能再被用到,那么个对象就是可回收对象。

相互引用的时候,内存不能回收;
所谓引用计数法,每个对象额外保存一个计数属性,如果有一个对象引用了它,那么该属性会加1,例,

A a = new A();
A a2 = a;

上面这段代码会在堆中生成一个A的对象实例,且a、a2都指向了该对象,那么该对象的计数属性便是2,又如,

A a = new A();
A a2 = a;
a = null;
a2 = null;

这时a、a2均指向了null,那么A的对象实例的计数属性则为0,按照引用计数法的定义这时该实例可以被回收。

A a = new A();
B b = new B();
a.b = b;
b.a = a;
a = null;
b = null;

上面的代码在堆中会有一个A的实例一个B的实例,且计数属性均为1,执行了第3、4两行代码后,两个实例的引用计数均为2,执行了5、6两行代码后两个实例的计数属性均为1,这时a、b均指向了null,但是堆中的两个实例的计数属性的值却不为0,那么这两个实例无法回收,存在内存泄漏的风险;

可达性分析
为了解决引用计数法的循环引用问题,Java 使用了可达性分析的方法。通过一系列的“GC roots”对象作为起点搜索。如果在“GC roots”和一个对象之间没有可达路径,则称该对象是不可达的。要注意的是,不可达对象不等价于可回收对象,不可达对象变为可回收对象至少要经过两次标记过程。两次标记后仍然是可回收对象,则将面临回收。

4、GCrooot 包括哪些?

虚拟机栈(栈桢中的局部变量表操作数栈)中的引用的对象
方法区中的类静态属性引用的对象
方法区中的常量引用的对象
本地方法栈中JNI的引用的对象

5、JVM对象头包含哪些部分

在HotSpot虚拟机中,对象在内存中存储的布局可以分为3块区域:对象头(Header)、实例数据(Instance Data)和对⻬填充(Padding)
对象头
实例数据
对⻬填充

在这里插入图片描述

给定⼀个具体的类,请分析对象的内存占用!
在这里插入图片描述
每个long类型的字段占⽤8字节,3个long字段占⽤24字节。byte 字段占⽤1个字节。

在这里插入图片描述

6、GC算法有哪些

标记清除算法( Mark-Sweep )
分为两个阶段,标注和清除。标记阶段标记出所有需要回收的对象,清除阶段回收被标记的对象所占用的空间。如图
在这里插入图片描述
从图中我们就可以发现,该算法最大的问题是:内存碎片化严重,效率低后续可能发生大对象不能找到可利用空间的问题
在这里插入图片描述
复制算法( copying )
按内存容量将内存划分为等大小的两块。每次只使用其中一块,当这一块内存满后将尚存活的对象复制到另一块上去,把已使用的内存清掉,如图:

在这里插入图片描述

这种算法虽然实现简单,内存效率高,不易产生碎片,但是最大的问题是:可用内存被压缩到了原本的一半。且存活对象增多的话,Copying 算法的效率会大大降低。

标记整理算法(Mark-Compact)
结合了以上两个算法,为了避免缺陷而提出。标记阶段和 Mark-Sweep 算法相同,标记后不是清理对象,而是将存活对象移向内存的一端。然后清除端边界外的对象。如图:

在这里插入图片描述

7、JVM中类的加载机制

在这里插入图片描述

1)加载→验证→准备→解析→初始化
加载
加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的入口;
2) 验证
确保这个类符合要求
3) 准备
加载一些静态变量和常量
4) 解析
把编译class文件进行解析
5)初始化
初始化默认对象属性信息

8、分代收集算法

分代收集法是目前大部分 JVM 所采用的方法,其核心思想是根据对象存活的不同生命周期将内存划分为不同的域,一般情况下将 GC 堆划分为老生代(Tenured/Old Generation)和新生代(YoungGeneration)。老年代的特点是每次垃圾回收时只有少量对象需要被回收,新生代的特点是每次垃圾回收时都有大量垃圾需要被回收,因此可以根据不同区域选择不同的算法。

新生代采用复制算法
目前大部分 JVM 的 GC 对于新生代都采取 Copying 算法,因为新生代中每次垃圾回收都需要频繁回收对象,即要复制的操作比较少,但通常并不是按照 1:1 来划分新生代。一般将新生代划分为一块较大的 Eden 空间和两个较小的 Survivor 空间(From Space, To Space),每次使用 Eden 空间和其中的一块Survivor 空间,当进行回收时,将该两块空间中还存活的对象复制到另一块 Survivor 空间中。

老年代采用复制算法
而老年代因为每次只回收少量对象,因而采用 Mark-Compact 算法。
当对象在 Survivor 区躲过一次 GC 后,其年龄就会+1。默认情况下年龄到达 15 的对象会被移到老生代中。

9、JDK1.8 和 1.7做了哪些优化

在 Java8 中,永久代已经被移除,被一个称为“元数据区”(元空间)的区域所取代。元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是使用本地内存。因此,默认情况下,元空间的大小仅受本地内存限制。类的元数据放入 native memory, 字符串池和类的静态变量放入 java 堆中,这样可以加载多少类的元数据就不再由MaxPermSize 控制, 而由系统的实际可用空间来控制。

10、内存泄漏和内存溢出有什么区别

Csdn : JAVA内存泄漏和内存溢出的区别和联系_马帅的博客的博客-CSDN博客_java内存泄漏和内存溢出

内存泄漏 memory leak
是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。

内存溢出 out of memory
指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出。

二者的关系
内存泄漏的堆积最终会导致内存溢出
内存溢出:就是你要的内存空间超过了系统实际分配给你的空间,此时系统相当于没法满足你的需求,就会报内存溢出的错误。
内存泄漏:是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。就相当于你租了个带钥匙的柜子,你存完东西之后把柜子锁上之后,把钥匙丢了或者没有将钥匙还回去,那么结果就是这个柜子将无法供给任何人使用,也无法被垃圾回收器回收,因为找不到他的任何信息。
内存溢出:一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出。比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。说白了就是我承受不了那么多,那我就报错

内存泄漏的分类(按发生方式来分类)
常发性内存泄漏。发生内存泄漏的代码会被多次执行到,每次被执行的时候都会导致一块内存泄漏。
偶发性内存泄漏。发生内存泄漏的代码只有在某些特定环境或操作过程下才会发生。常发性和偶发性是相对的。对于特定的环境,偶发性的也许就变成了常发性的。所以测试环境和测试方法对检测内存泄漏至关重要。
一次性内存泄漏。发生内存泄漏的代码只会被执行一次,或者由于算法上的缺陷,导致总会有一块仅且一块内存发生泄漏。比如,在类的构造函数中分配内存,在析构函数中却没有释放该内存,所以内存泄漏只会发生一次。

隐式内存泄漏。程序在运行过程中不停的分配内存,但是直到结束的时候才释放内存。严格的说这里并没有发生内存泄漏,因为最终程序释放了所有申请的内存。但是对于一个服务器程序,需要运行几天,几周甚至几个月,不及时释放内存也可能导致最终耗尽系统的所有内存。所以,我们称这类内存泄漏为隐式内存泄漏。

内存溢出的原因及解决方法:
内存中加载的数据量过于庞大,如一次从数据库取出过多数据;
集合类中有对对象的引用,使用完后未清空,使得JVM不能回收;
代码中存在死循环或循环产生过多重复的对象实体;
使用的第三方软件中的BUG;
启动参数内存值设定的过小

内存溢出的解决方案:
第一步,修改JVM启动参数,直接增加内存。(-Xms,-Xmx参数一定不要忘记加。)
第二步,检查错误日志,查看“OutOfMemory”错误前是否有其 它异常或错误。
第三步,对代码进行走查和分析,找出可能发生内存溢出的位置。

重点排查以下几点:
检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。
检查代码中是否有死循环或递归调用。
检查是否有大循环重复产生新对象实体。
检查对数据库查询中,是否有一次获得全部数据的查询。一般来说,如果一次取十万条记录到内存,就可能引起内存溢出。这个问题比较隐蔽,在上线前,数据库中数据较少,不容易出问题,上线后,数据库中数据多了,一次查询就有可能引起内存溢出。因此对于数据库查询尽量采用分页的方式查询。
检查List、MAP等集合对象是否有使用完后,未清除的问题。List、MAP等集合对象会始终存有对对象的引用,使得这些对象不能被GC回收。

11、JVM中栈上分配和内存逃逸解释

栈上分配:就是把没发生逃逸的对象,在栈帧分配空间。(一般对象分配空间是在堆)逃逸
逃逸分析(个人理解):就是方法内的对象,可以被方法外所访问
栈上分配:就是把没发生逃逸的对象,在栈分配空间。(一般对象分配空间是在堆)逃逸

二者联系:jvm根据对象是否发生逃逸,会分配到不同(堆或栈)的存储空间。
如果对象发生逃逸,那会分配到堆中。(因为对象发生了逃逸,就代表这个对象可以被外部访问,换句话说,就是可以共享,能共享数据的,无非就是堆或方法区,这里就是堆。)

如果对象没发生逃逸,那会分配到栈中。(因为对象没发生逃逸,那就代表这个对象不能被外部访问,换句话说,就是不可共享,这里就是栈。)
那我们再想深一层,为什么会有逃逸分析,有栈上分配这些东西?
当然是为了主体的考虑,主体就是jvm,或者直接说为了GC考虑也不为过。大家想想,GC主要回收的对象是堆和方法区。GC不会对栈、程序计数器这些进行回收的,因为没东西可以回收。

12、如何定位CPU100%占用

Linux 命令使用 top命令
在这里插入图片描述
执⾏top -p 2732单独监控该进程
在第2步的监控界⾯输⼊H,获取当前进程下的所有线程信息
在这里插入图片描述
找到消耗cpu特别⾼的线程编号(假设是2734)
在这里插入图片描述
执⾏jstack 2732对当前的进程做dump,输出所有的线程信息
同时将第4步得到的线程⼗进制编号2734转成16进制(AAE),在堆栈信息⾥⾯去找对应线程内容
在这里插入图片描述

13、在程序中如何判断是否有内存泄漏

内存泄漏的特点:
对象一直被引用,GC不能被回收,导致内存泄漏,一直内存泄露没有问题,多次内存泄露可能会引起内存溢出
我们可以通过Jstack 查看老年代是否被回收,比如第一次是200M,第二次是300M
Jstack 后台回收的时候执行的时候,看到FGC大于YGC回收;

14、JVM参数调优

Xmx 最大堆内存配置 -Xmx=2G
-Xms 最小堆内存配置 -Xms=2G
最大堆内存和最小堆内存要配置一样,不然会动态扩容 缩容

15、JVM运行区域分为几块,作用是什么

线程共享:
堆:new 对象和数组,栈上分配对象
方法区 :class对象、静态变量 常量池

线程私有:
程序计数器:某一个线程执行的行号位置
本地方法栈:调用外部方法 native 关键词修饰的 变量
虚拟机栈:每一个方法属于一个栈帧,而栈帧里面包括

栈帧
局部变量表
操作数栈
动态链接
返回值

16、GC算法有哪些,收集器有哪些

引用计数法
可达性分析
复制算法
分代算法
标记算法
标记整理算法
Serial 串联
parNew 多线程
Parallel Scavenge 并发变

cms 四个阶段
初始标记:
并发标记:
重新标记:
并发删除:

17、MiniGC 怎样扭转到MajorGC 里面

Age = 15
空间担保:新生代空间不够时
大对象直接分配到老年代

18、JVM中内加装机制

JVM 类加载机制分为五个部分:加载,验证,准备,解析,初始化,下面我们就分别来看一下这五个过程。
加载
加载是类加载过程中的一个阶段,这个阶段会在内存中生成一个代表这个类的 java.lang.Class 对象,作为方法区这个类的各种数据的入口。注意这里不一定非得要从一个 Class 文件获取,这里既可以从 ZIP 包中读取(比如从 jar 包和 war 包中读取),也可以在运行时计算生成(动态代理),也可以由其它文件生成(比如将 JSP 文件转换成对应的 Class 类)。

验证
这一阶段的主要目的是为了确保 Class 文件的字节流中包含的信息是否符合当前虚拟机的要求,并且不会危害虚拟机自身的安全。

准备
准备阶段是正式为类变量分配内存并设置类变量的初始值阶段,即在方法区中分配这些变量所使用的内存空间。注意这里所说的初始值概念,比如一个类变量定义为:

public static int v = 8080;

实际上变量 v 在准备阶段过后的初始值为 0 而不是 8080,将 v 赋值为 8080 的 put static 指令是程序被编译后,存放于类构造器方法之中。
但是注意如果声明为:
public static final int v = 8080;
在编译阶段会为 v 生成 ConstantValue 属性,在准备阶段虚拟机会根据 ConstantValue 属性将 v赋值为 8080。

解析
解析阶段是指虚拟机将常量池中的符号引用替换为直接引用的过程。符号引用就是 class 文件中的:
CONSTANT_Class_info
CONSTANT_Field_info
CONSTANT_Method_info
等类型的常量。

符号引用
符号引用与虚拟机实现的布局无关,引用的目标并不一定要已经加载到内存中。各种虚拟机实现的内存布局可以各不相同,但是它们能接受的符号引用必须是一致的,因为符号引用的字面量形式明确定义在 Java 虚拟机规范的 Class 文件格式中。

直接引用
直接引用可以是指向目标的指针,相对偏移量或是一个能间接定位到目标的句柄。如果有了直接引用,那引用的目标必定已经在内存中存在。

初始化
初始化阶段是类加载最后一个阶段,前面的类加载阶段之后,除了在加载阶段可以自定义类加载器以外,其它操作都由 JVM 主导。到了初始阶段,才开始真正执行类中定义的 Java 程序代码。
类构造器
初始化阶段是执行类构造器方法的过程。方法是由编译器自动收集类中的类变
量的赋值操作和静态语句块中的语句合并而成的。虚拟机会保证子方法执行之前,父类
的方法已经执行完毕,如果一个类中没有对静态变量赋值也没有静态语句块,那么编译
器可以不为这个类生成()方法。
注意以下几种情况不会执行类初始化:
通过子类引用父类的静态字段,只会触发父类的初始化,而不会触发子类的初始化。
定义对象数组,不会触发该类的初始化。
常量在编译期间会存入调用类的常量池中,本质上并没有直接引用定义常量的类,不会触发定义常量所在的类。
通过类名获取 Class 对象,不会触发类的初始化。
通过 Class.forName 加载指定类时,如果指定参数 initialize 为 false 时,也不会触发类初始化,其实这个参数是告诉虚拟机,是否要对类进行初始化。
通过 ClassLoader 默认的 loadClass 方法,也不会触发初始化动作。

类加载器
虚拟机设计团队把加载动作放到 JVM 外部实现,以便让应用程序决定如何获取所需的类,JVM 提供了 3 种类加载器:
启动类加载器(Bootstrap ClassLoader)
负责加载 JAVA_HOME\lib 目录中的,或通过-Xbootclasspath 参数指定路径中的,且被虚拟机认可(按文件名识别,如 rt.jar)的类。

扩展类加载器(Extension ClassLoader)
负责加载 JAVA_HOME\lib\ext 目录中的,或通过 java.ext.dirs 系统变量指定路径中的类库。

应用程序类加载器(Application ClassLoader):
负责加载用户路径(classpath)上的类库。
JVM 通过双亲委派模型进行类的加载,当然我们也可以通过继承 java.lang.ClassLoader 实现自定义的类加载器。

18、什么是双亲委派机制?它有什么作用?

双亲委派机制的意思是除了顶层的启动类加载器以外,其余的类加载器,在加载之前,都会委派给它的
⽗加载器进⾏加载。这样⼀层层向上传递,直到祖先们都⽆法胜任,它才会真正的加载。
通过带有优先级的层级关可以避免类的重复加载;
保证 Java 程序安全稳定运⾏,Java 核⼼ API 定义类型不会被随意替换。

在这里插入图片描述

19、设置堆空间的最大值(-Xmx)应该要考虑哪些因素?

需要根据系统的配置来确定,要给操作系统和JVM其他内存区域(栈、⽅法区)留下⼀定的剩余空间。
推荐配置系统或容器⾥可⽤内存的 70 %~80%最好。
假设物理内存是8G,设置多⼤堆内存⽐较合适?
系统有 8G 物理内存,系统⾃⼰可能会⽤掉⼀点,⼤概还有 7.5G 可以⽤。
那么建议配置-Xmx6g (7.5g*0.8=6g)

在这里插入图片描述

20、Java8默认使用的垃圾收集器是什么?

Java8版本的Hotspot JVM,默认情况下使用的是并行垃圾收集器(Parallel GC)。其他⼚商提供的JDK8基本上也默认使⽤并行垃圾收集器。
在这里插入图片描述

21、什么是并行垃圾收集?

并行垃圾收集,是指使⽤多个GC worker 线程并行地执行垃圾收集,能充分利用多核CPU的能力,缩短垃圾收集的暂停时间。
除了单线程的GC,其他的垃圾收集器,比如 PS,CMS, G1等新的垃圾收集器都使用了多个线程来并行执行GC⼯作

在这里插入图片描述

22、什么是STW?什么是安全点,什么是安全区域?

因为GC过程中,所有应⽤线程都需要暂停之后才能执⾏GC,这时候就称为STW,或者叫做GC暂停。
在这里插入图片描述
OopMap#
前文我们说到,JVM 采用的可达性分析法有个缺点,就是从 GC Roots 找引用链耗时。
都说他耗时,他究竟耗时在哪里?
GC 进行扫描时,需要查看每个位置存储的是不是引用类型,如果是,其所引用的对象就不能被回收;如果不是,那就是基本类型,这些肯定是不会引用对象的;这种对 GC 无用的基本类型的数据非常多,每次 GC 都要去扫描,显然是非常浪费时间的。
而且迄今为止,所有收集器在 GC Roots 枚举这一步骤都是必须暂停用户线程的。
那有没有办法减少耗时呢?
一个很自然的想法,能不能用空间换时间? 把栈上的引用类型的位置全部记录下来,这样到 GC 的时候就可以直接读取,而不用一个个扫描了。Hotspot 就是这么实现的,这个用于存储引用类型的数据结构叫 OopMap。
OopMap 这个词可以拆成两部分:Oop 和 Map,Oop 的全称是 Ordinary Object Pointer 普通对象指针,Map 大家都知道是映射表,组合起来就是 普通对象指针映射表。
在 OopMap 的协助下,HotSpot 就能快速准确地完成 GC Roots 枚举啦。

在这里插入图片描述

安全点#
OopMap 的更新,从直观上来说,需要在对象引用关系发生变化的时候修改。不过导致引用关系变化的指令非常多,如果对每条指令都记录 OopMap 的话 ,那将会需要大量的额外存储空间,空间成本就会变得无法忍受的高昂。选用一些特定的点来记录就能有效的缩小需要记录的数据量,这些特定的点就称为 安全点 (Safepoint)。
有了安全点,当 GC 回收需要停止用户线程的时候,将设置某个中断标志位,各个线程不断轮询这个标志位,发现需要挂起时,自己跑到最近的安全点,更新完 OopMap 才能挂起。这主动式中断的方式是绝大部分现代虚拟机选择的方案,另一种抢占式就不介绍了。
安全点不是任意的选择,既不能太少以至于让收集器等待时间过长,也不能过多以至于过分增大运行时的内存负荷。通常选择一些执行时间较长的指令作为安全点,如方法调用、循环跳转和异常跳转等。

23、CMS、G1垃圾回收器中的三色标记你了解吗?

三色标记法是⼀种垃圾回收法,它可以让 JVM 不发生或仅短时间发生 STW(Stop The World),从而达到清除 JVM 内存垃圾的目的。
三色标记法将对象的颜色分为了黑、灰、白三种颜⾊。
黑色:该对象已经被标记过了,且该对象下的属性也全部都被标记过了;
灰色:对象已经被垃圾收集器扫描过了,但是对象中还存在没有扫描的引用 ;
白色:表示对象没有被垃圾收集器访问过,即表示不可达;

在这里插入图片描述

三⾊标记的漏标问题
在这里插入图片描述

C被漏标了(不是垃圾的当做垃圾)
CMS的解决⽅案:Incremental Update(重新扫描)

在这里插入图片描述

G1的解决⽅案:SATB(snapshot-at-the-beginning)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/1451.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

带头双向循环链表

在前面我们学习了单链表,发现单链表还是有一些不够方便,比如我们要尾插,需要遍历一遍然后找到它的尾,这样时间复炸度就为O(N),现在我们引入双向带头链表就很方便了,我们先看看它的结构。通过观察,我们发现一…

Vue全新一代状态管理库 Pinia【一篇通】

文章目录前言1. Pinia 是什么?1.1 为什么取名叫 Pinia?1.2. 为什么要使用 Pinia ?2. 安装 Pinia2.1.创建 Store2.1.1. Option 类型 Store2.1.2 Setup 函数类型 Store2.1.3 模板中使用3. State 的使用事项(Option Store )3.1 读取 State3.2 …

EEPROM芯片(24c02)使用详解(I2C通信时序分析、操作源码分析、原理图分析)

1、前言 (1)本文主要是通过24c02芯片来讲解I2C接口的EEPROM操作方法,包含底层时序和读写的代码; (2)大部分代码是EEPROM芯片通用的,但是其中关于某些时间的要求,是和具体芯片相关的,和主控芯片和外设芯片都有关系&…

一天吃透TCP面试八股文

本文已经收录到Github仓库,该仓库包含计算机基础、Java基础、多线程、JVM、数据库、Redis、Spring、Mybatis、SpringMVC、SpringBoot、分布式、微服务、设计模式、架构、校招社招分享等核心知识点,欢迎star~ Github地址:https://github.com/…

vue模板语法

src目录文件说明: 1,数据绑定{{}} 数据绑定最常见的形式就是使用{{}}(双花括号)语法的文本插值 在template中使用{{}}文本插值语法中,设置一个变量,再在script中引入data函数,在return中进行数…

接口测试和性能测试有什么区别?我敢打赌你一定不知道

目录 一、什么是接口测试 二、接口测试原理 三、接口测试步骤 四、什么是性能测试 五、性能测试步骤 六、接口测试和性能测试的区别 一、什么是接口测试 接口测试是测试系统组件间接口的一种测试。接口测试主要用于检测外部系统与系统之间以及内部各个子系统之间的交互点…

2023最全Python+Selenium环境搭建教程-你绝对想不到有这么简单!

还有视频版本结合项目实战介绍,轻松学习! PythonSelenium自动化测试环境搭建Web自动化测试全套教程_哔哩哔哩_bilibiliPythonSelenium自动化测试环境搭建Web自动化测试全套教程共计180条视频,包括:1、Web自动化测试需求和挑战、2…

深度学习-Tensorflow使用Keras进行模型训练

本文以FasionMNIST/加州房价数据集为例,介绍KerasAPI进行分类问题/回归问题模型训练的方法Tensorflow版本Tensorflow和keara都需要2.0及以上版本import tensorflow as tf from tensorflow import keras print(tf.__version__) print(keras.__version__)分类MLP构建数…

AI_Papers周刊:第六期

CV - 计算机视觉 | ML - 机器学习 | RL - 强化学习 | NLP 自然语言处理 2023.03.13—2023.03.19 文摘词云 Top Papers Subjects: cs.CL 1.UPRISE: Universal Prompt Retrieval for Improving Zero-Shot Evaluation 标题:UPRISE:改进零样本评估…

要是早看到这篇文章,你起码少走3年弯路,20年老程序员的忠告

文章目录前言一、程序员的薪资是怎么样的?二、我现在的情况适合做程序员吗?三、大学期间到底应该学些什么?四、工作还是考研?五、总结前言 我是龙叔,一名工作了20多年的退休老程序员。 如果你在工作之前看到这篇文章…

【AI大比拼】文心一言 VS ChatGPT-4

摘要:本文将对比分析两款知名的 AI 对话引擎:文心一言和 OpenAI 的 ChatGPT,通过实际案例让大家对这两款对话引擎有更深入的了解,以便大家选择合适的 AI 对话引擎。 亲爱的 CSDN 朋友们,大家好!近年来&…

libcurl库访问人工智能平台之人脸识别

一、前言上一篇文章我们调用libcurl库去访问了百度,访问的是http协议的百度云主页。那么现在我们要基于翔云人工智能平台来实现人脸识别,具体的操作大概就是我们在linux下调用libcurl库去访问翔云人工智能平台,然后实现我们想要的两张人脸图片…

FPGA纯verilog实现RIFFA的PCIE通信,提供工程源码和软件驱动

目录1、前言2、RIFFA简介RIFFA概述RIFFA架构RIFFA驱动3、vivado工程详解4、上板调试验证并演示5、福利:工程代码的获取1、前言 PCIE是目前速率很高的外部板卡与CPU通信的方案之一,广泛应用于电脑主板与外部板卡的通讯,PCIE协议极其复杂&…

【Linux】基本指令介绍

前言从今天开始,我们一起来学习Linux的相关知识,今天先来介绍怎么登录Linux,并且介绍一些Linux的基本指令。使用 XShell 远程登录 Linux很多同学的 Linux 启动进入图形化的桌面. 这个东西大家以后就可以忘记了. 以后的工作中 没有机会 使用图…

蓝桥杯刷题冲刺 | 倒计时21天

作者:指针不指南吗 专栏:蓝桥杯倒计时冲刺 🐾马上就要蓝桥杯了,最后的这几天尤为重要,不可懈怠哦🐾 文章目录1.迷宫1.迷宫 题目 链接: 迷宫 - 蓝桥云课 (lanqiao.cn) 本题为填空题,只…

Three.js——learn02

Three.js——learn02Three.js——learn02通过轨道控制器查看物体OrbitControls核心代码index2.htmlindex.cssindex2.jsresult添加辅助器1.坐标轴辅助器AxesHelper核心代码完整代码2.箭头辅助器ArrowHelper核心代码完整代码3.相机视锥体辅助器CameraHelper核心代码完整代码Three…

近期投简历、找日常实习的一些碎碎念(大二---测试岗)

嘿嘿嘿,我又回来了,相信不少兄弟已经发现我似乎已经断更了好久,哈哈,我是尝试去找实习,投简历面试去了。 先说一下背景。 目录 背景 求职进行中 简历 投递和沟通 收获和感受 背景 博主,大二软件工程…

Arthas工具的基本使用

介绍 Arthas 是Alibaba开源的Java诊断工具,深受开发者喜爱。在线排查问题,无需重启;动态跟踪Java代码;实时监控JVM状态。Arthas支持JDK 6,支持Linux/Mac/Windows,采用命令行交互模式,同时提供丰…

Python截图自动化工具

1、展示部分源码(写的比较乱,哈哈) 2、功能展示 1)首页 2)按钮截图(用于自动翻页) 3)保存位置按钮(选择图片保存的位置) 4)重复次数,就是要截取多少次 5)定位截屏(截取的内容&#x…

[数据分析与可视化] Python绘制数据地图1-GeoPandas入门指北

本文主要介绍GeoPandas的基本使用方法,以绘制简单的地图。GeoPandas是一个Python开源项目,旨在提供丰富而简单的地理空间数据处理接口。GeoPandas扩展了Pandas的数据类型,并使用matplotlib进行绘图。GeoPandas官方仓库地址为:GeoP…