写在前面

从开始学习Java的时候,我们就接触了这样一种观点:Java中的对象是在堆上创建的,对象的引用是放在栈里的,那这个观点就真的是正确的吗?如果是正确的,那么,面试官为啥会问:“Java中的对象就一定是在堆上分配的吗?”这个问题呢?看来,我们从接触Java就被灌输的这个观点值得我们怀疑。

关于面试题

标题中的面试题为:Java中的对象和数组都是在堆上分配的吗?

面试官这样问,有些小伙伴心里会想:我从一开始学习Java时,就知道了:Java中的对象是在堆上创建的,对象的引用是存储到栈中的,那Java中的对象和数组肯定是在堆上分配的啊!难道不是吗?

如果你这样回答,就会被直接Pass掉。

或许有些小伙伴还是不太明白,那我们继续往下看。

面试题答案

首先,我们先给出这个题目的答案,这里我先简短的回答下这个面试题,后续我们会进行相关分析。

你可以这样回答:Java中的对象不一定是在堆上分配的,因为JVM通过逃逸分析,能够分析出一个新对象的使用范围,并以此确定是否要将这个对象分配到堆上。如果JVM发现某些对象没有逃逸出方法,就很有可能被优化成在栈上分配。

这里,我们接触了一个新名词:逃逸分析。相信很多小伙伴不是很明白,那我们继续往下看。

逃逸分析

逃逸分析的概念

先以官方的形式来说下什么是逃逸分析。逃逸分析就是:一种确定指针动态范围的静态分析,它可以分析在程序的哪些地方可以访问到指针。

在JVM的即时编译语境下,逃逸分析将判断新建的对象是否逃逸。即时编译判断对象是否逃逸的依据:一种是对象是否被存入堆中(静态字段或者堆中对象的实例字段),另一种就是对象是否被传入未知代码。

直接说这些概念,确实有点晕啊,那我们就来两个示例。

对象逃逸示例

一种典型的对象逃逸就是:对象被复制给成员变量或者静态变量,可能被外部使用,此时变量就发生了逃逸。

我们可以用下面的代码来表示这个现象。

/*** @author binghe* @description 对象逃逸示例1*/
public class ObjectEscape{private User user;public void init(){user = new User();}
}

在ObjectEscape类中,存在一个成员变量user,我们在init()方法中,创建了一个User类的对象,并将其赋值给成员变量user。此时,对象被复制给了成员变量,可能被外部使用,此时的变量就发生了逃逸。

另一种典型的场景就是:对象通过return语句返回。如果对象通过return语句返回了,此时的程序并不能确定这个对象后续会不会被使用,外部的线程可以访问到这个变量,此时对象也发生了逃逸。

我们可以用下面的代码来表示这个现象。

/*** @author binghe* @description 对象逃逸示例2*/
public class ObjectReturn{public User createUser(){User user = new User();return user;}
}

给出两个示例,相信小伙伴们对JVM的逃逸分析多少有点了解了吧,没错,JVM通过逃逸分析,能够分析出新对象的使用范围,从而决定新对象是否要在堆上进行分配。

还没完,我们继续看下逃逸分析的优点,以便于小伙伴们能够更好的理解逃逸分析。

逃逸分析的优点

逃逸分析的优点总体上来说可以分为三个:对象可能分配在栈上、分离对象或标量替换、消除同步锁。我们可以使用下图来表示。

对象可能分配在栈上

JVM通过逃逸分析,分析出新对象的使用范围,就可能将对象在栈上进行分配。栈分配可以快速地在栈帧上创建和销毁对象,不用再将对象分配到堆空间,可以有效地减少 JVM 垃圾回收的压力。

分离对象或标量替换

当JVM通过逃逸分析,确定要将对象分配到栈上时,即时编译可以将对象打散,将对象替换为一个个很小的局部变量,我们将这个打散的过程叫做标量替换。将对象替换为一个个局部变量后,就可以非常方便的在栈上进行分配了。

同步锁消除

如果JVM通过逃逸分析,发现一个对象只能从一个线程被访问到,则访问这个对象时,可以不加同步锁。如果程序中使用了synchronized锁,则JVM会将synchronized锁消除。

这里,需要注意的是:这种情况针对的是synchronized锁,而对于Lock锁,则JVM并不能消除。

要开启同步消除,需要加上 -XX:+EliminateLocks 参数。因为这个参数依赖逃逸分析,所以同时要打开 -XX:+DoEscapeAnalysis 选项。

所以,并不是所有的对象和数组,都是在堆上进行分配的,由于即时编译的存在,如果JVM发现某些对象没有逃逸出方法,就很有可能被优化成在栈上分配。

特别推荐一个分享架构+算法的优质内容,还没关注的小伙伴,可以长按关注一下:

长按订阅更多精彩▼如有收获,点个在看,诚挚感谢

