Java 性能调优实战
刘超
前金山软件技术经理
59174 人已学习
新⼈⾸单¥59
登录后,你可以任选4讲全文学习
课程目录
已完结/共 49 讲
开篇词 (1讲)
模块一 · 概述 (2讲)
结束语 (1讲)
Java 性能调优实战
15
15
1.0x
00:00/00:00
登录|注册

21 | 磨刀不误砍柴工:欲知JVM调优先了解JVM内存模型

JVM性能调优方式
对象生命周期管理
JVM的自动内存分配管理
方法执行
初始化阶段
class文件加载、验证、准备、解析
内存分配
内存申请
本地方法栈
虚拟机栈
方法区
程序计数器
思考题
总结
运行原理
内存模型
JVM
性能调优

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

你好,我是刘超。
从今天开始,我将和你一起探讨 Java 虚拟机(JVM)的性能调优。JVM 算是面试中的高频问题了,通常情况下总会有人问到:请你讲解下 JVM 的内存模型,JVM 的性能调优做过吗?

为什么 JVM 在 Java 中如此重要?

首先你应该知道,运行一个 Java 应用程序,我们必须要先安装 JDK 或者 JRE 包。这是因为 Java 应用在编译后会变成字节码,然后通过字节码运行在 JVM 中,而 JVM 是 JRE 的核心组成部分。
JVM 不仅承担了 Java 字节码的分析(JIT compiler)和执行(Runtime),同时也内置了自动内存分配管理机制。这个机制可以大大降低手动分配回收机制可能带来的内存泄露和内存溢出风险,使 Java 开发人员不需要关注每个对象的内存分配以及回收,从而更专注于业务本身。

从了解内存模型开始

JVM 自动内存分配管理机制的好处很多,但实则是把双刃剑。这个机制在提升 Java 开发效率的同时,也容易使 Java 开发人员过度依赖于自动化,弱化对内存的管理能力,这样系统就很容易发生 JVM 的堆内存异常,垃圾回收(GC)的方式不合适以及 GC 次数过于频繁等问题,这些都将直接影响到应用服务的性能。
因此,要进行 JVM 层面的调优,就需要深入了解 JVM 内存分配和回收原理,这样在遇到问题时,我们才能通过日志分析快速地定位问题;也能在系统遇到性能瓶颈时,通过分析 JVM 调优来优化系统性能。这也是整个模块四的重点内容,今天我们就从 JVM 的内存模型学起,为后续的学习打下一个坚实的基础。
确认放弃笔记?
放弃后所记笔记将不保留。
新功能上线,你的历史笔记已初始化为私密笔记,是否一键批量公开?
批量公开的笔记不会为你同步至部落
公开
同步至部落
取消
完成
0/2000
荧光笔
直线
曲线
笔记
复制
AI
  • 深入了解
  • 翻译
    • 英语
    • 中文简体
    • 中文繁体
    • 法语
    • 德语
    • 日语
    • 韩语
    • 俄语
    • 西班牙语
    • 阿拉伯语
  • 解释
  • 总结

本文深入介绍了JVM内存模型的重要性和具体设计,帮助读者快速了解JVM内存模型的关键概念。文章首先强调了JVM在Java中的重要性,然后详细解释了JVM内存模型的具体设计,包括堆、程序计数器、方法区、虚拟机栈和本地方法栈。此外,还介绍了Java6、Java7和Java8版本对永久代和元空间的变化,以及Java8使用元空间替代永久代的原因。通过一个案例,文章还展示了Java代码在JVM中的运行过程,帮助读者更好地理解内存模型中各个区域的职责分工。最后,文章提出了一个思考题,引发读者对JVM内存模型的进一步思考和讨论。整体而言,本文以深入浅出的方式介绍了JVM内存模型,为读者打下了坚实的基础。

仅可试看部分内容,如需阅读全部内容,请付费购买文章所属专栏
《Java 性能调优实战》
新⼈⾸单¥59
立即购买
登录 后留言

