首页 > 编程语言 >Java面试题———JVM篇

Java面试题———JVM篇

时间:2024-08-18 14:54:09浏览次数:11  
标签:面试题 Java 对象 回收 算法 GC JVM 加载

目录

1、JVM的主要组成部分有哪些

2、堆栈的区别是什么

3、JVM的类加载器有哪些

4、什么是双亲委派模型

5、说一下类加载器的执行过程

6、怎么判断对象是否可以被回收

7、JVM的垃圾回收算法有哪些

8、JVM的垃圾回收器都有哪些


1、JVM的主要组成部分有哪些

JVM主要分为下面几部分

  • 类加载器:负责将字节码文件加载到内存中

  • 运行时数据区:用于保存java程序运行过程中需要用到的数据和相关信息

  • 执行引擎:字节码文件并不能直接交给底层操作系统去执行,因此需要特定的命令解析器执行引擎将字节码翻译成底层系统指令

  • 本地库接口:会被执行引擎调用参与字节码的翻译

在这里面最主要的部分是运行时数据区,它又由五部分构成,分别是:堆、方法区、栈、本地方法栈、程序计数器

  • 堆是对象实例存储的主要区域

  • 方法区可以认为是堆的一部分,用于存储已被虚拟机加载的信息,比如常量、静态变量等等

  • 栈是程序方法运行的主要区域,栈里面存的是栈帧,栈帧里面存的是局部变量表、操作数栈、动态链接、方法出口等信息

  • 本地方法栈与栈功能相同,区别在于本地方法栈执行的是本地方法,即一个Java调用非Java代码的接口

  • 程序计数器主要存放的是当前线程所执行的字节码的行号,用于记录正在执行的字节码指令的地址

2、堆栈的区别是什么

堆和栈都是JVM的主要组成部分,不同点在于:

  • 栈内存一般会用来存储局部变量和方法调用,但堆内存是用来存储Java对象和数组的

  • 堆会GC垃圾回收,而栈不会

  • 栈内存是线程私有的,而堆内存是线程共有的

  • 两者异常错误不同,栈空间不足:java.lang.StackOverFlowError,堆空间不足:java.lang.OutOfMemoryError

3、JVM的类加载器有哪些

类加载器的主要作用就是将字节码文件加载到JVM中,从而让Java程序能够启动起来。根据各自加载范围的不同,主要划分为四种类加载器:

  • 启动类加载器(BootStrap ClassLoader):用于加载JAVA_HOME/jre/lib目录下的类库

  • 扩展类加载器(ExtClassLoader):用于加载JAVA_HOME/jre/lib/ext目录中的类库

  • 应用类加载器(AppClassLoader):用于加载classPath下的类,也就是加载开发者自己编写的Java类

  • 自定义类加载器:开发者自定义类继承ClassLoader,实现自定义类加载规则

4、什么是双亲委派模型

1.双亲委派模型是Java中的一种类加载机制。

在双亲委派模型中,类加载器之间形成了一种层次继承关系,从顶端开始依次是:启动类加载器->扩展类加载器->应用类加载器->自定义类加载器

当一个类加载器需要加载某个类时,它首先会委派给其上层类加载器去尝试加载该类。如果父类加载器无法加载该类,子类加载器才会尝试加载。

这种层次关系形成了一个从上到下的委派链。

2.双亲委派模型的主要目的是保证Java类的安全性和避免类的重复加载。当一个类加载器收到加载请求时,它会首先检查自己是否已经加载了该类。

如果已经加载,则直接返回该类的Class对象;如果未加载,则将加载请求委派给父类加载器。

父类加载器也会按照同样的方式进行检查,直到顶层的启动类加载器。如果顶层的启动类加载器无法加载该类,那么子类加载器会尝试自己加载。

这样可以避免同一个类被不同的类加载器加载多次,确保类的唯一性。

3.双亲委派模型的优势在于能够保证类的一致性和安全性。

通过委派链的机制,可以避免恶意代码通过自定义的类加载器加载替换系统核心类,从而提高了Java程序的安全性。

此外,通过双亲委派模型,可以实现类的共享和重用,减少内存占用和加载时间,提高了系统的性能。

5、说一下类加载器的执行过程

