JVM--

文章详细介绍了Java内存模型的分区,包括堆、栈、方法区等,以及对象的分配。GC的两种判定方法是引用计数法和引用链法,三种收集算法分别是标记清除、标记整理和复制算法,分别适用于不同的场景。SafePoint是在代码执行中特定的位置,用于GC时线程同步。类加载过程包括加载、验证、准备、解析和初始化。文章还讨论了Java中的内存泄漏、垃圾回收器类型以及MinorGC和FullGC的触发条件。
摘要由CSDN通过智能技术生成

目录

内存模型以及分区,需要详细到每个区放什么

GC 的两种判定方法

SafePoint 是什么

GC 的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路?

GC 收集器有哪些?

CMS 收集器与 G1 收集器的特点

Minor GC 与 Full GC 分别在什么时候发生?

如和判断一个对象是否存活?(或者 GC 对象的判定方

法)

简述 java 垃圾回收机制?  

java内存模型 

简述类加载的几个过程

java 类加载过程

类加载器双亲委派模型机制


内存模型以及分区,需要详细到每个区放什么

JVM 分为堆区和栈区,还有方法区,初始化的对象放在堆里面,引用放在栈里面,
class 类信息常量池(static 常量和 static 变量)等放在方法区  
new:
  • 方法区:主要是存储类信息,常量池(static 常量和 static 变量),编译后的代码(字节码)等数据
  • 堆:初始化的对象,成员变量 (那种非 static 的变量),所有的对象实例和数组都要在堆上分配
  • 栈:栈的结构是栈帧组成的,调用一个方法就压入一帧,帧上面存储局部变量表,操作数栈,方法出口等信息,局部变量表存放的是 8 大基础类型加上一个应用类型,所以还是一个指向地址的指针
  • 本地方法栈:主要为 Native 方法服务
  • 程序计数器:记录当前线程执行的行号

Java 中会存在内存泄漏吗,请简单描述。 

所谓内存泄露就是指一个不再被程序使用的对象或变量一直被占 据在内存中。Java 中有垃圾回收机制,它可以保证一对象不再被 引用的时候,即对象变成了孤儿的时候,对象将自动被垃圾回收器从内存中清除掉。由于 Java 使用有向图的方式进行垃圾回收管理,可以消除引用循环的问题,例如有两个对象,相互引用,只要它们和根进程不可达的,那么 GC 也是可以回收它们的

垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?

有什么办法主动通知虚拟机进行垃圾回收?

对于 GC 来说,当程序员创建对象时,GC 就开始监控这个对象的地址、大小以及使用情况。通常,GC 采用有向图的方式记录和管理堆(heap)中的所有对象。通过这种方式确定哪些对象是”可达的”,哪些对象是”不可达的”。当 GC 确定一些对象为“不可达”时,GC 就有责任回收这些内存空间。

可以。程序员可以手动执行 System.gc(),通知 GC 运行,但是 Java 语言规范并不 保证 GC 一定会执行。

System.gc() 和 Runtime.gc() 会做什么事情?

这两个方法用来提示 JVM 要进行垃圾回收。但是,立即开始还是延迟进行垃圾回收是取决于 JVM 的。

如果对象的引用被置为 null,垃圾收集器是否会立即释放对象占

用的内存?

不会,在下一个垃圾回收周期中,这个对象将是可被回收的。

在 Java 中,对象什么时候可以被垃圾回收?

当对象对当前使用这个对象的应用程序变得不可触及的时候,这个对象就可以被回收了。

GC 的两种判定方法

引用计数法:指的是如果某个地方引用了这个对象就+1,如果失效了就-1,当为 0 就
会回收但是 JVM 没有用这种方式,因为无法判定相互循环引用(A 引用 B,B 引用 A)
的情况
引用链法: 通过一种 GC ROOT 的对象(方法区中静态变量引用的对象等-static 变
量)来判断,如果有一条链能够到达 GC ROOT 就说明,不能到达 GC ROOT 就说明
可以回收

