自学内容网 自学内容网

Java面试题、八股文学习之JVM篇

1、知识点汇总

JVM是Java运行基础,面试时一定会遇到JVM的有关问题,内容相对集中,但对只是深度要求较高。

在这里插入图片描述

重点包括内存模型、类加载机制和垃圾回收(GC)。性能调优侧重应用实践,编译器优化与执行模式侧重理论基础。需掌握内存模型的各部分功能和数据保存;类加载的双亲委派机制及各类加载器的使用;GC的分代回收思想、算法与适用场景;性能调优的JVM参数及工具的应用;执行模式中的解释、编译、混合模式优缺点,以及JIT即时编译、OSR栈替换、C1/C2编译器优化等。新技术包括Java 10的Graal编译器,javac编译过程优化及AST抽象语法树。

2、知识点详解:

1、JVM内存模型:

线程独占:栈,本地方法栈,程序计数器 线程共享:堆,方法区

2、栈:

又称方法栈,线程私有的,线程执行方法是都会创建一个栈阵,用来存储局部变量表,操作栈,动态链接,方 法出口等信息.调用方法时执行入栈,方法返回式执行出栈.

3、本地方法栈

与栈类似,也是用来保存执行方法的信息.执行Java方法是使用栈,执行Native方法时使用本地方法栈.

4、程序计数器

保存着当前线程执行的字节码位置,每个线程工作时都有独立的计数器,只为执行Java方法服务,执行 Native方法时,程序计数器为空.

5、堆

JVM内存管理最大的一块,对被线程共享, 目的是存放对象的实例,几乎所欲的对象实例都会放在这里, 当堆没有可用空间时,会抛出OOM异常.根据对象的存活周期不同,JVM把对象进行分代管理,由垃圾回 收器进行垃圾的回收管理

6、方法区:

又称非堆区,用于存储已被虚拟机加载的类信息,常量,静态变量,即时编译器优化后的代码等数据.1.7 的永久代和1.8的元空间都是方法区的一种实现

7、JVM 内存可见性

在这里插入图片描述

JMM是定义程序中变量的访问规则,线程对于变量的操作只能在自己的工作内存中进行,而不能直接对主内存操作.由于指令重排序,读写的顺序会被打乱。因此JMM需要提供原子性,可见性,有序性保证.

在这里插入图片描述

3、说说类加载与卸载

加载过程
在这里插入图片描述

其中验证,准备,解析合称 链接

  • 加载通过类的完全限定名,查找此类字节码文件,利用字节码文件创建Class对象。
  • 验证确保Class文件符合当前虚拟机的要求,不会危害到虚拟机自身安全。
  • 准备进行内存分配,为static修饰的类变量分配内存,并设置初始值(0或null).不包含final修饰的静态变 量,因为final变量在编译时分配.
  • 解析将常量池中的符号引用替换为直接引用的过程.直接引用为直接指向目标的指针或者相对偏移量等。
  • 初始化主要完成静态块执行以及静态变量的赋值.先初始化父类,再初始化当前类.只有对类主动使用 时才会初始化。
  • 触发条件包括,创建类的实例时,访问类的静态方法或静态变量的时候,使用Class.forName反射类的时候,或者某个子类初始化的时候。
  • Java自带的加载器加载的类,在虚拟机的生命周期中是不会被卸载的,只有用户自定义的加载器加载的类才可以被卸。

1、加载机制-双亲委派模式

在这里插入图片描述

双亲委派模式,即加载器加载类时先把请求委托给自己的父类加载器执行,直到顶层的启动类加载器. 父类加载器能够完成加载则成功返回,不能则子类加载器才自己尝试加载。

优点:

  1. 避免类的重复加载
  2. 避免Java的核心API被篡改

2、分代回收
分代回收基于两个事实:大部分对象很快就不使用了,还有一部分不会立即无用,但也不会持续很长时间。
在这里插入图片描述

  • 年轻代->标记-复制
  • 老年代->标记-清除

3、回收算法

a、 G1算法
1.9后默认的垃圾回收算法,特点保持高回收率的同时减少停顿.采用每次只清理一部分,而不是清理全 部的增量式清理,以保证停顿时间不会过长。

其取消了年轻代与老年代的物理划分,但仍属于分代收集器,算法将堆分为若干个逻辑区域(region),一 部分用作年轻代,一部分用作老年代,还有用来存储巨型对象的分区。

同CMS相同,会遍历所有对象,标记引用情况,清除对象后会对区域进行复制移动,以整合碎片空间。

年轻代回收: 并行复制采用复制算法,并行收集,会StopTheWorld。

老年代回收: 会对年轻代一并回收。

初始标记完成堆root对象的标记,会StopTheWorld.并发标记 GC线程和应用线程并发执行. 最终标记 完成三色标记周期,会StopTheWorld.复制/清楚会优先对可回收空间加大的区域进行回收。

b、ZGC算法
前面提供的高效垃圾回收算法,针对大堆内存设计,可以处理TB级别的堆,可以做到10ms以下的回收停顿时间。

