Java面试准备-JVM篇

简介: Java面试准备-JVM篇

知识汇总


需要了解 内存模型 各部分作用,保存哪些数据

类加载双亲委派加载机制,常用加载器加载哪些类型的类

GC分代回收的思想、不同垃圾回收算法的思路

性能调优及常有的参数作用,参数调优的依据和工具分析问题的使用方法。

执行模式

编译器优化


Java内存模型


栈(线程独占):又称为方法栈,线程私有的,与线程同一时间创建,线程执行方法都会创建一个栈阵,用来存储局部变量表,调用方法时执行入栈,方法返回时执行出栈。,-Xss参数可以设置虚拟机栈大小。

本地方法栈:与栈类似,也是用来保存执行方法的信息,执行Java方法是使用栈,实现Native方法是使用本地方法栈 C语言

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

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

方法区(非堆区):线程共享的,用于存储已被虚拟机加载的类信息,常量,静态变量等。


说说类加载与卸载


加载通过类的完全限定名,查找次类字节码文件,利用字节码文件创建Class对象

验证当前Class文件符合当前虚拟机的要求,不会危害到虚拟机自身安全

准备进行内存分配

解析 将常量池中的符号引用替换

初始化主要完成静态块执行及静态变量的赋值。

加载机制:双亲委派模式,即加载器加载类时先把请求委托给自己的父类加载器执行,直到顶层的启动类加载器,父类加载器能够完成加载者成功返回,不能再进行子类加载。

优点:避免类的重复加载、避免Java核心API被篡改

分代回收:年轻代 、标记复制老年代、标记清除


JVM垃圾回收算法


G1算法

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

其取消了新生代和老年代的物理划分,但任然属于分代收集器。

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

ZBC算法


说说堆和栈的区别


栈是运行时单位,代表着逻辑,内含基本数据类型和堆中的引用,所在区域连续,没有碎片。

堆是存储单位,代表着数据,可被多个栈共享,所在区域不联系,碎片化。

功能不同:栈用来存储局部变量和方法调用,而堆内存来存储Java中的对象,无论是成员变量、局部变量、还是类变量,它们指向的对象都是存储在堆内存中。

共享性不一样:栈是线程私有的,堆是内存中共享的。

异常错误不同:栈内存不足:StackOverFlowError、堆内存不住:OutOfMemoryError

空间大小:栈的空间远远小于堆空间的大小


什么时候会发生FullGC


直接调用 System.gc() 方法

旧生代空间不足:新生代对象转入或创建大对象,当执行FullGC仍然内存不足时,抛出java.lang.OutOfMemoryError: Java heap space 错误

永久代空间满时:当系统要加载的类、反射的类、和调用方法比较多时,永久代可能会被占满,如果还是不足则抛出: java.lang.OutOfMemoryError: PermGen space


什么是虚拟机,为什么Java叫与平台无关的语言


Java虚拟机是可以执行Java字节码的虚拟机进程,Java源文件被编译成Java虚拟机执行的字节码文件,Java编译后可实现跨平台,因为JVM虚拟机让这个变得可能。


谈谈对象分配规则


对象有限分配在Eden区,如果没有足够的空间,则进行MinorGC

大对象直接进入老年代,这样做是避免内存中进行拷贝(新生代采用复制算法收集内存)

长期存活的对象进入老年代,


描述下JVM加载class文件原理机制


JVM的加载是由类加载器(ClassLoader)和它的子类来实现的,当Java程序需要某个类时,JVM确保这个类已经被加载、验证、准备、解析、初始化等操作,类加载就是把.class文件读取到内存中,通常创建一个字节数组进行存取。

类加载机制采用了双亲委派机制进行加载、保证了平台的安全性。


关于类的生命周期


加载、查找并加载二进制数据、在Java堆中创建一个Class类的对象。

连接(验证、准备、解析)

初始化:类赋值

使用:new出对象

卸载:执行垃圾回收


如何判断对象可以被回收


引用计数:每个对象都有一个引用计算属性、新增一个引用+1,引用释放-1,计数为0时可以回收,次方法简单,无法解决对象互相引用问题。