【性能优化】面试官:Java中的对象和数组都是在堆上分配的吗?相关推荐

  1. Java对象都是在堆上分配空间吗?答案竟然是...

    作者 l Hollis 来源 l Hollis(ID:hollischuang) Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点,所以,即使是一个Java的初学者,也一定或 ...

  2. Java 对象都是在堆上分配内存吗?

    为了防止歧义,可以换个说法:Java对象实例和数组元素都是在堆上分配内存的吗? 答:不一定.满足特定条件时,它们可以在(虚拟机)栈上分配内存. JVM内存结构很重要,多多复习 这和我们平时的理解可能有 ...

  3. java 堆_Java 对象都是在堆上分配内存吗?

    为了防止歧义,可以换个说法:Java对象实例和数组元素都是在堆上分配内存的吗? 答:不一定.满足特定条件时,它们可以在(虚拟机)栈上分配内存. JVM内存结构很重要,多多复习 这和我们平时的理解可能有 ...

  4. 对象并不一定都是在堆上分配内存的

    JVM内存分配策略 关于JVM的内存结构及内存分配方式,不是本文的重点,这里只做简单回顾.以下是我们知道的一些常识: 1.根据Java虚拟机规范,Java虚拟机所管理的内存包括方法区.虚拟机栈.本地方 ...

  5. 惊艳面试官-Java中关于随机数生成8种方式的思考

    Java中生成随机数常用的有下面这8种写法:简而言之,名称带安全的未必安全,名字简洁的未必简单. Math.random() Random ThreadLocalRandom SecureRandom ...

  6. 面试官 | Java中的注解是如何工作的?

    自Java5.0版本引入注解之后,它就成为了Java平台中非常重要的一部分.开发过程中,我们也时常在应用代码中会看到诸如@Override,@Deprecated这样的注解.这篇文章中,我将向大家讲述 ...

  7. Android 性能优化 之初识Java内存区域

    前言     不管是日常开发,还是面试,我们都会和内存打交道,因为内存是支持软件运行的基本硬件环境.了解Android 内存管理,就有必要了解Java GC机制,必须要理解JVM 内存区域,这里我们主 ...

  8. Android 性能优化 之谈谈Java内存区域

    最近一年副业主要在学习投资和技能学习,把以前学习内存分析的一些笔记总结发出来,写了很多笔记总结都没有写完就又忙着了,最近再次总结复习学习一遍,还有提醒各位同学一定要学会投资.. 了解Android 内 ...

  9. Java中String对象的replaceAll方法调用性能优化小技巧

    Java中String对象的replaceAll方法调用性能优化小技巧 0x01 Java中String对象的replaceAll方法调用性能优化小技巧 1.1 What? 1.2 Why? 1.3 ...

最新文章

  1. linux服务器文件后缀名,linux服务器备份网站程序并下载到本地(自动)
  2. python英语-50 行代码,实现中英文翻译
  3. canopen服务器协议,CANopen
  4. 国产化达梦数据库数据迁移文档:oracle11g数据库转达梦8数据库实例演示
  5. UVA 10534 - Wavio Sequence
  6. 【素数】P1217 [USACO1.5]回文质数 Prime Palindromes
  7. navicat连接mysql闪退_Navicat连接MySQL时报10060及1045错误及my.ini位置问题
  8. 外设位宽为8、16、32时,CPU与外设之间地址线的连接方法
  9. 程序员成长之路(转)
  10. 安卓讲课笔记(9):列表视图
  11. 软件对于英特尔意味着什么?
  12. PS网页设计教程V——如何在Photoshop中创建一个商业网站布局
  13. javascript 基础之事件(event)-------1
  14. 跟着Code走,详解Symbian Client/Server架构
  15. win10安装双系统ubuntu
  16. HTML文字阴影火焰,CSS3文字特效属性text-shadow的介绍,实例讲解火焰文字效果
  17. 历史在重演:从KHTML到WebKit,再到Blink
  18. 摄像头 UIImagePickerController拍照和视频录制
  19. 代码随想录Day01:数组理论基础、二分查找、移除元素
  20. 彻底删除MySQL57服务

热门文章

  1. 你确定你理解内存分配吗?
  2. 新手学stm32学f1还是f4,stm32初学者最好买哪种开发板?
  3. HDU1250(高精度加法)
  4. codeforces 337D:树形dp[能到最远的一定可以到其他点]
  5. 解题报告:【kuangbin带你飞】专题九 连通图
  6. 牛客练习赛61 D 最短路变短了(最短路,反向最短路)难度⭐⭐⭐★
  7. log函数 oracle power_数学函数
  8. Selenium 2.0的由来及设计架构(二)
  9. 找出1个小时前更新的文件并进行拷贝
  10. 智能家居数据获得美好生活的6种方法