深入JVM - Code Cache内存池

1. 本文内容

本文简要介绍JVM的 Code Cache(本地代码缓存池)。

2. Code Cache 简要介绍

简单来说,JVM会将字节码编译为本地机器码,并使用 Code Cache 来保存。
每一个可执行的本地代码块,称为一个 nmethod。
nmethod 可能对应一个完整的Java方法,或者是内联后的方法。

即时编译器(just-in-time,JIT)是代码缓存区的最大消费者,所以此区域又被开发者称为 JIT code cache。

3. 对 Code Cache 进行调优

code cache 区域的大小是固定的。

如果Code Cache区域用满了,就会停止JIT编译, 也就是说JVM不再编译任何代码。
我们还会收到 “CodeCache is full… The compiler has been disabled” 之类的告警消息。
JIT编译器关闭的结果,就是系统性能急剧下降。
为了避免这种情况,我们需要对Code Cache进行调优,例如使用以下参数:

  • InitialCodeCacheSize - 初始大小, 默认值为 160KB
  • ReservedCodeCacheSize - 保留给Code Cache的空间, 也就是最大空间, 默认值: 48MB
  • CodeCacheExpansionSize - 每次扩充的大小, 一般为 32KB 或者 64KB

合理地增加 ReservedCodeCacheSize 是一种解决办法, 毕竟现在很多应用加上依赖库的代码量一点都不少。
但我们也不能无限制地增大这个区域的大小。

幸运的是,JVM提供了一个启动参数 UseCodeCacheFlushing, 用来控制Code Cache的刷新。 这个参数的默认值为 false
如果将其开启(-XX:+UseCodeCacheFlushing),则会在满足以下条件时释放占用的区域:

  • code cache用满; 如果该区域的大小超过某个阈值,则会刷新。
  • 自上次清理后经过了一定的时间间隔。
  • 预编译的代码不够热。 对于每个JIT编译的方法,JVM都会有一个热度跟踪计数器。 如果计数器的值小于动态阈值,则JVM会释放这段预编译的代码。

提示: 除非Code Cache不够用了,否则不要乱开;

4. 查看Code Cache的使用情况

想要监控代码缓存的使用情况,我们可以跟踪当前使用的内存大小。

指定JVM启动参数: -XX:+PrintCodeCache, 会打印Code Cache区的使用情况。
程序执行过程中, 我们可以看到类似下面的输出:

$ java -XX:+PrintCodeCache -XX:+UseCodeCacheFlushing -version

CodeCache: size=245760Kb used=1060Kb max_used=1071Kb free=244699Kb
  • 1
  • 2
  • 3

一起来分析下各个部分数值的含义:

  • size 表示此内存区域的最大值,与 ReservedCodeCacheSize 相等。
  • used 是此区域当前实际使用的内存大小。
  • max_used 是程序启动以来的历史最大使用量
  • free 是此区域尚未使用的空闲空间

PrintCodeCache 选项非常有用,可以帮助我们:

  • 查看何时进行了刷新(flushing)
  • 确定内存使用量是否达到关键点位

5. Code Cache分段

从Java 9开始,JVM将 Code Cache 细分为三个不同的段,每个段包含一种类型的编译代码。
具体是:

  • 非方法段(non-method segment), 保存相关的JVM内部代码,例如字节码解释器。 默认情况下,此段约为 5 MB。 可通过 -XX:NonNMethodCodeHeapSize 参数进行调整。
  • 待分析代码段(profiled-code segment), 包含经过简单优化的代码,使用寿命很短。 此段的大小默认为 122 MB,可以通过 -XX:ProfiledCodeHeapSize 参数进行调整。
  • 静态代码段(non-profiled segment), 保存经过全面优化的本地代码,使用寿命可能很长。 默认大小同样是 122 MB。 可以通过-XX:NonProfiledCodeHeapSize 参数进行调整。

这种新的分段结构,以不同方式处理各种类型的编译代码,整体上具有更好的性能。

例如,将已编译的短命代码和长寿代码分开,提高方法清除器的性能 - 毕竟需要扫描的内存区域变小了。

6. 小结

本文简要介绍了JVM的Code Cache内存区域。

也介绍了一些监视和诊断此内存区使用情况的方法,以及相关的优化和配置选项。

文章知识点与官方知识档案匹配,可进一步学习相关知识
Java技能树首页概览139460 人正在系统学习中

