JVM中的垃圾回收器

相关概念:

  • 并行收集:多个垃圾回收线程同时执行,此时用户线程处于等待状态
  • 并发收集:用户线程和垃圾回收线程同时工作

JVM中一共有七种垃圾回收器,这里主要简单概述两种

  • G1收集器:Java堆并行收集器

    • 它是jdk1.7提供的新收集器,它是基于标记压缩算法实现的,因此GC时不会产生内存碎片
    • 它的另一个特点就是,它的作用范围是整个Java堆,不同于其他六种收集器,其他六种收集器的作用范围都仅限于堆中新生代或老年代。
  • CMS收集器:老年代并行收集器

    • 它是基于标记清除算法实现的,因此GC时会产生内存碎片
    • 它的特点是,高并发、低停顿。是以获取最短垃圾回收停段时间为目标的收集器。

类的加载时机

  • 创建类的实例
  • 调用类的静态变量,或者为类的静态变量赋值
  • 调用类的静态方法
  • 使用反射方式来创建类对应的Class对象
  • 初始化某个类的子类
  • 直接使用java.exe命令来运行某个主类

类的加载过程

  1. 加载:将class字节码文件加载到JVM内存中,并创建这个类对应的Class对象
  2. 验证:校验这个class文件是否符合规范,确保不会危害虚拟机自身的安全
  3. 准备:为这个类中的静态变量分配内存并初始化赋值
  4. 解析:将常量池中的符号引用变为直接引用
  5. 初始化:执行这个类的初始化操作,例如执行java初始化代码,静态代码块、为栈内存开辟空间等

扩展

1、Java中存在内存泄漏吗?

Java中肯定是存在内存泄漏的。虽然Java中存在GC垃圾回收机制,能够及时回收不在被使用的对象。但是依然存在内存泄漏问题。
Java导致内存泄漏的原因很明确:长生命周期的对象持有短生命周期对象的引用就可能会导致内存泄漏问题。尽管这个短生命周期对象不在被需要,但是由于长生命周期的对象持有它的引用,导致它无法被GC垃圾回收。这就是Java中内存泄漏的发生场景。

2、HotSpot的堆中为什么要分为新生代和老年代?

HotSpot的堆中根据对象生命周期的不同分为新生代和老年代,这样就可以根据各个年代的特点采用最适当的收集算法

  • 在新生代中,因为大部分对象的生命周期都很短,只有少量的对象存活,这时候垃圾回收器使用复制算法是最优的。只需要付出少量的复制成本就可以完成收集。
  • 在老年代中,存活的对象比较多,没有额外的空间对它进行分配了,于是采用标记清除或者标记压缩算法来进行回收。

因此,从这里也可以看出JVM是采用分代收集算法来进行垃圾回收的

3、JVM中栈内存溢出的情况有哪些?

  1. 虚拟机栈中,栈帧过多,也就是方法的无限递归调用,导致栈内存溢出,这种情况比较常见
  2. 每个栈帧占用的内存过大,它们的栈帧内存直接超过了栈的最大内存,导致栈内存溢出。这种情况很少见

4、HotSpot 中GC的触发条件

  • Young GC(轻GC):当伊甸园区的内存空间不够的时候,就会触发轻GC
  • Full GC(重GC、全局GC)

    • 当要触发一次Young GC时,统计发现之前的Young GC的平均晋升值大于老年代剩余的空间时,也就是发现老年代内存空间不够了,这时就不会进行Young GC,而会触发Full GC。(通常情况)
    • 永久代(元空间)中的没有足够的内存空间了,这时就会触发Full GC
    • System.gc() 默认也是触发的Full GC

补充Jvm如何确定一个类的(判断类相同)
在Java中,是通过全类名(包名+类名)来确定一个类的。在JVM中,一个类是用全类名+类加载器来作为唯一标识的。不同的类加载器加载的类置于不同的命名空间中,这叫做类加载器隔离。

最后修改:2021 年 07 月 20 日 01 : 48 PM
如果觉得我的文章对你有用,请随意赞赏