SafePoint 是什么

  1. 循环的末尾 (防止大循环的时候一直不进入 safepoint,而其他线程在等待它进入
  2. safepoint)
  3. 方法返回前
  4. 调用方法的 call 之后
  5. 抛出异常的位置
比如 GC 的时候必须要等到 Java 线程都进入到 safepoint 的时候 VMThread 才能开始
执行 GC

GC 的三种收集方法:标记清除、标记整理、复制算法的原理与特点,分别用在什么地方,如果让你优化收集方法,有什么思路?

标记清除:
原理:分为标记和清除两个阶段:首先标记出所有的需要回收的对象,在标记完成以后统一回收所有被标记的对象。

特点:

  • 效率问题,标记和清除的效率都不高;
  • 空间的问题,标记清除以后会产生大量不连续的空间碎片,空间碎片太多可能会导致程序运行过程需要分配较大的对象时候,无法找到足够连续内存而不得不提前触发一次垃圾收集。

适用场景 :适合在老年代进行垃圾回收,比如CMS收集器就是采用该算法进行回收的。

复制算法

原理:它先将可用的内存按容量划分为大小相同的两块,每次只是用其中的一块。当这块内存用完了,就将还存活着的对象复制到另一块上面,然后把已经使用过的内存空间一次清理掉。

特点:没有内存碎片,只要移动堆顶指针,按顺序分配内存即可。代价是将内存缩小位原来的一半。

地方:适合新生代区进行垃圾回收。serial new,parallel new和parallel scanvage收集器,就是采用该算法进行回收的。

标记整理

原理:分为标记和整理两个阶段:首先标记出所有需要回收的对象,让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。

特点:不会产生空间碎片,但是整理会花一定的时间。

地方:适合老年代进行垃圾收集,parallel Old(针对parallel scanvange gc的) gc和Serial old收集器就是采用该算法进行回收的。

优化收集方法的思路
分代收集算法
原理:根据对象存活的周期的不同将内存划分为几块,然后再选择合适的收集算法。
一般是把java堆分成新生代和老年代,这样就可以根据各个年待的特点采用最适合的收集算法。在新生代中,每次垃圾收集都会有大量的对象死去,只有少量存活,所以选用复制算法。老年代因为对象存活率高,没有额外空间对他进行分配担保,所以一般采用标记整理或者标记清除算法进行回收。

GC 收集器有哪些?

  • 并行收集器:串行收集器使用一个单独的线程进行收集,GC 时服务有停顿时间
  • 串行收集器:次要回收中使用多线程来执行

CMS 收集器与 G1 收集器的特点

  • CMS 收集器是基于“标记—清除”算法实现的,经过多次标记才会被清除
  • G1 从整体来看是基于“标记—整理算法实现的收集器,从局部(两个 Region 之间)上来看是基于“复制算法实现的

Minor GC 与 Full GC 分别在什么时候发生?

Minor GC: 新生代内存不够用时候发生 MGC(内存空间耗尽)
Full GC: JVM 内存不够的时候发生 FGC(空间不足)

如和判断一个对象是否存活?(或者 GC 对象的判定方

法)

 引用计数法

所谓引用计数法就是给每一个对象设置一个引用计数器,每当有一个地方引用这个对象
时,就将计数器加一,引用失效时,计数器就减一。当一个对象的引用计数器为零时,说
明此对象没有被引用,也就是“死对象”,将会被垃圾回收.
引用计数法有一个缺陷就是无法解决循环引用问题,也就是说当对象 A 引用对象 B,对象
B 又引用者对象 A,那么此时 A,B 对象的引用计数器都不为零,也就造成无法完成垃圾回
收,所以主流的虚拟机都没有采用这种算法。

 可达性算法(引用链法)

该算法的思想是:从一个被称为 GC Roots 的对象开始向下搜索,如果一个对象到 GC
Roots 没有任何引用链相连时,则说明此对象不可用。
在 java 中可以作为 GC Roots 的对象有以下几种:
  • 虚拟机栈中引用的对象
  • 方法区类静态属性引用的对象
  • 方法区常量池引用的对象
  • 本地方法栈 JNI 引用的对象