在这里插入图片描述

  • 着色指针
  • 读屏障
  • 并发处理
  • 基于region
  • 内存压缩(整理)

roots标记:标记root对象,会StopTheWorld。
并发标记:利用读屏障与应用线程一起运行标记,可能 会发生StopTheWorld.清除会清理标记为不可用的对象。
roots重定位是对存活的对象进行移动,以腾出大块内存空间,减少碎片产生。重定位最开始会StopTheWorld,却决于重定位集与对象总活动集的比例。 并发重定位与并发标记类似。

4.简述一下JVM的内存模型

JVM(Java虚拟机)的内存模型定义了Java程序在运行时,JVM如何管理和使用内存。它包括程序运行时所需的各个内存区域,并规定了这些区域如何分配、使用和回收。JVM内存模型的设计非常关键,因为它直接影响程序的性能、稳定性及并发执行的行为。

JVM内存模型的主要组成部分:

1.方法区(Method Area)

功能:方法区用于存储类的相关信息(如类的结构、字段、方法、常量池、静态变量等),是所有线程共享的内存区域。

特点

  • 存储类信息、常量池、静态变量和即时编译(JIT)编译后的代码。
  • 由于类的加载、卸载和回收,方法区可能会经历频繁的垃圾回收。
  • 在早期的JVM中,方法区和永久代(PermGen)是同一块内存区域,但在Java 8及以后,永久代被**元空间(Metaspace)**替代,元空间不再在堆内存中,而是存储在本地内存中。

2.堆(Heap)

功能:堆是JVM中最大的内存区域,用于存储所有的对象实例。它是垃圾回收器(GC)管理的主要区域,所有的对象实例和数组都在堆中创建。

特点

  • 堆是所有线程共享的内存区域。
  • 通过垃圾回收器来管理内存,避免内存泄漏。
  • 堆通常分为年轻代(Young Generation)和老年代(Old Generation),其中年轻代存放新创建的对象,而老年代用于存放生命周期较长的对象。

3.栈(Stack)

功能:每个线程都有自己的栈,用于存储局部变量、方法调用的栈帧、返回地址等。栈内存也用于方法的调用和返回。

特点

  • 每个线程有独立的栈。
  • 局部变量、方法调用、返回地址等信息都保存在栈中。
  • 栈是基于先进后出(LIFO)方式存储的,因此每次方法调用时都会创建一个新的栈帧,方法执行完后,栈帧就会被销毁。

4.程序计数器(Program Counter Register)

功能:程序计数器是一个较小的内存区域,用于记录当前线程所执行的字节码的行号指示器。它能够跟踪正在执行的代码位置,以便程序能够顺利地进行线程切换。

特点

  • 每个线程都有一个独立的程序计数器。
  • 线程上下文切换时,程序计数器保存当前线程的执行位置。

5.本地方法栈(Native Method Stack)

功能:本地方法栈是用于支持JVM与本地(非Java)代码交互的栈。它与JVM的栈类似,但用于执行本地方法(如C、C++等语言编写的代码)。

特点

本地方法栈主要用于执行本地方法,调用本地代码时会创建本地方法的栈帧。

6.直接内存(Direct Memory)

功能:直接内存并非JVM内存的一部分,但它是通过nio(New Input/Output)类库对本地内存的直接访问。这允许JVM绕过堆内存,通过直接与操作系统内存交互来提高性能。

特点

通过DirectByteBuffer直接访问本地内存,可以减少内存复制,提高I/O性能。

JVM内存模型的内存区域划分

  • 堆内存:存储对象实例和数组,是垃圾回收的主要区域。堆被划分为年轻代(Young Generation)和老年代(Old Generation):

  • 年轻代:存储大部分新创建的对象,垃圾回收较频繁。年轻代又分为三个区域:

    • Eden区:新创建的对象通常会被分配到这里。
    • Survivor区:存放经过一次或多次垃圾回收的对象。
  • 老年代:存储生命周期较长的对象,垃圾回收相对较少。长期存活的对象会被转移到老年代。

  • 方法区:存储类的元数据(如类的结构、方法、字段、常量等),它是所有线程共享的区域。

  • 栈内存:每个线程都有自己的栈空间,用于存放局部变量和方法的调用。

  • 程序计数器:每个线程都有一个程序计数器,用于记录程序当前的执行位置。

  • 本地方法栈:与栈类似,但用于执行本地方法。

JVM内存模型与并发

JVM的内存模型在多线程环境中至关重要,尤其是关于内存可见性和有序性的问题。Java的内存模型(JMM)规定了多线程并发执行时,如何保证各个线程之间对共享变量的访问是一致的。它主要涉及以下几个方面:

  • 可见性:一个线程对共享变量的修改,其他线程能够及时看到。
  • 原子性:操作的不可分割性,保证某个操作要么完全执行,要么完全不执行。
  • 有序性:程序指令的执行顺序,不会随意重排。