可达性分析:从GC Roots开始向下搜索,搜索所经过的路径称为引用链,当一个对象从GC Roots没有任何引用链时,则证明次对象是不可用的,可进行回收。


垃圾回收算法


标记-清除算法:算法分别是标记和清除两个阶段、首先标记出所需要清理的对象,在标记完成后统一对标记的对象进行回收。

复制算法:讲可用的容量划分为相等的两块,每次只使用其中的一块,当一块内存要用完了的时候,就将存活的对象复制到另一块上面,然后把已经使用过的一块全部清楚。

标记-压缩算法:标记和标记-清除算法中一致,让所有存活的内存都移向一边,然后清理掉端边界以外的内存。

分代收集算法:把堆内存分为新生代和老年代,这样可以根据不同年代的特点采用最适合的垃圾收集算法。


调优的命令有哪些


jps:显示指定系统内所有HotSpot虚拟机进程

jstat:用于监视虚拟机运行时状态命令,显示虚拟机内存,垃圾回收等。

jmap:生成 heap dump文件

jstack:生成当时的线程快照

jinfo:实时查看和调整虚拟机的运行参数


常见的调优工具


jconsole:jdk自带的监控控制台

Java VisualVM:内存快照、线程快照。

arthas 阿里巴巴开源 命令查看


为什么将-Xms和-Xmx设置为相同的值


每次JVM增加堆大小时,它都必须向操作系统申请额外的内存,这会有一定的时间开销。

使用较小的堆大小,使得GC更加的频繁,如果从最开始就设置大一些,GC就不会那也频繁。


逃逸分析


虚拟机为什么要使用元空间替换永久代

在之前方法区都是永久代来实现的

从1.8开始,取消了永久代,改为元空间,换句话说方法区还在,只是实现变了,从永久代变成了元空间。

在jdk1.8后,方法区存于元空间,物理内存不在于堆连续,而是直接存于本地内存中,理论上是(内存有多大、元空间就有多大)

之所以要替换永久代:是为了避免OOM异常,因为设置了永久代的大小,当使用元空间时,可以加载多少类的元数据不再由MaxPermSize来控制,而由系统实际空间来控制。

调优命令有哪些


堆栈内存相关


-Xms 设置初始堆的大小

-Xmx 设置最大堆的大小

-Xss 每个线程的堆栈大小


垃圾收集器相关


-XX:+UseParallelGC:选择垃圾收集器为并行收集器。

-XX:ParallelGCThreads=20:配置并行收集器的线程数

-XX:+UseCMSCompactAtFullCollection 。可能会影响性能,但是

可以消除碎片


辅助信息


-XX:+PrintGCDetails 打印GC详细信息

-XX:+HeapDumpOnOutOfMemoryError让JVM在发生内存溢出的时候自动生成内存快照,排查问题用

-XX:+DisableExplicitGC禁止系统System.gc(),防止手动误触发FGC造成问题


JVM有哪些垃圾回收器


Serial收集器(复制算法):新生代单线程收集器,有点是简单高效

ParNew收集器(复制算法):新生代并行收集器,实际是Serial多线程收集器。

Parallel Scavenge(复制算法):新生代并行收集器,高吞吐,高效利用CPU。

Serial Old收集器(标记-整理):老年代单线程收集器。

Parallel Old收集器(标记-整理):老年代并行收集器

CMS(标记-清除):搞并发,低停顿。

G1(标记-整理):Java堆并行收集器,不会产生内存碎片。

ZGC:不设年龄分代,使用了读屏障,在JDK11中加入。

新生代垃圾收集器:Serial、ParNew、Paral

老年代垃圾收集器:CMS、Serial Old、Parallel Old

整堆收集器:G1、ZGC


如何选择垃圾收集器


如果堆不是特别大、且单核的机器、选择单线程收集器(参数: -XX:+UseSerialGC)

如果吞吐量优先的,并且停顿时间没有要求的,可以选择并行收集器( -XX:+UseParallelGC)

响应要求高、较少的停顿、基本上选择CMS、G1、ZGC(-XX:+UseZGC、-XX:+UseG1GC)

使用并行收集器是一个不错的选择。

