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

 

概述

 

很多人想要到阿里巴巴、美团、京东等互联网大公司去面试,但是现在互联网大厂面试一般都必定会考核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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/251773.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

医学知识图谱一

大纲 知识自动提取技术 医学知识融合 医学知识推理 转载于:https://www.cnblogs.com/quietwalk/p/9000950.html

在一个div里,列表样式图片进行float,实现水平排序

<div class"xiangce"><ul> <li><a href"#"><img src"images/pic4.gif" alt"">产品名称</a></li><li><a href"#"><img src"images/pic4.gif" alt"…

团队开发git使用各种问题

参考:https://www.cnblogs.com/schaepher/p/4933873.html 问题-3:保持github上项目干净&#xff0c;对于在不同机器上运行会不同的文件不予维护(如.idea/workspace.xml) 建议:对于项目输出在项目目录中的文件不予维护 对于IDE自动生成且与项目所在目录有关的文件不予维护 将这些…

filebeat 乱码

查看 文件的类型 [rootelk-node-1 rsyslog] # file 192.168.1.16.log 192.168.1.16.log: Non-ISO extended-ASCII text, with very long lines, with LF, NEL line terminators 如果命令返回结果说明改日志为utf-8&#xff0c;则logstash配置文件中charset设置为UTF-8 如果命令…

团队编程项目代码设计规范(爬取豆瓣电影top250)

基本格式 缩进 使用4个空格进行缩进 行宽 每行代码尽量不超过80个字符 理由&#xff1a; 这在查看side-by-side的diff时很有帮助方便在控制台下查看代码太长可能是设计有缺陷换行 Python支持括号内的换行。这时有两种情况。 第二行缩进到括号的起始处foo long_function_name(v…

程序员的浪漫

程序员的浪漫 马上就到520了&#xff0c;各位小伙伴想好了准备什么礼物送个自己的另一半呢&#xff1f;还没想好的注意啦&#xff01;&#xff01;现在还有机会&#xff0c;今天给大家分享一些程序员的浪漫创意礼物&#xff0c;希望你可以从中找到一些灵感。 One Link&#xff…

14-1 部署项目

1313转载于:https://www.cnblogs.com/ZHONGZHENHUA/p/9011671.html

The listener supports no services

$ lsnrctl start 报错提示: The listener supports no services The command completed successfully 如图所示&#xff1a; 这样启动后远程连接会报错&#xff1a; oracle ORA-12514:TNS:listener does not currently know of service requested in connect descriptor 问题原…

Luogu P2577 [ZJOI2005]午餐

一道贪心类背包DP的好题 首先发现一个十分显然的性质&#xff0c;没有这个性质整道题目都难以下手&#xff1a; 无论两队的顺序如何&#xff0c;总是让吃饭慢的人先排队 这是一个很显然的贪心&#xff0c;因为如果让吃饭慢的排在后面要更多的时间至少没有这样优 因此我们先按吃…

SEO【总结】by 2019年5月

2019独角兽企业重金招聘Python工程师标准>>> 关键点&#xff1a; 1、代码 1.1、seo前端代码&#xff1a;基于Html代码的SEOherf&#xff1a;https://my.oschina.net/u/2862573/blog/3030664 注意的要点&#xff1a; h1&#xff0c;h2的内容很关键 网页的压缩、静态化…

Linux 系统的启动顺序

第一步&#xff1a;加载BIOS当你打开ia计算机的电源&#xff0c;计算机会首先加载计算机主板的BIOS信息&#xff0c;因为它包含了CPU的相关信息&#xff0c;设备启动顺序[安装系统的U盘启动顺序]&#xff0c;内存信息&#xff0c;时钟信息&#xff0c;PnP特性等等&#xff0c; …

Oracle数据库 查看表是否是 索引组织表的方法

1. 最近在工作过程中发现 一个表插入很慢 以为是索引组织表, 所以一直有点纠结 但是发现 产品里面是没有IOT的 于是找了下公司的OCP 问了下 如何查看 就是 user_tables 视图里面的一个字段. 见图: 转载于:https://www.cnblogs.com/jinanxiaolaohu/p/9018037.html

Windows server 2016 搭建RDS服务

计算机的更新换代太快&#xff0c;新购置的计算机没几年便觉得运行速度越来越慢&#xff0c;尤其是在运行一些比较大的应用程序是&#xff0c;用户总是抱怨运行速度太慢或者总是死机等问题。如果要更换新的计算机&#xff0c;又得不到领导的批准&#xff0c;因此对于企业来说&a…

π 的定义(极限)

圆周率&#xff0c;周长&#xff08;2πr&#xff09;与直径&#xff08;2r&#xff09;的比值。在名称上&#xff0c;是通过计算命名的。 1. 刘徽割圆与圆周率 π 通过圆内接正多边形的周长来计算圆周长&#xff0c;是三世纪中期我国魏晋时代的数学家刘徽的光辉思想。 对于圆内…

前端开发浏览器兼容问题

csshack 1234567我很少使用hacker的&#xff0c;可能是个人习惯吧&#xff0c;我不喜欢写的代码IE不兼容&#xff0c;然后用hack来解决。不过hacker还是非常好用的。使用hacker我可以把浏览器分为3类&#xff1a;IE6 &#xff1b;IE7和遨游&#xff1b;其他&#xff08;IE8 chr…

springboot2.0 多数据源整合问题 At least one JPA metamodel must be present!   at

2019独角兽企业重金招聘Python工程师标准>>> 数据源代码&#xff1a; 第一个读取配置文件代码&#xff1a; package com.datasource;import org.apache.ibatis.session.SqlSessionFactory; import org.mybatis.spring.SqlSessionFactoryBean; import org.mybatis.sp…

好书推荐

阿尔花剌子模:代数学. 乔治波利亚:怎样解题:数学思维的新方法. Anany Levitin:算法设计与分析基础.转载于:https://www.cnblogs.com/mtl6906/p/7625290.html

docker实战系列之搭建rabbitmq

1.搜索镜像【注&#xff1a;因为我这里采用的是阿里云镜像加速器,所以我直接在阿里云中搜索相关镜像路径】,点击"详情"查看公网拉取路径 2.拉取镜像 docker pull registry.cn-hangzhou.aliyuncs.com/jc/rabbitmq-3 3.查看拉取的镜像 docker images 4.创建并运行容器【…

【hdu 6038】Function

【Link】:http://codeforces.com/contest/834/problem/C 【Description】 给你两个排列a和b; a排列的长度为n,b排列的长度为m; a∈[0..n-1],b∈[0..m-1]; 然后让你求一个函数f[i]; f[i]的定义域为0..n-1,值域为0..m-1 同时使得对于任意f[i],i∈[0..n-1]; f(i)bf(a[i])成…

树中点对距离(点分治)

题目 给出一棵带边权的树&#xff0c;问有多少对点的距离<Len 分析 这是一道点分治的经典题目&#xff0c;可以给点分治的初学者练手。 点分治&#xff0c;顾名思义就是把每个点分开了处理答案。 假设&#xff0c;目前做到了以x为根的子树。 先求出子树中每个点到根的距离\(…