面试官问你jvm,你知道加分项在哪吗?

wx61cd7f82847ee      2022-04-27     587

关键词:


引言

在面试别人的过程中,​​JVM 内存模型​​​几乎必问,虽然有人说问这些就是​​面试造航母,工作拧螺丝​​。如果你想当一名 CRUD 码农,你可以选择不用了解这些。

在 JVM 内存模型的问答中,有些人能说出对象是在堆上分配的。但当我问对象一定是在堆上存储的嘛时,大部分人都回答是,或者犹豫了。

其实能回答出对象是在堆上分配存储已算正确了。但随着 ​​JIT​​​ 即时编译器的发展和逃逸分析技术的逐渐成熟,所有对象都分配到堆上也逐渐变得不那么绝对了。​​栈上分配​​​,​​标量替换​​​,​​锁消除​​等优化技术会发生一些微妙的变化。

我们知道,我们编写的 Java 源代码通过 ​​javac​​ 编译成字节码文件,然后类加载器将字节码文件加载到内存中,JVM 逐行读取解释字节码翻译成对应的机器指令执行。很明显,解释执行比那些可直接执行的二进制程序(例如 C 语言程序)慢得多。

所以为了提高效率,引入了 JIT (即时编译器)优化技术。Java 程序还是会通过解释器进行解释执行,但是如果某个方法或者代码块运行比较频繁的时候,JVM 认为这是​​热点代码​​,然后将热点代码翻译成本地机器指令,并且进行优化,缓存起来,下次再运行此段代码的时候直接运行而不用再解释。

JIT 中一个很重要的优化技术就是逃逸分析(Escape Analysis)。

逃逸分析

逃逸分析,其实就是分析一个对象是否会逃逸出方法,分析对象的动态作用域。如果一个对象在一个方法内定义,并且有可能被方法外部引用使用,那认为它逃逸了。

例如以下的 person 对象就发生了逃逸,即有可能会被方法外部引用。

public Person personEscape() 
Person person = new Person();
return person;

所以为什么要进行逃逸分析,其实最终目的就是为程序做优化,提高运行性能。有如下优化技术点:

  • 栈上分配
  • 标量替换
  • 锁消除

JDK1.7 开始,逃逸分析默认是开启的,可以通过以下参数进行启停。

# 开启
-XX:+DoEscapeAnalysis
# 关闭
-XX:-DoEscapeAnalysis

栈上分配

如果分析一个对象没有逃逸出方法的时候,就有可能被分配到栈上。这样就不需要在堆中进行 GC 回收,提高了性能。

package com.chenpi;

/**
* @Description
* @Author 陈皮
* @Date 2021/7/14
* @Version 1.0
*/
public class EscapeAnalysisTest

public static void main(String[] args)

long startTime = System.currentTimeMillis();

for (int i = 0; i < 10000000; i++)
stackAlloc();


System.out.println((System.currentTimeMillis() - startTime) + "ms");


public static void stackAlloc()
Person person = new Person("陈皮", 18);




class Person

private String name;
private long age;

public Person(String name, long age)
this.name = name;
this.age = age;

虚拟机参数设置开启逃逸分析,并且打印 GC 日志。

-Xms200m -Xmx200m -XX:+DoEscapeAnalysis -XX:+PrintGC

运行程序结果如下,消耗只需要 10 ms,并且没有 GC 。

10ms

关闭逃逸分析,并且打印 GC 日志。

-Xms200m -Xmx200m -XX:-DoEscapeAnalysis -XX:+PrintGC

运行程序结果如下,消耗时间增加了10多倍,并且伴随着多次的 GC 。

[GC (Allocation Failure)  51712K->784K(196608K), 0.0050396 secs]
[GC (Allocation Failure) 52496K->784K(196608K), 0.0030730 secs]
[GC (Allocation Failure) 52496K->752K(196608K), 0.0013993 secs]
[GC (Allocation Failure) 52464K->720K(196608K), 0.0018371 secs]
176ms

标量替换

  • 标量:不可再分解成更小数据的类型,例如基本数据类型就是标量。
  • 聚合量:可以再分解成其他聚合量或者标量的数据类型,例如对象引用类型。

