概述

很多人想要到阿里巴巴、美团、京东等互联网大公司去面试,但是现在互联网大厂面试一般都必定会考核JVM相关的知识积累和实践经验,毕竟线上系统写好代码部署之后,每个工程师都必须关注JVM相关的东西,比如OOM、GC等问题.

所以一起来看看JVM的最基本的区域划分以及工作原理,这个基本上是互联网公司面试必问。

区域划分

jvm的区域划分如下所示:

大致就是分为:程序计数器,虚拟机栈,堆,方法区,本地方法栈,这几个部分。

接下来我们从自己写好的Java代码如何通过JVM来运行的角度,来分析一下JVM里这些区域是如何支撑我们的Java代码跑起来的。

程序计数器

假设我们有如下的一个类,就是最最基本的一个HelloWorld而已:

public class HelloWorld {public static void main(String[] args) {System.out.println("Hello World");}}

上面那段代码首先会存在于 “.java” 后缀的文件里,这个文件就是java源代码文件,但是这个文件是面向我们程序员的,计算机他是看不懂你写的这段代码的

所以此时就得通过编译器,把“.java”后缀的源代码文件编译为“.class”后缀的字节码文件。

这个“.class”后缀的字节码文件里,存放的就是对你写出来的代码编译好的字节码了,这个字节码才是计算器可以理解的一种语言,而不是我们写出来的那一堆代码。

这个字节码看起来大概是下面这样的:

这段字节码并不是完全对照着HelloWorld那个类来写的,就是给一段示例,让大家知道“.java”翻译成的“.class”是大概什么样子的。

这里比如说“0: aload_0”这样的,就是“字节码指令”,他对应了一条一条的机器指令,计算机只有读到这种机器码指令,才知道具体应该要干什么。

比如说字节码指令可能会让计算机从内存里读取某个数据,或者把某个数据写入到内存里去,都有可能,各种各样的指令,就会指示计算机去干各种各样的事情。

所以现在首先明白一点,我们写好的Java代码是会被翻译成字节码的,对应各种字节码指令。

那么Java代码通过JVM跑起来的第一件事情就明确了, 首先Java代码被编译出来的字节码指令一定会被一条一条的执行,这样才能实现我们写好的代码被执行的效果。

那么在执行字节码指令的时候,JVM里的程序计数器就是用来记录每个线程当前执行的字节码指令的位置的,记录当前线程目前执行到了哪一条字节码指令。

因为会有多个线程来并发的执行各种不同的代码,所以每个线程都有自己的一个程序计数器,专门记录当前这个线程目前执行到了哪一条字节码指令了

下图更加清晰的展示出了他们之间的关系。

Java虚拟机栈

Java代码在执行的时候,一定是线程来执行某个方法中的代码,比如哪怕就是上面的那个最基础的HelloWorld代码,也会有一个main线程来执行main方法里的代码。

在方法里,经常会定义一些方法内的局部变量,比如下面这样,就在方法里定义了一个局部变量“name”。

public void sayHello() {String name = "hello";}

所以JVM必须有一块区域是来保存每个方法内的局部变量等等数据的,这个区域就是Java虚拟机栈

每个线程都会去执行各种方法的代码,方法内还会嵌套调用其他的方法,所以首先每个线程都有自己的Java虚拟机栈。

如果线程执行了一个方法,那么就会被这个方法调用创建对应的一个栈帧,栈帧里就有这个方法的局部变量表 、操作数栈、动态链接、方法出口等东西,但是这里别的不太好理解,先理解一个局部变量就可以。

比如说一个线程调用了上面写的“sayHello”方法,那么就会为“sayHello”方法创建一个栈帧,压入线程自己的Java虚拟机栈里面去。

在栈帧的局部变量表里就会有“name”这个局部变量,下图展示了这个过程。

接着如果“sayHello”方法调用了另外一个“greeting”方法 ,比如下面那样的代码:

那么这个时候会给“greeting”方法又创建一个栈帧压入线程的Java虚拟机栈里,因为开始执行“greeting”方法了,而且“greeting”方法的栈帧的局部变量表里会有一个“greet”变量,这是“greeting”方法的局部变量。

接着如果“greeting”方法执行完毕了,就会把“greeting”方法对应的栈帧从Java虚拟机栈里给出栈,然后如果“sayHello”方法也执行完毕了,就会把“sayHello”方法也从Java虚拟机栈里出栈。

