Jvm 笔记

前言

先看几道面试题?

1、请你谈谈你对JVM的理解?Java8的虚拟机有什么更新?

JVM是Java Virtual Machine(Java虚拟机)的缩写,JVM是一种用于计算设备的规范,它是一个虚构出来的计算机,是通过在实际的计算机上仿真模拟各种计算机功能来实现的。Java跨平台就是通过jvm实现的
java8的更新撤销了永久带,引入了元空间

2、JVM的常用参数调优你知道哪些?

Java堆区用于存储Java对象实例,那么堆的大小在JVM启动时就已经设定好了,大家可以通过选项"-Xmx"和"-Xms"来进行设置。
“-Xms"用于表示堆区的起始内存,等价于-xx:InitialHeapSize
“-Xmx"则用于表示堆区的最大内存,等价于-XX:MaxHeapSize
一旦堆区中的内存大小超过“-Xmx"所指定的最大内存时,将会抛出outofMemoryError异常。
通常会将-Xms和-Xmx两个参数配置相同的值,其目的是 为了能够在Java垃圾回收机制清理完堆区后不需要重新分隔计算堆区的大小,从而提高性能。

3、什么时候需要JVM调优

应用系统慢(响应性能下降,吞吐量下降)、卡顿(GC停顿时间长、次数频繁)
应用出现OOM等内存异常(使用的堆内存过大、本地缓存过大;会发生OOM的区域:堆、元空间、虚拟机栈、本地方法栈、直接内存)

4、JVM调优的原则

JVM调优是一种手段,但并不一定所有问题都需要通过JVM调优解决,最有效的优化手段是架构和代码层面的优化。所以JVM优化是最后不得已的手段,在架构调优和代码调优后对服务器配置的最后一次"压榨"。

5、谈谈JVM中,你对类加载器认识?

1) 根类加载器(bootstrap class loader):它用来加载 Java 的核心类,是用原生代码来实现的,并不继承自
java.lang.ClassLoader(负责加载$JAVA_HOME中jre/lib/rt.jar里所有的class,由C++实现,不是ClassLoader子类)。
2)扩展类加载器(extensions class
loader):它负责加载JRE的扩展目录,lib/ext或者由java.ext.dirs系统属性指定的目录中的JAR包的类。由Java语言实现,父类加载器为null。
3)系统类加载器(system class
loader):被称为系统(也称为应用)类加载器,它负责在JVM启动时加载来自Java命令的-classpath选项、java.class.path系统属性,或者CLASSPATH换将变量所指定的JAR包和类路径。程序可以通过ClassLoader的静态方法getSystemClassLoader()来获取系统类加载器。

6、JVM中垃圾回收的算法?
1)复制算法:时间效率较高、空间利用率低、不会产生空间碎片。主要操作是复制“活对象”,故适合于每次回收时大量对象死去只有少量存活的情况(年轻代)
2)标记-清除算法:时间效率低、空间利用率高、会产生空间碎片。主要操作是清除“死对象”,故适合于回收时大量对象仍存活只有少数死去的情况(老年代)
3)标记-整理算法。时间效率低、空间利用率高、不会产生空间碎片,但复制移动会产生性能消耗。适用情况同上
4)分代收集算法:就是上面几种用在堆的不同的分代区域中。年轻代:复制算法;老年代:标记-清除算法、标记-整理算法。

7、什么是OOM?什么是StackOverFlowError?有哪些方法分析?

OOM是OutOfMemoryError内存溢出错误,一旦堆区中的内存大小超过“-Xmx"所指定的最大内存时会报错
StackOverFlowError是函数调用栈太深了,注意代码中是否有了循环调用方法而无法退出的情况

8、JVM调优目的

吞吐量:用户代码运行时间 / (用户代码运行时间 + GC时间) 响应时间:STW越短,响应时间越好

虽然Java开发者每天都在使用JVM,但对其有所研究并且研究深入的人却少之又少。然而,JVM的重要性却又是不言而喻的。基于JVM的各种动态与静态语言生态圈已经异常繁荣了,对JVM的运行机制有一定的了解不但可以提升我们的竞争力,还可以让我们在面对问题时能够沉着应对,加速问题的解决速度;同时还能够增强我们的自信心,让我们更加游刃有余。而且,如果我们想要进阶到技术专家或者更高等级,就必须要学习JVM

一.什么是jvm?

(1)jvm是一种用于计算设备的规范,它是一个虚构出来的机器,是通过在实际的计算机上仿真模拟各种功能实现的。
(2)jvm包含一套字节码指令集,一组寄存器,一个栈,一个垃圾回收堆和一个存储方法域。
(3)JVM屏蔽了与具体操作系统平台相关的信息,使Java程序只需生成在Java虚拟机上运行的目标代码(字节码),就可以在多种平台上不加修改地运行。
JVM在执行字节码时,实际上最终还是把字节码解释成具体平台上的机器指令执行。