如果一个对象不会发生逃逸,那么 JIT 可以优化把这个对象分解成若干个标量来代替。这就是标量替换。

public void scalarReplace() 
Coordinates coordinates = new Coordinates(105.10, 80.22);
System.out.println(coordinates.longitude);
System.out.println(coordinates.latitude);

以上演示程序,coordinates 对象不会发生逃逸,所以 JIT 编译器可以使用标量替换进行优化。最终被优化成如下程序。

public void scalarReplace() 
System.out.println(105.10);
System.out.println(80.22);

其实在现有的虚拟机中,并没有真正的实现栈上分配,其实是通过标量替换来实现的。

锁消除

为什么要消除锁呢?因为加锁会降低性能,那如何不用加锁是最好的。如果分析出加锁的对象不会发生逃逸,即只能被一个线程访问,JIT 是可以优化消除这个锁的。也称为同步省略。

public void lockRemove() 
synchronized (new Object())
System.out.println("我是陈皮!");

以上演示程序,Object 对象不会发生逃逸,所以也只能当前线程访问到,所以 JIT 编译器可以进行优化锁消除。最终被优化成如下程序。

public void lockRemove() 
System.out.println("我是陈皮!");

总结

但随着 ​​JIT​​ 即时编译器的发展和逃逸分析技术的逐渐成熟,所有对象都分配到堆上也逐渐变得不那么绝对了。通过逃逸分析技术,对象可能被分配到栈上,能减少 GC,提高程序性能。

但是开启逃逸分析的程序的性能一定高于没有开启逃逸分析的性能吗?其实不一定。逃逸分析技术其实也是很复杂的,所以也是一个会耗时的过程,如果经过逃逸分析之后,发现所有对象都逃逸了,就不能做优化处理,那这个逃逸分析的过程就消耗了时间,还不起优化作用,得不偿失。



大厂面试官问你meta-inf/spring.factories要怎么实现自动扫描自动装配?

大厂面试官问你META-INF/spring.factories要怎么实现自动扫描、自动装配?很多程序员想面试进互联网大厂,但是也有很多人不知道进入大厂需要具备哪些条件,以及面试官会问哪些问题,这里今天就给大家分享一下,如果大厂面试... 查看详情

面试官问你期望的工资是多少,怎么回答最好?

上一篇:应届入职华为OD一个半月,治好了我的精神内耗作者:叨叨快乐吧https://www.zhihu.com/question/64845093/answer/1861118311不会谈薪的程序员不是好程序员,哈哈,作为一个程序员,经常为了跳槽涨薪在正常不... 查看详情

android面试必备之jvm相关口水话(代码片段)

何为口水话呢?就是面试官问你相关问题的时候,你应该如何说的话。有没有遇到这样的场景,明明面试官问我的问题我会,我也看过甚至我自己也写过相关博客,但是在回答的时候还是支支吾吾说不清楚ÿ... 查看详情

面试官问你多线程你该怎么回答

...知识点,我们很容易遗忘,因此想要记住这些知识点,在面试过程中从容不迫,我们该怎么做呢?问:你了解多线程吗?讲一讲吧!OK,既然面试官要我们来讲,那么我们就要把握住这个机会,把面试官带到我们自己的节奏中来... 查看详情

面试官问你javascript,直接把这篇文章甩给他(代码片段)

大家好,我是辣条。给大家整理了JavaScript学习知识,对你有用的话,记得关注、评论、收藏、转发。目录JavaScript的介绍1.JavaScript的定义2.小结JavaScript的使用方式1.行内式(主要用于事件)2.内嵌式3.外链式4.小... 查看详情

面试官:你对jvm垃圾收集器了解吗?13连问你是否抗的住!

关于JVM垃圾收集器的面试题1、简述Java垃圾回收机制2、GC是什么?为什么要GC3、垃圾回收的优点和原理。并考虑2种回收机制4、垃圾回收器的基本原理是什么?垃圾回收器可以马上回收内存吗?有什么办法主动通知虚拟机进行垃... 查看详情

面试官问我jvm调优,我忍不住了,哈哈哈哈