全部留言(68)

  • 最新
  • 精选
  • 张学磊
    String a="b"可能创建一个对象或者不创建对象,如果"b"这个字符串在常量池里不存在会在常量池创建一个String对象"b",如果已经存在则a直接reference to这个常量池里的对象; String c= new String("b")至少创建一个对象,也可能两个,因为用到new关键字,会在堆内在创建一个的String对象,它的值是"b"。同时,如果"b"这个字符串在常量池里不存在,会在常量池创建这个一个String对象"b"。

    作者回复: 对的

    2019-07-09
    4
    90
  • Xiao
    老师,这儿其实应该说JVM内存结构更合适!JVM内存模型是一种规范,和JVM内存结构不是一个概念。其次,元空间,在Java8,不是在堆内分配的,它的大小是依赖于本地内存大小!

    作者回复: 感谢Xiao同学的提醒。 我想你说的内存模型应该是指Java内存模型(JMM)吧。这里的JVM内存模型跟Java内存模型是不一样的,这里的JVM内存模型和和内存结构是一个意思。 元空间是分配的本地内存,文中开始描述不清楚(已纠正),但后面有明确说明。

    2019-07-09
    38
  • Liam
    请教一个问题,所以1.8开始,方法区是堆的一部分吗?也即是说,方法区的大小受限于堆

    作者回复: 方法区不是堆的一部分,方法区和堆存在交集。方法区的静态变量和运行时常量池存放在堆中,但类的元信息等还是存放在了本地内存中。

    2019-07-09
    2
    23
  • 夏天39度
    超哥,我可以这样理解吗,方法区只是一个逻辑概念,方法区是包括元空间物理内存和堆内存

    作者回复: 对的

    2019-07-31
    2
    13
  • Gred
    老师,运行时变量应该都在方法区中,从java7开始只有字符串常量池移到堆中而已

    作者回复: 严格来说,是静态常量池和运行时常量池,静态常量池是存放字符串字面量、符号引用以及类和方法的信息,而运行时常量池存放的是运行时一些直接引用。 运行时常量池是在类加载完成之后,将静态常量池中的符号引用值转存到运行时常量池中,类在解析之后,将符号引用替换成直接引用。 这两个常量池在JDK1.7版本之后,就移到堆内存中了,这里指的是物理空间,而逻辑上还是属于方法区(方法区是逻辑分区)。

    2019-08-02
    3
    8
  • 我又不乱来
    String a="b"应该会放在字符串常量池中。 String c= new String("b") 首先应该放在 堆中一份,再在常量池中放一份。但是常量池中有b了。 第一次留言。不知道理解的对不对。超哥

    作者回复: 正确

    2019-07-09
    7
  • 发条橙子 。
    老师,这句话怎么理解 之前永久代的类的元数据存储在了元空间,永久代的静态变量(class static variables)以及运行时常量池(runtime constant pool)则跟 Java7 一样,转移到了堆中。 方法区的一部分是由永久代实现的,永久代主要存储类的静态数据以及运行时常量池并储存在堆内存中。 但是由于容易发生permen内存溢出,后来就发明了元数据空间。那我理解元空间除了存储之前方法区的类信息还包括之前放在永久代中的 静态变量 和 运行时常量池 。 文中为什么说和jdk7一样还是转移到堆中,那不是没有变化么?

    作者回复: 是的,没有变化。

    2019-07-20
    6
  • 尔冬橙
    老师,我看有人说字符串常量池只放引用;那new出来除了堆中会有一个对象,如果字符串常量池没有,也会创建一个,这个对象是在堆中非字符串常量池的地方么

    作者回复: 我们说的常量池一般分为静态常量池和运行时常量池,通常字符串常量是存放的引用是在运行时常量池,而字面量是存在了静态常量池。动态生成的字符串,对象是存放在堆中,如果调用intern方法,会将引用存放在常量池中。

    2019-09-02
    2
    4
  • 黑夜里的猫
    字符串常量不是在java8中已经被放入到堆中了吗,应该不在方法区中了,但是看到老师的图中还在方法区中

    作者回复: 方法区是一个规范,并不是一个物理空间,我们这里说的字符串常量放在堆内存空间中,是指实际的物理空间。

    2019-07-09
    4
  • 东方奇骥
    老师,问一下,1.8静态变量和常量存储在的堆里面,那元空间里是什么?文中说之前永久带类的数据存储在了元空间,不是很理解,

    作者回复: 元空间主要存储类的一些信息,包括方法、字段、类等描述类信息。

    2019-07-12
    3
收起评论
显示
设置
留言
68
收藏
沉浸
阅读
分享
手机端
快捷键
回顶部