这就是JVM中的 “ Java虚拟机栈 ” 这个组件的作用,调用执行任何方法的时候,都会给方法创建栈帧然后入栈。

而在栈帧里存放了这个方法对应的局部变量之类的数据,包括这个方法执行的其他相关的信息,方法执行完毕之后就出栈。

Java堆内存

JVM中有另外一个非常关键的区域,就是Java堆,这里就是存放我们在代码中创建的各种对象的,比如说下面的代码:

public void teach(String name) {Student student = new Student(name);student.study();}

上面的 “new Student(name)” 这个代码就是创建了一个Student类型的对象实例,这个对象实例里面会包含一些数据。

比如说这个Student的“name”就是属于这个对象实例的一个数据,那么类似Student这样的对象,就会存放在Java堆内存里。

Java堆内存区域里会放入类似Student的对象,然后方法的栈帧的局部变量表里,这个引用类型的“student”局部变量就会存放Student对象的地址。

相当于你可以认为局部变量表里的“student”指向了Java堆里的Student对象。

看下图会更加清晰一些。

方法区 / Metaspace

这个方法区是在JDK 1.8以前的版本里,代表JVM中的一块区域,主要是放类似Student类自己的信息的,平时用到的各种类的信息,都是放在这个区域里的,还会有一些类似常量池的东西放在这个区域里。

但是在JDK 1.8以后,这块区域的名字改了,叫做“Metaspace”,可以认为是“元数据空间”这样的意思,这里当然主要其实还是存放我们自己写的各种类相关的信息。

本地方法栈

其实在JDK很多底层API里,比如IO相关的,NIO相关的,网络Socket相关的,如果大家去看他内部的源码,会发现很多地方都不是Java代码了。

很多地方都会去走native方法,去调用本地操作系统里面的一些方法,可能调用的都是c语言写的方法,或者一些底层类库,比如下面这样的:

public native int hashCode();

在调用这种native方法的时候,就会有线程对应的本地方法栈,这个里面也是跟Java虚拟机栈类似的,也是存放各种native方法的局部变量表之类的信息。

堆外内存

还有一个区域,是不属于JVM的,通过NIO中的allocateDirect这种API,可以在Java堆外分配内存空间。

然后通过Java虚拟机里的 DirectByteBuffer 来引用和操作堆外内存空间,其实很多技术都会用这种方式,因为有一些场景下,堆外内存分配可以提升性能。

总结

最后做一点总结,我们的Java代码通过JVM来运行的时候,首先一定会一行一行执行编译好的字节码指令。

然后在执行的过程中,对于方法的调用,会通过Java虚拟机栈来为每个方法创建栈帧入栈和出栈,而且栈帧里有方法的局部变量表

接着对于对象的创建,会分配到Java堆内存里去

对于类信息的存储,会放在方法区 / Metaspace这样的区域里。

另外有两块特殊的区域:

  • 本地方法栈,是执行native方法时候用的栈,跟Java虚拟机栈是类似的

  • 堆外内存,是可以在Java堆外分配内存空间来存储一些对象。

转载:

原子弹大侠,阿里P8高级技术专家

经历过每日百亿流量的互联网系统架构,尤其对上亿用户场景下的高并发系统架构设计以及性能优化相关领域有深入的研究。

转载于:https://www.cnblogs.com/technologykai/articles/10869206.html