类从被加载到虚拟机内存中开始,直到卸载出内存为止,整个生命周期包括了7个阶段:加载、验证、准备、解析、初始化、使用、卸载

  1. 加载: 这个阶段会在内存中生成一个代表这个类的java.lang.Class对象

  2. 验证: 这个阶段的主要目的是为了确保Class文件包含的信息符合当前虚拟机的要求,并且不会危害虚拟机自身的安全

  3. 准备: 这个阶段正式为类变量分配内存并设置类变量的初始值,注意这里的初始值指的是默认值,而不是代码=后的实际值

  4. 解析: 这个阶段将符号引用替换为直接引用,比如方法中调用了其他方法,方法名可以理解为符号引用,而直接引用就是使用指针直接引用方法

  5. 初始化: 这个阶段是执行类构造器方法的过程,是类加载的最后一步,到了这一步Java虚拟机才开始真正执行类中定义的Java程序代码(字节码)

  6. 使用: 这个节点程序在运行

  7. 卸载: 这个阶段类Class对象被GC

6、怎么判断对象是否可以被回收

在堆中存放着几乎所有的对象实例,垃圾收集器在对堆进行回收前,第一件事就是要确定哪些对象是要回收的

JVM认为不被引用的对象就是可以被回收的对象,而它确认对象是否还在被引用的算法主要有两种:引用计数法和可达性分析算法

  1. 引用计数法

    在对象头处维护一个counter,每增加一次对该对象的引用,计数器自加,如果对该对象的引用失联,则计数器自减

    当counter为0时,表明该对象已经被废弃,不处于存活状态,

    但是此方法存在问题,假设两个对象相互引用始终无法释放counter,则永远不能GC

  2. 可达性分析算法

        通过一系列为GC Roots的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链

        当一个对象到GC Roots没有任何引用链相连时,则证明该对象是不可用的

        可以作为GC Roots的对象一般有栈中引用的对象 、方法区中类静态属性引用的对象以及

7、JVM的垃圾回收算法有哪些

目前JVM中的垃圾回收算法主要有四个,分别是:标记清除算法、标记-整理算法、复制算法和分代收集算法

  1. 标记清除算法是将垃圾回收分为2个阶段,分别是标记和清除

    它会先使用根据可达性分析算法找到垃圾资源进行标记,然后对这些标记为可回收的内容进行垃圾回收

    这种算法的主要不足有两个:

    • 效率问题,标记和清除阶段都要遍历多有对象,并且在GC时,需要停止应用程序,对于交互性要求比较高的应用而言这个体验是非常差的

    • 空间问题,对象被回收之后会产生大量不连续的内存碎片,当需要分配较大对象时,由于找不到合适的空闲内存而不得不再次触发垃圾回收动作

  2. 标记整理算法也是将垃圾回收分为2个阶段,分别是标记和整理清除

    它的第一阶段也是会先将存活的对象先标记出来

    不一样的地方在于第二阶段,它会将所有存活的对象向前移动放在一起,然后将无用空间回收,这样就会出现连续的可用空间了

    所以它解决了空间碎片问题,但是效率低的问题依旧存在

  3. 复制算法,将原有的内存空间一分为二,每次只用其中的一半

    在垃圾回收时,将正在使用的对象复制到另一个内存空间中,然后将当前内存空间清空,交换两个内存的角色,完成垃圾的回收。

    这种算法的缺点在于分配2块内存空间,在同一个时刻,只能使用一半,内存使用率较低

  4. 分代收集算法,它会将整个堆内存分成几部分空间,每个空间中放入不同类型的对象,然后各自适合的算法回收

    在JDK8时,堆被分为了两份:新生代和老年代,默认空间比例为1:2

    对于新生代,内部又被分为了三个区域:Eden区,S0区,S1区,,默认空间比例为8:1:1

它的基本工作机制是:

当创建一个对象的时候,这个对象会被分配在新生代的Eden区,当Eden区要满了时候,触发MinorGC

当进行MinorGC后,此时在Eden区存活的对象被移动到S0区,并且当前对象的年龄会加1,清空Eden区

当再一次触发MinorGC的时候,会把Eden区中存活下来的对象和S0中的对象,移动到S1区中,这些对象的年龄会加1,清空Eden区和S0区

当再一次触发YoungGC的时候,会把Eden区中存活下来的对象和S1中的对象,移动到S0区中,这些对象的年龄会加1,清空Eden区和S1区

对象的年龄达到了某一个限定的值(默认15岁),那么这个对象就会进入到老年代中,除此之外,大对象也会直接放入老年代空间

当老年代满了之后,触发FullGCFullGC同时回收新生代和老年代

在上述过程中,新生代中的对象存活率比较低,所以选用复制算法;老年代中对象存活率高,所以使用标记-整理算法

