深入拆解 Java 虚拟机
郑雨迪
Oracle 高级研究员,计算机博士
87446 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 40 讲
模块四:黑科技 (3讲)
深入拆解 Java 虚拟机
15
15
1.0x
00:00/00:00
登录|注册

01 | Java代码是怎么运行的?

HotSpot采用即时编译提升性能
Java虚拟机划分内存区域,加载class文件到方法区
虚拟机提供托管环境,处理冗长且易出错的部分
Java代码在虚拟机中运行提供了可移植性
即时编译在额外线程中进行,不干扰应用运行
分层编译,热点方法先被C1编译,再由C2编译
HotSpot内置多个即时编译器:C1、C2、Graal
即时编译根据二八定律,优化热点代码
HotSpot采用即时编译提升性能
退出方法时弹出栈帧
调用Java方法时生成栈帧,存放局部变量和字节码操作数
划分内存中的堆、栈、PC寄存器、Java方法栈、本地方法栈
执行方法区内的代码
加载class文件到方法区
虚拟机提供托管环境,处理冗长且易出错的部分
Java字节码可在不同平台上的虚拟机实现上运行
设计虚拟机,将Java程序转换成Java字节码
Java语言复杂,抽象程度高
总结与实践
Java虚拟机的运行效率究竟是怎么样的?
Java虚拟机具体是怎样运行Java字节码的?
为什么Java要在虚拟机里运行?
Java代码是怎么运行的?

该思维导图由 AI 生成,仅供参考

我们学院的一位教授之前去美国开会,入境的时候海关官员就问他:既然你会计算机,那你说说你用的都是什么语言吧?
教授随口就答了个 Java。海关一看是懂行的,也就放行了,边敲章还边说他们上学那会学的是 C+。我还特意去查了下,真有叫 C+ 的语言,但是这里海关官员应该指的是 C++。
事后教授告诉我们,他当时差点就问海关,是否知道 Java 和 C++ 在运行方式上的区别。但是又担心海关官员拿他的问题来考别人,也就没问出口。那么,下次你去美国,不幸地被海关官员问这个问题,你懂得如何回答吗?
作为一名 Java 程序员,你应该知道,Java 代码有很多种不同的运行方式。比如说可以在开发工具中运行,可以双击执行 jar 文件运行,也可以在命令行中运行,甚至可以在网页中运行。当然,这些执行方式都离不开 JRE,也就是 Java 运行时环境。
实际上,JRE 仅包含运行 Java 程序的必需组件,包括 Java 虚拟机以及 Java 核心类库等。我们 Java 程序员经常接触到的 JDK(Java 开发工具包)同样包含了 JRE,并且还附带了一系列开发、诊断工具。
然而,运行 C++ 代码则无需额外的运行时。我们往往把这些代码直接编译成 CPU 所能理解的代码格式,也就是机器码。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