想要去阿里面试?你必须得跨过 JVM 这道坎!相关推荐

  1. 某百度程序员中午面试一个阿里程序员,晚上去阿里面试,面试官竟是中午那个人!

    世界之大无奇不有,有些巧合简直就是天作之合,就像下面这位百度程序员和阿里程序员的故事. 某百度程序员发帖吐槽:中午面试了一个阿里程序员,问了他一些刁钻的问题,结果自己晚上去阿里面试,面试官竟然就是中午 ...

  2. 某百度程序员中午面试一个阿里程序员,晚上去阿里面试,面试官竟是中午那个人!...

    世界之大无奇不有,有些巧合简直就是天作之合,就像下面这位百度程序员和阿里程序员的故事. 某百度程序员发帖吐槽:中午面试了一个阿里程序员,问了他一些刁钻的问题,结果自己晚上去阿里面试,面试官竟然就是中午 ...

  3. 去阿里面试,面试前20分钟突然要求候选人展示过去的工作方案,候选人拒绝后,竟被取消面试!...

    离职时,你会把自己的工作成果拷贝下来留档吗? 一位网友说: 面试阿里,面试前20分钟,面试官突然要求他展示过去的工作成果,因为之前是用公司电脑,离职时把电脑交上去了,没有任何留档,就拒绝了,结果被通知 ...

  4. 只需 5 分钟看完这篇 HTTPS,去阿里面试和面试官扯皮就没问题了!

    点击上方 好好学java ,选择 星标 公众号 重磅资讯.干货,第一时间送达 今日推荐:牛人 20000 字的 Spring Cloud 总结,太硬核了~ 作者:肖萧 链接:https://segme ...

  5. 只需5分钟看完这篇 HTTPS,去阿里面试和面试官扯皮就没问题了!

    下面我们来一起学习一下 HTTPS ,首先问你一个问题,为什么有了 HTTP 之后,还需要有 HTTPS ?我突然有个想法,为什么我们面试的时候需要回答标准答案呢?为什么我们不说出我们自己的想法和见解 ...

  6. 2021年最新阿里社招面试题合集,能答对90%你就能去阿里面试了!

    前言 Java-社招-3至5年经验 流程 填写资料-笔试-面试-等通知 文章的开始为大家准备了一些Java架构学习资料,学习技术内容包含有:Spring,Dubbo,MyBatis, RPC, 源码分 ...

  7. 去阿里面试Java岗位,一个Spring问题就给干趴下了

    上周公司让我面了个32岁的Java程序员,各方面都挺好,问啥都会,对于Spring问题,答得还行,最后问了个亿级流量Spring的实战题,就答不上来了,走时几乎落泪-唉! 小编这里有一套Spring面 ...

  8. 我从阿里面试回来,想和Java程序猿谈一谈

    最近小编看了一篇关于面试的文章,题目是"我从阿里面试回来,想和Java程序员谈一谈",内容不是讲面试前刷题,而是更加聚焦在面试前如何准备,以及工作当中如何学习.感觉总结的很不错,今 ...

  9. 阿里面试,三面都过了,却被无理由挂了,快来一起吃瓜

    进入互联网大厂一般都是"过五关斩六将",难度堪比西天取经.但当你真正面对这些大厂的面试时,有时候又会被其中的神操作弄的很是蒙圈. 近日,某位Android程序员发帖称,自己去阿里面 ...

最新文章

  1. XenApp / XenDesktop 7.6 初体验五 KEYWORDS
  2. Silverlight 里如何实现隐式样式,ImplicitStyleManager 的实现思想
  3. 【CC精品教程】任务三:CC刺像控点,提交空三,新建重建项目(三维格网、三维点云、DOM和DSM)
  4. C语言Main函数到底有几种,你真的懂吗?
  5. opencv:边缘检测之Laplacian算子思想及实现
  6. zookeeper启动失败的排错 no route to host 防火墙未关闭导致的
  7. 精益标准工时软件VIOOVI:没有标准工时,别谈精益改善!
  8. 手机铃声格式规范,midi格式规范(转)
  9. 表单提交中文时出现乱码的问题
  10. 云计算时代的域名解析
  11. MySQL数据库W版与L版转换_mysql博文总结
  12. 微信支付v3 AEAD_AES_256_GCM解密JS版本代码及验证 javascript
  13. Number Game(数字游戏)
  14. 高级软件工程第四次作业:东理三剑客团队项目
  15. 一个软件公司需要多少前端_自己开发一个app需要多少钱,多少时间
  16. 聚类算法——python实现SOM算法
  17. 2.0 JAVA线性表
  18. 如何使用atom编辑php,安装和使用Atom编辑器
  19. c语言界面 和 cp1h通讯,CP1H与EJ1简易主站通讯.doc
  20. 2014年十一 带小齐 西安-华山-…

热门文章

  1. 吴恩达《机器学习训练秘籍》:7 条关于项目实践的实用建议
  2. 牛!何恺明包揽2项ICCV 2017最佳论文奖!这位高考状元告诉你什么是开挂的人生
  3. 公司规定所有接口都用 POST请求?
  4. 线上出现死锁怎么解决?
  5. Java 处理 Exception 的 9 个最佳实践!
  6. 面试官:你简历中写用过docker,能说说容器和镜像的区别吗?
  7. 开发者说:基于 Nacos 的网关灰度路由和服务权重灰度
  8. 数据项目总结:王者荣耀总决赛预测!
  9. 在非互联网公司?!算法工程师的工作内容及心得建议
  10. 【一周算法实践集训】_【模型构建】_baseline