面试官:今天要不来聊聊JVM调优相关的吧?面试官:你曾经在生产环境下有过调优JVM的经历吗?候选者:没有面试官:…候选者:嗯…是这样的,我们一般优化系统的思路是这样的候选者:1.一... 查看详情

如果面试官问你布隆过滤器,你该怎么回答?

参考技术A假设遇到这样一个问题:一个网站有20亿url存在一个黑名单中,这个黑名单要怎么存?若此时随便输入一个url,你如何快速判断该url是否在这个黑名单中?并且需在给定内存空间(比如:500M)内快速判断出。可能很多... 查看详情

面试官问你2:数组去重有什么方法(代码片段)

数组去重的九种方法(难度:★★★)1.利用set去重(这种方法无法去掉“”空对象,)2.for循环嵌套,splice去重(NaN和没有去重,两个null直接消失了)3.利用indexof去重()4.利用inclu... 查看详情

面试官问你stprstp选举原则,你该如何回答?

STP的选举角色①根端口存在于非根桥上,发送和接收数据帧②指定端口存在于根网桥和非根网桥上,根桥上所有的端口都为指定端口③非指定端口不转发也不接收数据帧④禁用端口处于关闭状态;RSTP的选举角色①根端口非根桥... 查看详情

面试官问你为什么离职,hr都认可的离职原因,你学会了吗?(代码片段)

...离职原因:`太闲了`离职原因可以说:结语面试时被问为什么离职,其实就是面试官,想通过这个问题来考察面试者综合能力,主要包含以下几个方面:1、是否有克服困难的能力2、人际关系处理能力... 查看详情

当面试官问你:如何进行性能优化?

...是区分一个程序猿技术水平和视野的一个重要指标。所以面试时,面试官总会问你一个问题,如何进行性能优化呢?性能优化是什么从前端的角度来说,性能优化可以分为两个方向。从用户角度来看,一个是页面加载的很快,另... 查看详情

面试官问你gc怎么调优?思路是什么呀?我直接把这篇文章甩到面试官脸上

...学过JVM垃圾回收机制的小伙伴肯定了解过CG调优,当面试官问到这个问题时,相信很多小伙伴第一时间想到的就是调节几个参数,调节一下分代的大小。简单的可以用这么一句话概括,水多了加面,面多了加水... 查看详情

面试官问你mybatissql是如何执行的?把这篇文章甩给他

摘自:https://www.cnblogs.com/cxuanBlog/p/12248536.html初识MyBatisMyBatis是第一个支持自定义SQL、存储过程和高级映射的类持久框架。MyBatis消除了大部分JDBC的样板代码、手动设置参数以及检索结果。MyBatis能够支持简单的XML和注解配置规则。... 查看详情

面试官问我jvm内存结构,我真的是

面试官:今天来聊聊JVM的内存结构吧?候选者:嗯,好的候选者:前几次面试的时候也提到了:class文件会被类加载器装载至JVM中,并且JVM会负责程序「运行时」的「内存管理」候选者:而JVM的内存... 查看详情

面试官问:mysql锁与事物隔离级别你知道吗?(代码片段)

 前言 前面我们讲了MySQL数据库底层的数据结构与算法、MySQL性能优化篇一些内容。我们再来聊聊MySQL的锁与事务隔离级别,分上下两篇,本篇重点讲MySQL的行锁与事务隔离级别。锁定义锁是计算机协调多个进程或线程并发... 查看详情

面试官问你mybatissql是如何执行的?把这篇文章甩给他

初识MyBatisMyBatis是第一个支持自定义SQL、存储过程和高级映射的类持久框架。MyBatis消除了大部分JDBC的样板代码、手动设置参数以及检索结果。MyBatis能够支持简单的XML和注解配置规则。使Map接口和POJO类映射到数据库字段和记录。... 查看详情

面试官问你mybatissql是如何执行的?把这篇文章甩给他

初识MyBatisMyBatis是第一个支持自定义SQL、存储过程和高级映射的类持久框架。MyBatis消除了大部分JDBC的样板代码、手动设置参数以及检索结果。MyBatis能够支持简单的XML和注解配置规则。使Map接口和POJO类映射到数据库字段和记录。... 查看详情