Java虚拟机的运行效率是如何提升的?HotSpot采用了多种技术来提升启动性能以及峰值性能,其中即时编译是其中最重要的技术之一。即时编译建立在程序符合二八定律的假设上,对于占据大部分的不常用的代码,采取解释执行的方式运行;而对于仅占据小部分的热点代码,将其编译成机器码以达到理想的运行速度。HotSpot内置了多个即时编译器:C1、C2和Graal,以满足不同用户场景的需要。HotSpot的即时编译是放在额外的编译线程中进行的,根据CPU的数量设置编译线程的数目,并且按1:2的比例配置给C1及C2编译器。总之,Java代码的运行方式多样,而Java虚拟机的设计使得Java程序具有跨平台性和托管环境,同时在执行过程中采用了多种优化手段来提高效率。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《深入拆解 Java 虚拟机》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(208)

  • 最新
  • 精选
  • jiaobuchongจุ๊บ
    置顶
    对老师写的那段 awk 不懂得可参考: https://blog.csdn.net/jiaobuchong/article/details/83037467
    2018-10-14
    1
    96
  • 小名叫大明
    置顶
    受益匪浅,多谢老师。 请教老师一个问题,网上我没有搜到。 服务器线程数爆满,使用jstack打印线程堆栈信息,想知道是哪类线程数太多,但是堆栈里全是一样的信息且没有任何关键信息,是哪个方法创建的,以及哪个线程池的都看不到。 如何更改打印线程堆栈信息的代码(动态)让其打印线程池信息呢?
    2018-07-26
    5
    49
  • 曲东方
    jvm把boolean当做int来处理 flag = iconst_1 = true awk把stackframe中的flag改为iconst_2 if(flag)比较时ifeq指令做是否为零判断,常数2仍为true,打印输出 if(true == flag)比较时if_cmpne做整数比较,iconst_1是否等于flag,比较失败,不再打印输出

    作者回复: 字节码高手!

    2018-07-20
    10
    426
  • novembersky
    文中提到虚拟机会把部分热点代码编译成机器码,我有个疑问,为什么不把java代码全部编译成机器码?很多服务端应用发布频率不会太频繁,但是对运行时的性能和吞吐量要求较高。如果发布或启动时多花点时间编译,能够带来运行时的持久性能收益,不是很合适么?

    作者回复: 问得好!事实上JVM确实有考虑做AOT (ahead of time compilation) 这种事情。AOT能够在线下将Java字节码编译成机器码,主要是用来解决启动性能不好的问题。 对于这种发布频率不频繁(也就是长时间运行吧?)的程序,其实选择线下编译和即时编译都一样,因为至多一两个小时后该即时编译的都已经编译完成了。另外,即时编译器因为有程序的运行时信息,优化效果更好,也就是说峰值性能更好。

    2018-07-20
    7
    148
  • 1:为什么使用JVM? 1-1:可以轻松实现Java代码的跨平台执行 1-2:JVM提供了一个托管平台,提供内存管理、垃圾回收、编译时动态校验等功能 1-3:使用JVM能够让我们的编程工作更轻松、高效节省公司成本,提示社会化的整体快发效率,我们只关注和业务相关的程序逻辑的编写,其他业务无关但对于编程同样重要的事情交给JVM来处理 2:听完此节的课程的疑惑(之前就没太明白,原期待听完后不再疑惑的) 2-1:Java源代码怎么就经过编译变成了Java字节码? 2-2:JVM怎么就把Java字节码加载进JVM内了?先加载那个类的字节码?它怎么定位的?拿到后怎么解析的?不会整个文件放到一个地方吧?使用的时候又是怎么找到的呢?这些感觉还是黑盒 2-3:JVM将内存区域分成堆和栈,然后又将栈分成pc寄存器、本地方法栈、Java方法栈,有些内存空间是线程可共享的,有些是线程私有的。现在也了解不同的内存区块有不同的用处,不过他们是怎么被划分的哪?为什么是他们,不能再多几种或少几种了吗?共享的内存区和私有的又是怎么控制的哪?

    作者回复: 总结得非常细致! 2-1 其实是这样的,JVM接收字节码,要运行在JVM上只能选择转化为字节码。要是不想在JVM上跑,可以选择直接转化为机器码。 2-2 类加载会在第三篇详细介绍。 2-3 具体的划分都是实现细节。你也可以选择全部冗杂在一起。但是这样子做性能较高,因为线程私有的可以不用同步。

    2018-07-24
    53
  • Ryan-Hou
    在为什么Java要在虚拟机里执行这一节您提到,java语法复杂,抽象度高,直接通过硬件来执行不现实,但是同样作为高级语言为什么C++就可以呢?这个理由作为引入虚拟机这个中间层的原因不是很充分吧

    作者回复: 多谢指出!这里的直接运行指的是不经过任何转换(编译),直接在硬件上跑。即便是C++,也不可以直接运行。 C++的策略是直接编译成目标架构的机器码,Java的策略是编译成一个虚拟架构的机器码。这个虚拟架构可以有物理实现(可以搜Java processor),也可以是软件实现,也就是我们经常接触到的JRE。

    2018-07-20
    3
    41
  • 周仕林
    看到有人说热点代码的区别,在git里面涉及到的热点代码有两种算法,基于采样的热点探测和基于计数器的热点探测。一般采用的都是基于计数器的热点探测,两者的优缺点百度一下就知道了。基于计数器的热点探测又有两个计数器,方法调用计数器,回边计数器,他们在C1和C2又有不同的阈值。😂😂

    作者回复: 谢谢!

    2018-07-23
    2
    38
  • 笨笨蛋
    什么时候使用C1,什么时候使用C2,他是怎么区分热点方法的呢?

    作者回复: 刚刚看到一个同学总结了。JVM会统计每个方法被调用了多少次,超过多少次,那就是热点方法。(还有个循环回边计数器,用来编译热循环的。) 默认的分层编译应该是达到两千调C1,达到一万五调C2。

    2018-07-24
    4
    21
  • 那我懂你意思了
    老师,那个pc寄存器,本地方法栈,以及方法栈,java方法栈这三个组成的就是我们常统称的栈吧,然后也叫栈帧?

    作者回复: JVM里的栈指的应该是Java方法栈和本地方法栈。每个方法调用会在栈上划出一块作为栈帧(stack frame)。栈是由多个栈帧构成的,就好比电影是由一个个帧构成的。

    2018-07-20
    3
    18
  • 踏雪无痕
    您好,我现在所在的项目经常堆外内存占用非常多,超过总内存的70%,请问一下有没有什么方法能观察一下堆外内存有什么内容?

    作者回复: 堆外内存的话,就把JVM当成普通进程来查找内存泄漏。可以看下Google Performance Tools相关资料

    2018-07-20
    16
收起评论
显示
设置
留言
99+
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部