虽然这些算法可以判定一个对象是否能被回收,但是当满足上述条件时,一个对象比 不一
定会被回收。当一个对象不可达 GC Root 时,这个对象并
不会立马被回收,而是出于一个死缓的阶段,若要被真正的回收需要经历两次标记如果对象在可达性分析中没有与 GC Root 的引用链,那么此时就会被第一次标记并且进行一次筛选,筛选的条件是是否有必要执行 finalize()方法。当对象没有覆盖 finalize()方法或者已被虚拟机调用过,那么就认为是没必要的。如果该对象有必要执行 finalize()方法,那么这个对象将会放在一个称为 F-Queue 的对队列中,虚拟机会触发一个 Finalize()线程去执行,此线程是低优先级的,并且虚拟机不会承诺一直等待它运行完,这是因为如果 finalize()执行缓慢或者发生了死锁,那么就会造成 FQueue 队列一直等待,造成了内存回收系统的崩溃。GC 对处于 F-Queue 中的对象进行第二次被标记,这时,该对象将被移除”即将回收”集合,等待回收。

简述 java 垃圾回收机制?  

在 java 中,程序员是不需要显示的去释放一个对象的内存的,而是由虚拟机自行执行。在
JVM 中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚
拟机空闲或者当前堆内存不足时,才会触发执行,扫面那些没有被任何引用的对象,并将
它们添加到要回收的集合中,进行回收。

java内存模型 

简述类加载的几个过程

加载、验证、准备、解析、初始化、使用、卸载
通过全限定名来加载生成 class 对象到内存中,然后进行验证这个 class 文件,包括文
件格式校验、元数据验证,字节码校验等。准备是对这个对象分配内存。解析是将符
号引用转化为直接引用(指针引用),初始化就是开始执行构造器的代码

java 类加载过程

加载
加载时类加载的第一个过程,在这个阶段,将完成一下三件事情:
1. 通过一个类的全限定名获取该类的二进制流。
2. 将该二进制流中的静态存储结构转化为方法去运行时数据结构。
3. 在内存中生成该类的 Class 对象,作为该类的数据访问入口。
验证
验证的目的是为了确保 Class 文件的字节流中的信息不回危害到虚拟机.在该阶段主要完成
以下四钟验证:
1. 文件格式验证:验证字节流是否符合 Class 文件的规范,如主次版本号是否在当前虚拟
机范围内,常量池中的常量是否有不被支持的类型.
2. 元数据验证:对字节码描述的信息进行语义分析,如这个类是否有父类,是否集成了不
被继承的类等。
3. 字节码验证:是整个验证过程中最复杂的一个阶段,通过验证数据流和控制流的分析,
确定程序语义是否正确,主要针对方法体的验证。如:方法中的类型转换是否正确,跳转
指令是否正确等。
4. 符号引用验证:这个动作在后面的解析过程中发生,主要是为了确保解析动作能正确执行。
准备
准备阶段是为类的静态变量分配内存并将其初始化为默认值,这些内存都将在方法区中进
行分配。准备阶段不分配类中的实例变量的内存,实例变量将会在对象实例化时随着对象
一起分配在 Java 堆中。
解析
该阶段主要完成符号引用到直接引用的转换动作。解析动作并不一定在初始化动作完成之
前,也有可能在初始化之后。
初始化
初始化时类加载的最后一步,前面的类加载过程,除了在加载阶段用户应用程序可以通过
自定义类加载器参与之外,其余动作完全由虚拟机主导和控制。到了初始化阶段,才真正
开始执行类中定义的 Java 程序代码。

类加载器双亲委派模型机制

当一个类收到了类加载请求时,不会自己先去加载这个类,而是将其委派给父类,由父类
去加载,如果此时父类不能加载,反馈给子类,由子类去完成类的加载。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值