相关文章
|
5天前
|
存储 缓存 Oracle
Java I/O流面试之道
NIO的出现在于提高IO的速度,它相比传统的输入/输出流速度更快。NIO通过管道Channel和缓冲器Buffer来处理数据,可以把管道当成一个矿藏,缓冲器就是矿藏里的卡车。程序通过管道里的缓冲器进行数据交互,而不直接处理数据。程序要么从缓冲器获取数据,要么输入数据到缓冲器。
Java I/O流面试之道
|
2天前
|
存储 缓存 Java
大厂面试必看!Java基本数据类型和包装类的那些坑
本文介绍了Java中的基本数据类型和包装类,包括整数类型、浮点数类型、字符类型和布尔类型。详细讲解了每种类型的特性和应用场景,并探讨了包装类的引入原因、装箱与拆箱机制以及缓存机制。最后总结了面试中常见的相关考点,帮助读者更好地理解和应对面试中的问题。
15 4
|
2天前
|
存储 Java 程序员
Java基础的灵魂——Object类方法详解(社招面试不踩坑)
本文介绍了Java中`Object`类的几个重要方法,包括`toString`、`equals`、`hashCode`、`finalize`、`clone`、`getClass`、`notify`和`wait`。这些方法是面试中的常考点,掌握它们有助于理解Java对象的行为和实现多线程编程。作者通过具体示例和应用场景,详细解析了每个方法的作用和重写技巧,帮助读者更好地应对面试和技术开发。
26 4
|
23天前
|
存储 监控 算法
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程 ?
尼恩提示: G1垃圾回收 原理非常重要, 是面试的重点, 大家一定要好好掌握
美团面试:说说 G1垃圾回收 底层原理?说说你 JVM 调优的过程  ?
|
25天前
|
存储 SQL 小程序
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
这篇文章详细介绍了Java虚拟机(JVM)的运行时数据区域和JVM指令集,包括程序计数器、虚拟机栈、本地方法栈、直接内存、方法区和堆,以及栈帧的组成部分和执行流程。
25 2
JVM知识体系学习五:Java Runtime Data Area and JVM Instruction (java运行时数据区域和java指令(大约200多条,这里就将一些简单的指令和学习))
|
15天前
|
存储 Java 程序员
Java面试加分点!一文读懂HashMap底层实现与扩容机制
本文详细解析了Java中经典的HashMap数据结构,包括其底层实现、扩容机制、put和查找过程、哈希函数以及JDK 1.7与1.8的差异。通过数组、链表和红黑树的组合,HashMap实现了高效的键值对存储与检索。文章还介绍了HashMap在不同版本中的优化,帮助读者更好地理解和应用这一重要工具。
35 5
|
14天前
|
存储 Java
[Java]面试官:你对异常处理了解多少,例如,finally中可以有return吗?
本文介绍了Java中`try...catch...finally`语句的使用细节及返回值问题,并探讨了JDK1.7引入的`try...with...resources`新特性,强调了异常处理机制及资源自动关闭的优势。
16 1
|
15天前
|
存储 算法 Java
Java虚拟机(JVM)的内存管理与性能优化
本文深入探讨了Java虚拟机(JVM)的内存管理机制,包括堆、栈、方法区等关键区域的功能与作用。通过分析垃圾回收算法和调优策略,旨在帮助开发者理解如何有效提升Java应用的性能。文章采用通俗易懂的语言,结合具体实例,使读者能够轻松掌握复杂的内存管理概念,并应用于实际开发中。
|
23天前
|
Java 程序员
Java 面试高频考点:static 和 final 深度剖析
本文介绍了 Java 中的 `static` 和 `final` 关键字。`static` 修饰的属性和方法属于类而非对象,所有实例共享;`final` 用于变量、方法和类,确保其不可修改或继承。两者结合可用于定义常量。文章通过具体示例详细解析了它们的用法和应用场景。
24 3
|
25天前
|
Java 应用服务中间件 程序员
JVM知识体系学习八:OOM的案例(承接上篇博文,可以作为面试中的案例)
这篇文章通过多个案例深入探讨了Java虚拟机(JVM)中的内存溢出问题,涵盖了堆内存、方法区、直接内存和栈内存溢出的原因、诊断方法和解决方案,并讨论了不同JDK版本垃圾回收器的变化。
25 4