JVM体系结构图

在这里插入图片描述

二.JVM原理

(1)jvm是java的核心和基础,在java编译器和os平台之间的虚拟处理器,可在上面执行字节码程序。
(2)java编译器只要面向jvm,生成jvm能理解的字节码文件。java源文件经编译成字节码程序,通过jvm将每条指令翻译成不同的机器码,通过特定平台运行。

类加载过程

类从被加载到虚拟机内存中开始,到卸载出内存为止,它的整个生命周期包括:加载(Loading)、验证(Verification)、准备(Preparation)、解析(Resolution)、初始化(Initialization)、使用(Using)和卸载(Unloading)7个阶段。其中准备、验证、解析3个部分统称为连接(Linking)。如图所示。
在这里插入图片描述
加载、验证、准备、初始化和卸载这5个阶段的顺序是确定的。

加载(Loading):根据类的全限定名(包括包路径和类名),定位并读取类文件的字节码。
链接(Linking):将类的字节码转换为可以在虚拟机中运行的格式。链接过程包括三个阶段:
验证(Verification):验证字节码的正确性和安全性,确保它符合Java虚拟机的规范。
准备(Preparation):为类的静态变量分配内存,并设置默认的初始值。
解析(Resolution):将类的符号引用(比如方法和字段的引用)解析为直接引用(内存地址)。
初始化(Initialization):执行类的初始化代码,包括静态变量的赋值和静态块的执行。

双亲委派机制

双亲委派机制的工作原理:一层一层的 让父类去加载,最顶层父类不能加载往下数,依次类推。

  1. 类加载器收到类加载的请求;
  2. 把这个请求委托给父加载器去完成,一直向上委托,直到启动类加载器;
  3. 启动器加载器检查能不能加载(使用findClass()方法),能就加载(结束);否则,抛出异常,通
    知子加载器进行加载。
  4. 重复步骤三;
package java.lang;
public class String {
      public static void main(String[] args) {
      System.out.println(1);
   }
}

在这里插入图片描述
大家所熟知的String 类,直接告诉大家,String 默认情况下是启动类加载器进行加载的。假设我也自定义一个String 。现在你会发现自定义的String 可以正常编译,但是永远无法被加载运行。这是因为申请自定义String 加载时,总是启动类加载器,而不是自定义加载器,也不会是其他的加载器。双亲委派机制可以确保Java核心类库所提供的类,不会被自定义的类所替代。

什么时候需要JVM调优

  • 应用系统慢(响应性能下降,吞吐量下降)、卡顿(GC停顿时间长、次数频繁)
  • 应用出现OOM等内存异常(使用的堆内存过大、本地缓存过大;会发生OOM的区域:堆、元空间、虚拟机栈、本地方法栈、直接内存)

常用的垃圾回收器

  • 串行回收器:SerialSerial Old
  • 并行回收器: ParNewParallel scavengeParallel old
  • 并发回收器:CMS(Java8)、G1(Java9)

G1和CMS区别

G1 回收器与 CMS 回收器的另一个很大的区别是:G1 回收器使用的是「标记 - 整理」算法,而 CMS 回收器使用的是「标记 - 清除」算法。 因此,CMS 回收器会产生非常多的内存碎片,而 G1 回收器则没有这个困扰。

那为什么 CMS 回收器不用「标记 - 整理」算法呢?
因为 CMS 回收器的老年代很大,使用「标记 - 整理」算法需要耗费很长的 GC 停顿时间,这会导致接口响应时间变长。实际上 CMS 回收器后续提供了 -XX:+UseCMSCompactAtFullCollection 参数去实现内存压缩,但在内存压缩的时候 GC 停顿时间会很长,从而导致接口响应时间变长。

G1 回收器也用的是「标记 - 整理」算法,为啥就不会导致长 GC 停顿时间呢?

因为 G1 回收器使用了分 Region 的思想,其将大块的内存化整为零成为 Region。此外,其还维护了一个待回收 Region
列表,可以选择回收性价比最高的 Region 进行回收,从而实现对 GC 停顿时间的灵活控制。

JVM中如何判断对象可以被回收?

1.引用计数算法

给对象添加一个引用计数器,当有一个地方引用它,计数器值加 1;当引用失效时,计数器值减 1。任何时刻计数器值为 0 表示这个对象可以被回收了。

优点: 判断效率高,实现简单。

不足之处: 难以解决对象之间相互循环引用的问题。

2.可达性分析算法(JVM采用)

通过一系列称为 “GC Roots” 的对象作为起始点,从这个节点向下搜索,搜索走过的路径就是引用链,当一个对象到 GC Roots 没有任何引用链相连,也就是从 GC Roots 到这个对象不可达,则这个对象不可达,可以被回收。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值