[转帖]深入JVM - Code Cache内存池的更多相关文章

  1. JVM Code Cache空间不足,导致服务性能变慢

    本文阅读时间大约5分钟. 有业务反馈,线上一个应用运行了一段时间之后,在高峰期之后,突然发现处理能力下降,接口的响应时间变长,但是看Cat上的GC数据,一切都很正常. 通过跳板机上机器查看日志,发现一 ...

  2. [转帖]Linux中buff/cache内存占用过高解决办法

    Linux中buff/cache内存占用过高解决办法 https://www.cnblogs.com/rocky-AGE-24/p/7629500.html /proc/sys/vm/drop_cac ...

  3. JVM内存区域详解(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen)

    JVM区域总体分两类,heap区和非heap区.heap区又分为: Eden Space(伊甸园). Survivor Space(幸存者区). Old Gen(老年代). 非heap区又分: Cod ...

  4. JVM虚拟机20:内存区域详解(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen)

    1.内存区域划分 根据我们之前介绍的垃圾收集算法,限定商用虚拟机基本都采用分代收集算法进行垃圾回收.根据对象的生命周期的不同将内存划分为几块,然后根据各块的特点采用最适当的收集算法.大批对象死去.少量 ...

  5. [转帖]JVM—深入理解内存模型与垃圾收集机制

    JVM—深入理解内存模型与垃圾收集机制 https://juejin.im/post/5d68dc9ee51d4561ad6548f7 前言 Java是一种跨平台的语言,当初其设计初衷也是为了解决各个 ...

  6. JVM:查看java内存情况命令

    jmap (linux下特有,也是很常用的一个命令) 观察运行中的jvm物理内存的占用情况. 参数如下: -heap :打印jvm heap的情况 -histo: 打印jvm heap的直方图.其输出 ...

  7. 【JVM】Java内存模型

    原文:多线程之Java内存模型(JMM)(一) 概述 多任务和高并发是衡量一台计算机处理器的能力重要指标之一.一般衡量一个服务器性能的高低好坏,使用每秒事务处理数(Transactions Per S ...

  8. 感悟优化——Netty对JDK缓冲区的内存池零拷贝改造

    NIO中缓冲区是数据传输的基础,JDK通过ByteBuffer实现,Netty框架中并未采用JDK原生的ByteBuffer,而是构造了ByteBuf. ByteBuf对ByteBuffer做了大量的 ...

  9. 基础篇:JVM运行时内存布局

    目录 1 JVM的内存区域布局 2 JVM五大数据区域介绍 3 JVM运行时内存布局和JMM内存模型区别 4 JMM内存模型交互操作 欢迎指正文中错误 关注公众号,一起交流 参考文章 1 JVM的内存 ...

  10. JVM探秘1--JVM内存运行时区域划分

    Java程序员一般不需要太关注内存,因为操作内存的权力都交给了Java虚拟机,但是Java程序员必须需要了解JVM是如何使用内存的,否则一旦内存出现泄漏或事溢出的话,就会一筹莫展不知道从哪去入手排查问 ...

随机推荐

  1. JavaFx之整合JFoenix(十四)

    JavaFx之整合JFoenix JFoenix是JavaFx流行的UI框架之一 github:https://github.com/sshahine/JFoenix 整合Maven <!--h ...

  2. Baby_Step_Gaint_Step(BSGS) 算法

    \(BSGS\) 算法,又称 "北(\(B\))上(\(S\))广(\(G\))深(\(S\))" 算法,"拔山盖世"算法,可以在 \(O(\sqrt{n})\ ...

  3. QRCoder1.4.3生成二维码,不依赖System.Drawing,解决"未能找到类型或命名空间名QRCode","及ImageFormatPng仅在windows上受支持"

    生成二维码1(简单) 包引用: <PackageReference Include="QRCoder" Version="1.4.3" /> usi ...

  4. 用 Socket.D 替代原生 WebSocket 做前端开发

    socket.d.js 是基于 websocket 包装的 socket.d 协议的实现.就是用 ws 传输数据,但功能更强大. 功能 原生 websocket socket.d 说明 listen ...

  5. Deployment控制器

    目录 Deployment控制器 1.deployment及副本数 使用命令生产yaml文件模板 控制器通过什么管理pod? 2.副本数修改方法 3.动态扩展HPA 4.镜像滚动升级及回滚 升级 回退 ...

  6. 作为所有类的顶层父类,没想到Object的魔力如此之大!

    写在开头 在上一篇博文中我们提到了Java面向对象的四大特性,其中谈及"抽象"特性时做了一个引子,引出今天的主人公Object,作为所有类的顶级父类,Object被视为是James ...

  7. 大数据处理黑科技:揭秘PB级数仓GaussDB(DWS) 并行计算技术

    摘要:通过这篇文章,我们了解了GaussDB(DWS)并行计算技术的原理以及调优策略.希望广大开发者朋友们能够在实践中尝试该技术,更好地进行性能优化. 随着硬件系统的越来越好,数据库运行的CPU.磁盘 ...

  8. 云小课 | 一个三分钟快速定制OCR应用的神器,要不?

    摘要:ModelArts Pro提供了文字识别套件,基于丰富的文字识别算法和行业知识积累,帮助客户快速构建满足不同业务场景需求的文字识别服务.三分钟即可快速定制OCR服务,实现多种版式图像的文字信息结 ...

  9. SDK设计与封装:从基础概念入门到架构设计落地笔记

    什么是 SDK? SDK 全称 Software Development Kit,广义上的 SDK 是为特定的软件包.软件框架.硬件平台.操作系统等建立应用程序时所使用的开发工具的集合(在 iOS 项 ...

  10. 用 Java?试试国产轻量的 Solon v1.10.7

    Java 国产的轻量级应用开发框架.可用来快速开发 Java 应用项目.主框架仅 0.1 MB.Helloworld: @Controller public class App { public st ...