通过 synchronized 关键字和 volatile 关键字,Java提供了对并发访问的控制,确保了线程安全。

总结:

JVM内存模型包括了多个重要的内存区域,每个区域负责特定的任务。堆用于存储对象,栈用于存储局部变量和方法信息,方法区存储类信息,程序计数器帮助管理线程执行,直接内存则提供了与操作系统内存的直接交互。通过合理管理这些内存区域,JVM能够提供高效的内存管理和优化,支持多线程和并发执行。

5.说说堆和栈的区别

堆(Heap)和栈(Stack)是计算机内存管理中的两个重要区域,它们在用途、分配方式、生命周期等方面有许多区别。以下是堆和栈的主要区别:

1. 内存分配方式

栈:

  • 栈内存由操作系统自动管理,分配和回收的速度非常快。栈内存采用先进后出(LIFO)原则进行分配和回收。
  • 每当一个方法被调用时,系统会为该方法分配一个栈帧,存储方法的局部变量、参数和返回地址。当方法调用结束时,栈帧会被销毁,内存空间被释放。
    堆:
  • 堆内存由JVM或操作系统管理,分配和回收相对较慢。堆内存是动态分配的,可以在程序运行时灵活地分配空间。
  • 堆内存用于存储对象实例和数组。对象在堆中分配内存,而这些对象的生命周期由垃圾回收器管理。

2. 内存空间的大小

栈:

  • 栈的大小通常较小,受到操作系统或JVM的限制。每个线程都有自己的栈空间,因此栈的内存大小通常是有限的。
  • 栈的空间比较紧张,适合存储局部变量和函数调用等小规模的数据。

堆:

  • 堆的空间通常比较大,且由JVM动态管理,可以根据需要进行扩展。堆的大小可以通过JVM启动参数来配置。
  • 堆内存主要用于存储程序中创建的对象和数组,适合存储较大的数据结构。

3. 存储内容

栈:

  • 存储局部变量、方法调用信息(如返回地址、函数参数等)以及每个方法的栈帧。
  • 每个线程都有一个独立的栈,栈内存只存储当前线程的相关数据。

堆:

  • 存储对象实例和数组。这些对象由JVM的垃圾回收器进行管理。
  • 堆内存中的对象可以被多个线程共享访问,因此需要注意线程安全。

4. 生命周期

栈:

栈的生命周期由方法调用决定。当一个方法被调用时,栈为该方法分配栈帧,并在方法调用结束时释放栈帧。因此栈中的数据(如局部变量和方法调用信息)具有自动管理的生命周期

堆:

堆中的对象生命周期由垃圾回收器(GC)管理。当一个对象不再被引用时,垃圾回收器会回收该对象占用的堆内存空间。堆内存的管理更加灵活,但也更复杂。

5. 访问速度

栈:

栈的访问速度非常快,因为栈的内存分配和回收遵循严格的顺序(LIFO),每次分配和回收都是在栈的顶端进行。栈是连续的内存空间,操作系统为其分配的内存通常是高效的。

堆:

堆的访问速度相对较慢,因为堆内存的分配和回收是动态的。堆内存可能会因为频繁的分配和垃圾回收而产生碎片化,影响性能。

6. 线程共享

栈:

每个线程都有自己的栈空间,栈内存是线程私有的,其他线程不能访问当前线程的栈。

堆:

堆内存是所有线程共享的,多个线程可以同时访问堆中的对象。因此,在多线程环境下,堆中的数据需要特别小心,避免数据竞争和同步问题。

7. 垃圾回收

栈:

栈中的内存是自动回收的,每次方法结束时,栈帧会被销毁,栈内存也会被释放。

堆中的内存则由垃圾回收器(GC)负责回收。垃圾回收器会定期扫描堆内存,找出不再被引用的对象,并释放它们占用的内存。

8. 适用场景

栈:

栈适用于存储局部变量和方法调用信息,它非常适合用于函数调用、递归等操作。

堆:

堆适用于存储对象、数组等动态数据结构。它适合用于存储生命周期较长的对象,比如在Java中通过new关键字创建的对象都会被分配到堆上。

特性堆(Heap)栈(Stack)
分配方式动态分配,通过JVM管理静态分配,由操作系统自动管理
存储内容对象实例、数组局部变量、方法调用信息
生命周期由垃圾回收器管理,直到没有引用为止随着方法调用结束自动销毁
线程共享所有线程共享每个线程有独立的栈
访问速度较慢,因涉及动态分配和垃圾回收快,栈内存是连续的、按顺序分配的
内存大小较大,可以根据需要调整较小,受操作系统限制
管理方式由垃圾回收器管理由操作系统自动管理

总的来说,栈和堆各自有不同的特点和适用场景。栈适合存储局部变量和执行上下文,速度快且自动回收;堆适合存储对象和数组,适用于动态数据分配,但需要垃圾回收器管理内存,速度较慢。


原文地址:https://blog.csdn.net/guihong004/article/details/143927158

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!