[转帖]深入JVM - Code Cache内存池
深入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内存区域。
也介绍了一些监视和诊断此内存区使用情况的方法,以及相关的优化和配置选项。
- 原文链接: https://www.baeldung.com/jvm-code-cache
- GitHub双语对照版: https://github.com/cncounter/translation/tree/master/tiemao_2020/21_jvm-code-cache (路过的小伙伴, 请点小星星Star支持)
[转帖]深入JVM - Code Cache内存池的更多相关文章
- JVM Code Cache空间不足,导致服务性能变慢
本文阅读时间大约5分钟. 有业务反馈,线上一个应用运行了一段时间之后,在高峰期之后,突然发现处理能力下降,接口的响应时间变长,但是看Cat上的GC数据,一切都很正常. 通过跳板机上机器查看日志,发现一 ...
- [转帖]Linux中buff/cache内存占用过高解决办法
Linux中buff/cache内存占用过高解决办法 https://www.cnblogs.com/rocky-AGE-24/p/7629500.html /proc/sys/vm/drop_cac ...
- JVM内存区域详解(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen)
JVM区域总体分两类,heap区和非heap区.heap区又分为: Eden Space(伊甸园). Survivor Space(幸存者区). Old Gen(老年代). 非heap区又分: Cod ...
- JVM虚拟机20:内存区域详解(Eden Space、Survivor Space、Old Gen、Code Cache和Perm Gen)
1.内存区域划分 根据我们之前介绍的垃圾收集算法,限定商用虚拟机基本都采用分代收集算法进行垃圾回收.根据对象的生命周期的不同将内存划分为几块,然后根据各块的特点采用最适当的收集算法.大批对象死去.少量 ...
- [转帖]JVM—深入理解内存模型与垃圾收集机制
JVM—深入理解内存模型与垃圾收集机制 https://juejin.im/post/5d68dc9ee51d4561ad6548f7 前言 Java是一种跨平台的语言,当初其设计初衷也是为了解决各个 ...
- JVM:查看java内存情况命令
jmap (linux下特有,也是很常用的一个命令) 观察运行中的jvm物理内存的占用情况. 参数如下: -heap :打印jvm heap的情况 -histo: 打印jvm heap的直方图.其输出 ...
- 【JVM】Java内存模型
原文:多线程之Java内存模型(JMM)(一) 概述 多任务和高并发是衡量一台计算机处理器的能力重要指标之一.一般衡量一个服务器性能的高低好坏,使用每秒事务处理数(Transactions Per S ...
- 感悟优化——Netty对JDK缓冲区的内存池零拷贝改造
NIO中缓冲区是数据传输的基础,JDK通过ByteBuffer实现,Netty框架中并未采用JDK原生的ByteBuffer,而是构造了ByteBuf. ByteBuf对ByteBuffer做了大量的 ...
- 基础篇:JVM运行时内存布局
目录 1 JVM的内存区域布局 2 JVM五大数据区域介绍 3 JVM运行时内存布局和JMM内存模型区别 4 JMM内存模型交互操作 欢迎指正文中错误 关注公众号,一起交流 参考文章 1 JVM的内存 ...
- JVM探秘1--JVM内存运行时区域划分
Java程序员一般不需要太关注内存,因为操作内存的权力都交给了Java虚拟机,但是Java程序员必须需要了解JVM是如何使用内存的,否则一旦内存出现泄漏或事溢出的话,就会一筹莫展不知道从哪去入手排查问 ...
随机推荐
- 从零玩转设计模式之单例模式-danlimos
title: 从零玩转设计模式之单例模式 date: 2022-12-12 12:41:03.604 updated: 2022-12-23 15:35:29.0 url: https://www.y ...
- Lean大神编译的OpenWRT问题汇总
1.初始密码为password,登录路由器后第一件事要修改默认密码 2.Lean大神编译的OpenWRT无法SSH.SFTP, 3.为了方便操作,一定要编译的时候安装TTYD,但是TTYD默认无法打开 ...
- libGDX游戏开发之菜单界面(四)
libGDX游戏开发之菜单界面(四) libGDX系列,游戏开发有unity3D巴拉巴拉的,为啥还用java开发?因为我是Java程序员emm-国内用libgdx比较少,多数情况需要去官网和googl ...
- quill富文本编辑器quill粘贴图片上传服务器
强大的富文本编辑器:quill github:32k start++,:https://github.com/quilljs/quill quill粘贴图片上传服务器 <link href=&q ...
- AI与低代码解锁无限可能
前言 近年来,人工智能(AI)和低代码开发技术逐渐成为数字化转型的重要推动力.AI作为一项具有革命性潜力的技术,正在改变我们生活的方方面面.而低代码开发则提供了一种快速构建应用程序的方法,使得开发者无 ...
- 为什么匿名内部类可以实例化并实现抽象方法?lambda表达式是简化了匿名内部类的实现过程吗?
为什么匿名内部类可以实例化并实现抽象方法? 在Java中,接口是一种特殊的抽象类型,它只定义了一个或多个抽象方法.接口不能被实例化,但是我们可以使用匿名内部类来实现接口并创建一个具体的对象. 匿名内部 ...
- linux 只查看 java 进程
top $(ps -e | grep java | awk '{print $1}' | sed 's/^/-p/')
- ThreadPoolExecutor 线程执行超时,释放线程
如果线程中的执行时间过长,导致长时间被占用,可以通过新建一个子线程,来监控主线程的执行超时时间,如果超时了,通过子线程杀掉父线程 (主意,父线程被杀后,子线程还会活着) 子线程杀掉主线程 这个问题其实 ...
- 从 Rancher 学习 K8s - Rancher 的基础使用
舞台环境 Rancher v2.6.9 K8s v1.24.16 如果你不具备该环境,可以移步 使用 Rancher 安装 K8s 集群 查看.本文适合已经了解了 k8s 基础概念,想使用 ranch ...
- 【Django drf】序列化器总结
目录 序列化器字段 外键字段自定义序列化 在模型类中写方法 在序列化类中写方法 反序列化 外键字段反序列化保存 ModelSerializer使用总结 序列化器字段 序列化中的字段可以根据用途分为三种 ...