jvm面试题

jvm面试题

一、基础知识

1.JDK,JRE,JVM区别

概述

Jdk中包括了Jre,Jre中包括了JVM

jdk

Jdk还包括了一些Jre之外的东西 ,就是这些东西帮我们编译Java代码的, 还有就是监控Jvm的一些工具 Java Development Kit是提供给Java开发人员使用的,其中包含了Java的开发工具,也包括了JRE。

jre

Jre大部分都是 C 和 C++ 语言编写的,他是我们在编译java时所需要的基础的类库 Java Runtime Environment包括Java虚拟机和Java程序所需的核心类库等。

jvm

Java程序需要运行在虚拟机上,不同的平台有自己的虚拟机,因此Java语言可以实现跨平台。

二、内存模型

1.jvm内存结构

在这里插入图片描述

程序计数器

用来存储指向下一条指令的地址,也即将要执行的指令代码。由执行引擎读取下一条指令。

每个线程都有它自己的程序计数器,是线程私有的,生命周期与线程的生命周期保持一致。

java虚拟机栈

每个线程在创建时都会创建一个虚拟机栈,其内部保存一个个的栈帧,对应着一次次的方法调用。

是线程私有的。

在这里插入图片描述

本地方法栈

java虚拟机栈用于管理java方法的调用,而本地方法栈用于管理本地方法的调用。

是线程私有的。

java堆

java堆区在jvm启动的时候即被创建,其空间大小也就确定了。是jvm管理的最大一块内存空间。

所有的线程共享java堆。

堆是GC执行垃圾回收的重点区域。

方法区

方法区看作是独立java堆的内存空间。

是各个线程共享的内存区域,在jvm启动的时候被创建。

在jdk1.7及以前,习惯上把方法区,称为永久代。
jdk8开始,使用元空间取代了永久代。

元空间与永久代最大的区别在于,元空间不在虚拟机设置的内存中,而是使用本地内存。

它用于存储已被虚拟机加载的类型信息、常量、静态变量、即时编辑器编译后的代码缓存等。

三、类加载

1.类的加载过程

加载

1)通过一个类的全限定名获取定义此类的二进制字节流
2)将这个字节流所代表的静态存储结构转化为方法区的运行时数据结构
3)在内存中生成一个代表这个类的java.lang.Class对象,作为方法区这个类的各种数据访问入口

链接
验证

目的在于确保Class文件的字节流中包含信息符合当前虚拟机要求,保证被加载类的正确性,不会危害虚拟机自身安全。

准备

1)为类变量分配内存并且设置该类变量的默认初始值,即零值。

2)这里不包含用final修饰的static,因为final在编译的时候就会分配了,准备阶段会显式初始化。

3)这里不会为实例变量分配初始化,类变量会分配在方法区中,而实例变量是会随着对象一起分配到堆中。

解析

1)将常量池内的符号引用转换为直接引用的过程。

2)符号引用就是一组符号来描述所引用的目标。

3)直接引用就是直接指向目标的指针、相对偏移量或一个间接定位到目标的句柄。

4)事实上,解析操作往往会伴随着jvm在执行完初始化之后再执行。

初始化

1)初始化阶段就是执行类构造器方法()的过程。

2)此方法不需定义,是javac编译器自动收集类中的所有类变量的赋值动作和静态代码块中的语句合并而来。(如果代码中不存在类变量和静态代码块,则没有()方法)

3)构造器方法中指令按语句在源文件中出现的顺序执行。

4)() 不同于类的构造器。(关联:构造器是虚拟机视角下的())

5)若该类具有父类,jvm会保证子类的()执行前,父类的()已经执行完毕。

6)虚拟机必须保证一个类的()方法在多线程下被同步加锁。

2.类加载器

启动类加载器(Bootstrap ClassLoader)

1)这个类加载器使用C/C++语言实现的,嵌套在jvm内部

2)它用来加载java核心类库

扩展类加载器(extensions classloader)\

它用来加载 Java 的扩展库。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。

应用程序类加载器(system class loader)

它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。

用户自定义类加载器

通过继承 java.lang.ClassLoader类的方式实现。

3.双亲委派机制

在这里插入图片描述

四、创建一个对象的过程

1.判断对象对应的类是否加载、链接、初始化

2.为对象分配内存

3.处理并发安全问题

4.初始化分配到空间

所有属性设置默认值,保证对象实例字段在不赋值时可以直接使用

5.设置对象的对象头

6.执行init方法进行初始化

五、堆空间

1.堆空间分区

在这里插入图片描述

分区比例

在这里插入图片描述

六、垃圾回收

1.java中的几种引用方式

强引用 - 不回收
概念

在这里插入图片描述

特点

1)强引用可以直接访问目标对象

2)强引用所指向的对象在任何时候都不会被系统回收,虚拟机宁愿抛出OOM异常,也不会回收强引用所指向对象。

3)强引用可能导致内存泄漏。

软引用 - 内存不足即回收

在这里插入图片描述

弱引用 - 发现即回收

在这里插入图片描述

虚引用 - 对象回收跟踪

在这里插入图片描述

2.垃圾回收机制

1)自动内存管理
无需开发人员手动的参与内存的分配与回收,这样降低内存泄漏和内存溢出的风险。

自动内存管理机制,将程序员从繁重的内存管理中释放出来,可以更专心的专注于业务开发。

2)垃圾回收器可以对年轻代回收,也可以对老年代回收,甚至是全堆或方法区的回收。

什么时候回收

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

3.垃圾回收算法

标记阶段

在这里插入图片描述

引用计数算法

在这里插入图片描述

可达性分析算法
概述

在这里插入图片描述

实现思路

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

GC Roots

在这里插入图片描述

清除阶段
标记-清除算法
概念

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

缺点

在这里插入图片描述

标记-压缩(整理)算法
概念

将存活的内存空间分为两块,每次只使用其中一块,在垃圾回收时将正在使用的内存中的存活对象复制到未被使用的内存块中,之后清除正在使用的内存块中的所有对象,交换两个内存的角色,最后完成垃圾回收。

在这里插入图片描述

优缺点

在这里插入图片描述

应用场景

在这里插入图片描述

标记-压缩(整理)算法
出现背景

在这里插入图片描述

具体流程

在这里插入图片描述

指针碰撞

在这里插入图片描述

优缺点

在这里插入图片描述

分代收集算法

在这里插入图片描述

增量收集算法
概述

在这里插入图片描述

缺点

在这里插入图片描述

分区算法

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

4.垃圾回收器

前置知识
内存溢出

没有空闲内存,并且垃圾收集器也无法提供更多内存。

内存泄漏
概述

对象不会再被程序用到了,但是GC又不能回收它们的情况

场景举例

在这里插入图片描述

Stop the World

在这里插入图片描述

垃圾回收器分类

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

评估GC的性能指标
吞吐量

在这里插入图片描述

暂停时间

在这里插入图片描述

7种经典垃圾回收器

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

传统垃圾收集器介绍
Serial回收器:串行回收

在这里插入图片描述

ParNew回收器:并行回收

在这里插入图片描述

Parallel回收器:吞吐量优先

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

CMS回收器:低延迟
概述

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

工作的四个阶段

在这里插入图片描述

Concurrent Mode Failure

在这里插入图片描述

优缺点

在这里插入图片描述

G1回收器:区域化分代式
优点

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

缺点

在这里插入图片描述

适用场景

在这里插入图片描述

Remembered Set

在这里插入图片描述

回收过程

在这里插入图片描述

promotion failed

该问题是在进行Minor GC时,Survivor Space放不下,对象只能放入老年代,而此时老年代也放不下造成的。

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值