小细节:

  1. 当对新生代产生GC:MinorGC,老年代代产生GC:Major GC ,新生代和老年代产生FullGC

  2. Minor GC非常频繁,一般回收速度也很快,Major GC一般会伴随一次Minor GC,Major GC的速度要慢很多,一般要比Minor GC慢10倍

  3. 占用内存较大的对象,对于虚拟机内存分配是一个坏消息,虚拟机提供了一个-XX:PretenureSizeThreshold让大于这个设置的对象直接存入老年代

  4. 虚拟机给每个对象定义了一个Age年龄计数器,对象在Eden中出生并经过第一次Minor GC后仍然存活,年龄+1,此后每熬过一次Minor GC则年龄+1,

    当年龄增加到一定程度(默认15岁),就会晋升到老年代。可通过参数设置晋升年龄 -XX:MaxTenuringThreshold

8、JVM的垃圾回收器都有哪些

JVM中常见的一些垃圾回收器有:

  • 新生代回收器:Serial、ParNew、Parallel Scavenge

  • 老年代回收器:Serial Old、Parallel Old、CMS

  • 整堆回收器:G1

新生代垃圾回收器一般采用的是复制算法,复制算法的优点是效率高,缺点是内存利用率低

老年代回收器一般采用的是标记-整理的算法进行垃圾回收

标签:面试题,Java,对象,回收,算法,GC,JVM,加载
From: https://blog.csdn.net/w13114/article/details/141299881

相关文章

  • 最新版Java面试题及答案整理(程序员必备)
    1、java为什么要有包装类型?主要原因包括以下几点:处理基本数据类型的null值:基本数据类型(如int,double等)不能直接赋值为null,而包装类型(如Integer、Double)可以表示null值,这对于某些业务逻辑和数据处理来说非常有用。提供额外功能:包装类型提供了一些额外的方法和功能,这些......
  • JavaEE篇:多线程(1)
    一认识线程(Thread)1.1概念1.1.1线程是什么?线程被创建出来是为了完成分配给它的任务。线程又称轻量级进程,是操作系统的基本调度单位。一个线程就是一个执行流。线程的创建销毁和切换都比进程更加的方便。进程是操作系统分配资源的基本单位,线程的创建和释放不涉及资源分配......
  • 【JavaEE】线程安全的集合类
    目录前言多线程环境使用ArrayList多线程环境使用队列多线程环境下使用哈希表1.HashTable2.ConcurrentHashMap面试题1.ConcurrentHashMap的读会否需要加锁,为什么?2.介绍下ConcurrentHashMap的锁分段技术?3.ConcurrentHashMap在jdk1.8做了哪些优化?4.HashTable和HashMap......
  • 全网最新200道Java程序员面试题(含答案)!
    发现网上很多Java面试题都没有答案,所以花了很长时间搜集整理出来了这套Java面试题大全~这套互联网30w字Java面试题包括了:MyBatis、ZK、Dubbo、EL、Redis、MySQL、并发编程、Java面试、Spring、微服务、Linux、Springboot、SpringCloud、MQ、Kafka 面试专题一、Java基础1.......
  • javaSE
    JDK的安装与卸载卸载首先在控制面版上卸载---》需要在环境变量上删除配置。安装直接下载install版的jdk直接安装即可配置环境变量(当前电脑在任何位置都能使用jdk中bin目录的命令)我的电脑--》属性--》高级属性设置--》环境变量--》path添加jdk安装目录中的bin文件路径C:\P......
  • javaSE面向对象
    面向对象思想编程学习面向对象内容的三条主线Java类及类的成员:(重点)属性、方法、构造器;(熟悉)代码块、内部类面向对象的特征:封装、继承、多态、(抽象)其他关键字的使用:this、super、package、import、static、final、interface、abstract等方法(对功能进行封装,实现代码的复用)方......
  • JAVA13-线程
    1.线程的简介1.1什么是进程        进程,是正在运行的程序实例,是操作系统进行资源分配的最小单位。每个进程都有它自己的地址空间和系统资源(比如CPU时间,内存空间,磁盘IO等)。多个进程可以同时执行,每个进程在运行时都不会影响其他进程的运行,资源不共享。程序是一个没......
  • 基于Java学生资助管理系统设计实现(源码+LW+调试文档)
     ......
  • 基于Java驾校信息管理系统设计实现(源码+LW+调试文档)
     ......
  • 基于Java奶茶店管理系统设计实现(源码+LW+调试文档)
     ......