深入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. Java注解,看完就会用

    一.什么是注解 定义:注解(Annotation),也叫元数据.一种代码级别的说明. 它是JDK1.5及以后版本引入的一个特性,与类.接口.枚举是在同一个层次. 它可以声明在包.类.字段.方法.局部变 ...

  2. ClickHouse的JOIN算法选择逻辑以及auto选项

    ClickHouse的JOIN算法选择逻辑以及auto选项 ClickHouse中的JOIN的算法有6种: Direct; Partial merge; Hash; Grace hash; Full ...

  3. 国产Geoscene Server 4.0编译SOE总结

    背景:公司一直使用Arcgis Server 10.1.Visual Studio 2010开发SOE功能,随着国产化软件发展大趋势,SOE中的各种分析功能,需要升级到Geoscene Server环 ...

  4. Vue 2 和 Vue 3 中 toRefs的区别

    摘要:本文将介绍 Vue 2 和 Vue 3 中 toRefs 函数的不同用法和行为,并解释其在各个版本中的作用. 正文: Vue 是一款流行的 JavaScript 框架,用于构建用户界面.在 Vu ...

  5. Python快速爬取车标网图片,以后不要说这什么车你不认识了!

    知识不分边界...... 人,为什么要读书?举个例子: 当看到天边飞鸟,你会说:"落霞与孤鹜齐飞,秋水共长天一色."而不是:"卧靠,好多鸟."; 当你失恋时你低 ...

  6. 揭开KPI异常检测顶级AI模型面纱

    摘要:2020GDE全球开发者大赛-KPI异常检测告一段落,来自深圳福田莲花街道的"原子弹从入门到精通"有幸取得了总榜TOP1的成绩,在这里跟大家分享深圳福田莲花街道在本次比赛的解 ...

  7. Python 可以满足你任何 API 使用需求

    摘要:在本教程中学到的概念和技术将允许您使用自己喜欢的任何 API 进行练习,并使用 Python 来满足您可能拥有的任何 API 使用需求. 本文分享自华为云社区<Python 和 API:读 ...

  8. 【鲲鹏 DevKit黑科技揭秘】│如何实现全链路系统问题90%精准诊断?

    摘要:DevKit系统诊断工具是鲲鹏性能分析工具的子工具之一,能够针对内存.网络.存储等常见故障和异常,提供精准定位和诊断能力,帮助用户识别出源代码中的问题点,提升程序的可靠性,故障定位准确率高达90 ...

  9. vue2升级vue3:Vue2/3插槽——vue3的jsx组件插槽slot怎么处理

    插槽的作用 让用户可以拓展组件,去更好地复用组件和对其做定制化处理. Vue 实现了一套内容分发的 API,将<slot>元素作为承载分发内容的出口,这是vue文档上的说明.具体来说,sl ...

  10. Mybatis 模块拆份带来的 Mapper 扫描问题

    项目中,两个模块中都放了 Mapper,如下所示 @MapperScan(basePackages ={"com.vipsoft.his.mapper","com.vip ...