JVM代码缓存区CodeCache原理及用法解析

2023-11-11

这篇文章主要介绍了JVM代码缓存区CodeCache原理及用法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下

一. CodeCache简介

从字面意思理解就是代码缓存区,它缓存的是JIT(Just in Time)编译器编译的代码,简言之codeCache是存放JIT生成的机器码(native code)。当然JNI(Java本地接口)的机器码也放在codeCache里,不过JIT编译生成的native code占主要部分。

大致在JVM中的分布如下:

大家都知道javac编译器,把java代码编译成class字节码,它和JIT编译器的区别是,javac只是前端编译(有的叫前期编译),jvm是通过执行机器码和底层交互的,这样我们编写的业务代码才能生效。所以还要把字节码class编译成与本地平台相关的机器码,这个过程就是后端编译。

后端编译根据具体的执行方式不同又分为两种:

1.解释执行

一行一行解释成机器码再执行,每次调用时都需要重新逐条解释执行。

2.编译执行(JIT)

将频繁调用的方法或循环体编译成机器码后,进行多层优化,然后缓存到codeCache里,避免重复编译。

两种执行方式的区别很明显,第一种在遇到频繁调用的方法或代码块时执行效率很低,但是解释执行可以节省内存(不存放到codeCache),立即执行。然后当程序运行一段时间后(达到一定的编译次数),编译执行即JIT优化,可以获得更高的执行效率。

所以说二者是相辅相成的。

现在的Java虚拟机这两种方式都包含(通过命令行java -version查看):

// mixed mode 解释+编译
Java HotSpot(TM) 64-Bit Server VM (build 24.80-b11, mixed mode)

其实JIT编译只是一个统称,具体要看jvm是client端还是server端的,不同的端会分为C1,C2编译器,这两种编译器的区别下一篇会讲到,这里先不展开。

二. JIT编译优化

上面讲到了JVM会对频繁使用的代码,即热点代码(Hot Spot Code),达到一定的阈值后会编译成本地平台相关的机器码,并进行各层次的优化,提升执行效率。

热点代码也分两种:

  • 被多次调用的方法

  • 被多次执行的循环体

那阈值如何判断呢?

方法计数器,统计被多次调用的方法次数,该计数器统计的并不是方法被调用的绝对次数,而是在一段时间内方法被调用的次数。server模式下默认是10000次,可以通过-XX:CompileThreshold来设置(client模式一般很少用到,默认是1500)。

回边计数器,统计一个方法中循环体代码执行的绝对次数,在字节码中遇到控制流向后跳转的指令称为回边,主要通过OnStackReplacePercentage设置。

编译后进行优化,JIT的优化有很多种,比如:

  • 针对方法的优化,方法内联

  • 针对多次调用的循环体优化:栈上替换OSR(On-Stack Replace)

  • 无用代码消除

  • 复写传播

  • 逃逸分析

  • 更多JIT优化技术可参考jvm官网介绍

三. codeCache使用注意事项

上面主要讲了codeCache的作用和JIT的关系,codeCache主要是存放JIT编译后的机器代码,codeCache的大小主要是通过下面的参数设置:

  • -XX:InitialCodeCacheSize 设置codeCache初始大小,一般默认是48M

  • -XX:ReservedCodeCacheSize 设置codeCache预留的大小,通常默认是240M

如果codeCache的内存满了会进行回收,但在jdk1.8之前的jvm回收算法有点问题,当codeCache满了之后会导致编译线程无法继续,并且消耗大量CPU导致系统运行变慢,现象就是系统响应增加,如果你也遇到这个问题建议直接升级成jdk8,或者调大codeCache内存。

codeCache的大小设置可以通过-XX:+PrintCodeCache参数查看调整,但这个参数只在JVM停止的时候打印codeCache使用情况,所以如果想实时监控codeCache的使用情况,可以参考如下代码:

package com.javakk;

import java.io.File;
import java.lang.management.ManagementFactory;
import javax.management.MBeanServerConnection;
import javax.management.ObjectName;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXServiceURL;
import com.sun.tools.attach.VirtualMachine;
/**
 * 基于JMX在运行时查看codeCache使用情况
 * @author 公众号:Java老K
 */
public class CodeCacheTest {
  public static void main(String[] args) throws Exception {
    String pid = getPid(); // 先获取java程序的pid
    String codeCache = getCodeCache(pid); // 根据pid获取codeCache的使用情况
    System.out.println(codeCache);
  }

  /**
   * 获取java进程id
   * @return
   */
  public static String getPid(){
    String name = ManagementFactory.getRuntimeMXBean().getName();
    return name.split("@")[0];
  }

  /**
   * 获取java应用的codeCache使用情况
   * @param pid
   * @throws Exception
   */
  public static String getCodeCache(String pid) throws Exception {
    VirtualMachine vm = VirtualMachine.attach(pid);
    JMXConnector connector = null;
    try {
      String addr = "com.sun.management.jmxremote.localConnectorAddress";
      String property= vm.getAgentProperties().getProperty(addr);
      if (property == null) {
        String agent = vm.getSystemProperties().getProperty("java.home")
            + File.separator
            + "lib"
            + File.separator
            + "management-agent.jar";
        vm.loadAgent(agent);
        property = vm.getAgentProperties().getProperty(addr);
      }

      JMXServiceURL url = new JMXServiceURL(property);
      connector = JMXConnectorFactory.connect(url);
      MBeanServerConnection mbeanConn = connector.getMBeanServerConnection();
      ObjectName obj = new ObjectName("java.lang:type=MemoryPool,name=Code Cache");
      return mbeanConn.getAttribute(obj, "Usage").toString();
    } finally {
      if(connector != null) {
        connector.close();
      }
      vm.detach();
    }
  }
}

运行后可以查看contents结果

contents={committed=2555904, init=2555904, max=251658240, used=2395648}

可以看到我本地的codeCahe配置,初始化是2555904,最大为251658240,已使用2395648

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

您可能感兴趣的文章:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

JVM代码缓存区CodeCache原理及用法解析 的相关文章

  • 从 PDF 中提取不可选择的内容

    我正在使用 Apache PDFBox 从 PDF 文件中提取页面 但找不到提取不可选择的内容 文本或图像 的方法 从 PDF 文件中选择内容是没有问题的 请注意 相关 PDF 在复制内容方面没有任何限制 至少从我在文件的 文档限制摘要 中
  • 如何以编程方式检查应用程序是否在调试模式下运行?

    我必须在应用程序中的某个位置确定我的应用程序是在调试模式还是实时模式下运行 是否有任何函数或代码可用于检查 在开 关两种情况下都会返回 true false 如果是这样 请帮助我 提前致谢 从问题中尚不清楚调试模式是否指的是 应用程序是否可
  • JPA 实体中的方法是否允许抛出异常?

    我尝试创建的 Entity 有问题 当尝试使用 OpenJPA 实现在 Eclipse 中测试类时出现问题 我有not尝试过其他人 所以不确定它是否适用于他们 我的测试用例非常简单 因为它创建一个 EntityManagerFactory
  • Android 上的 setTimeOut() 相当于什么?

    我需要等效的代码setTimeOut call function milliseconds 对于安卓 setTimeOut call function milliseconds 您可能想查看定时任务 http developer andro
  • Hamcrest 泛型地狱 #2:iterable With Size 给出错误“不适用于参数”

    在 hamcrest 中 1 3 RC2 没有 JUnit 依赖项 我使用失败iterableWithSize 我有一个 扩展 Iterator参数化为Content像这样EndResult
  • JLabel.setText() 中的换行符

    使用 JLabel setText 时如何插入换行符 我尝试使用 Html 但似乎可以使其适用于 setText 仅适用于 jLabel 的初始声明 最初声明 jlabel 时的方法是 label new JLabel Hello Worl
  • lombok - 多个镜头中的 @Builder 模式

    I use Builder of 龙目岛项目 https github com rzwitserloot lombok 所以考虑我有这个例子 Builder public class Client private Getter Setter
  • 将 Spring Boot 应用程序部署到 Heroku 失败并显示“无效标志:--release -> [帮助 1]”

    当我尝试将代码部署到 Heroku 时 通过git push heroku master 我收到 Maven 错误 remote ERROR Failed to execute goal org apache maven plugins m
  • 用户“root”@“localhost”的访问被拒绝

    我正在尝试从数据库中获取记录 但我面临这个访问被拒绝的问题 我尝试了 Stack Overflow 上提到的其他解决方案 例如向用户授予权限 但没有任何效果 访问数据库的代码 public void service HttpServletR
  • 按位非运算符

    为什么要按位运算 0 打印 1 在二进制中 不是0应该是1 为什么 你实际上很接近 在二进制中 不是0应该是1 是的 当我们谈论一位时 这是绝对正确的 然而 一个int其值为0的实际上是32位全零 将所有 32 个 0 反转为 32 个 1
  • 从外部 clojar 导入/使用资源

    我想做的是将一个大文件 MIDI 声音字体 打包到一个独立的 Maven repo clojar 中 然后能够以编程方式将其拉下来并从单独的项目中使用它 事实证明 这个看似简单的任务比我想象的要复杂 理想的情况是 如果有一种方法可以直接访问
  • 使用 javax.mail 和 CentOS 的邮件服务器

    我有一个 Java 程序 安装在一台旧的 Ubuntu 机器上 并使用 javax mail 发送邮件 然而 那台机器宕机了 我现在在新的 CentOS 机器上运行相同的 Java 应用程序 但是 当我尝试使用 mail smtp host
  • java3d 中的面部着色

    使用java3d 如何不在每个顶点基础上着色 而是在每个面基础上着色 我尝试学习 java3d 但我生成的 Shape3d 看起来并不符合预期 我想用不同的颜色给不同的三角形着色 但我不知道该怎么做 纹理看起来有点大材小用 而且我根本没有掌
  • Java反序列化中避免重复对象

    我有两个列表 list1 和 list2 其中包含对某些对象的引用 其中某些列表条目可能指向同一对象 然后 由于各种原因 我将这些列表序列化为两个单独的文件 最后 当我反序列化列表时 我想确保我不会重新创建超出需要的对象 换句话说 List
  • 在java中设置Process对象的安全性

    有人可以告诉我如何限制通过进程对象访问系统属性吗 如果我通过进程对象运行以下代码 我可以抛出安全异常吗 System getProperty user home 请告诉我如何为流程对象配置证券 在ProcessBuilder类文档中 环境方
  • 对于每个抛出异常的语句,try/catch 是否被视为反模式?

    我目前正在审查同事的 Java 代码 我看到很多情况下 每个可能抛出异常的语句都被封装在自己的 try catch 中 其中 catch 块都执行相同的操作 哪个操作与我的问题无关 对我来说 这似乎是一种代码味道 我记得读到过它是一种常见的
  • Android:如何以编程方式仅圆化位图的顶角?

    我目前正在使用这段代码 Override public Bitmap transform Bitmap source Bitmap result Bitmap createBitmap source getWidth source getH
  • 何时以及为何使用缓冲输入和输出流? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 我读到这些是为了减少磁盘 网络调用开销而使用的 这在写操作的情况下似乎很好 但是进行缓冲读取有什么好处呢 如果您按字节读取文件 则每次都会进
  • 用于将字符串与通配符模式进行匹配的递归函数

    所以我一整天都在试图解决这个作业 只是无法完成 以下函数接受 2 个字符串 第二个 不是第一个 可能包含 的 星号 An 是字符串的替换 空 1个字符或更多 它可以出现 仅在s2中 一次 两次 更多或根本不出现 它不能与另一个相邻 ab c
  • 跳过一行GridBagLayout

    我在 JFrame 上使用 GridBagLayout 我希望能够跳过一两行 但将这些行显示为空白 然后在这些行后面有一个按钮 我在文档中找不到任何方法来执行我所描述的操作 有谁知道我可以执行此操作的任何方法吗 发现它比添加空组件干净得多

随机推荐

  • windows下环境变量配置后没生效,不重启电脑的解决办法

    本篇文章主要讲解windows配置了环境变量但没有生效的原因及不重启电脑的解决办法 作者 任聪聪 配置环境变量后显示命令不存在 找不到 现象如下 主要原因 windows配置完毕环境变量 由于某种原因没有即时的同步更新 这可能是注册表没有即
  • 解决conda无法创建环境

    想用Python36的环境来做另一个项目 结果创建一直报错 试过在命令台创建 在anaconda界面里面创建 在Pycharm里面创建都失败了 后来查询才发现可能是镜像源的问题 报错情况 解决方法 更改在C Users 16340的 con
  • MFC新建内部消息

    提示 记录一下MFC新建内部消息的成功过程 文章目录 前言 一 第一阶段 二 第二阶段 三 第三阶段 总结 前言 先说一下基本情况 因为要在mapview上增加一个显示加载时间的功能 然后发现是要等加载完再显示时间 显示在主窗口 所以就是在
  • Python基础操作真题(三)

    第七套 1 键盘输入正整数s 按要求把s输出到屏幕 格式要求 宽度为25个字符 等号字符 填充 右对齐 带千位分隔符 如果正整数超过25位则按真实长度输出 s input print gt 25 format eval s 2 获得用户输入
  • Shell编程——脚本编写思路与过程

    Linux系统Shell编程 脚本编写思路与过程 前段时间有小伙伴问我一些问题 涉及到shell脚本的编写问题 事后 我深入思考了下 实际生产环境的确也会经常用到 因此如何写这个脚本 它的思路在哪 带这个问题引入今天的文章 仅供参考 如有不
  • python中的输入与输出

    文章目录 python中的输入与输出 1 python中的输入 2 比较两个数值的大小 3 python中的格式化的输出 4 格式化输出的练习 python中的输入与输出 1 python中的输入 python3 x input pytho
  • 权限维持-白银票据

    前言 白银票据是利用域的服务账户进行伪造ST 需要一些服务进行交互 比如cifs 共享文件服务 mysql sqlserver之类的 所以白银票据是没有黄金票据这么好用的 但是比白银票据更加隐藏一些 注 限定域环境 复现 1 收集信息 还是
  • 时序数据和语音处理

    时序数据 时序数据概述 即时间序列数据 用于时序预测 作用 用来连续观察同一对象在不同时间点上获得的数据样本集 处理目标 对给定的时间序列样本 找出统计特性和发展规律性 推测未来值 语音是一类特殊的时序数据 识别语音对应的文本信息是当前人工
  • MySQL基础篇

    目录 MySQL概念 数据库相关概念 MySQL数据库 启动与停止 客户端连接 数据模型 SQL SQL通用语法 SQL分类 DDL 数据库操作 表操作 图形化工具的使用 DataGrip DML DQL DCL 函数 字符串函数 数值函数
  • 函数被声明为已否决

    函数被声明为已否决 尝试这个1 Project Properties gt Configuration Properties gt C C gt General gt SDL checks关掉 我的电脑这个方法可以其他方法 2 pragma
  • 判断数组内容是否相同

    题目 设计一个方法 用于比较两个数组的内容是否相同 思路 1 定义两个数组 分别使用静态初始化完成数组元素的初始化 2 定义一个方法 用于比较两个数组的内容是否相同 3 比较两个数组的内容是否相同 按照下面的步骤实现就可以了 首先比较数组长
  • Ubuntu18.04 Apache2 配置CGI环境 C语言编写

    本人的Ubuntu版本号 18 04 4 LTS 根据其他人的参考资料 这套教程在Ubuntu的16 18 20版本基本上是通用的 1 卸载apache2 没有安装过的话可以跳过这一步 要保留网页文件的话 就不要 rm rf var www
  • corntab定时执行任务

    corntab介绍 cron 这个守护进程是为了周期性执行任务或处理等待事件而存在 任务调度分两种 系统任务调度 用户任务调度 计划任务的安排方式分两种 一种是定时性的 也就是例行 就是每隔一定的周期就要重复执行 一种是突发性的 就是这次做
  • 新建SpringBoot Maven项目中pom常用依赖配置及常用的依赖的介绍

    完整的pom文件放在后面 一 常用的依赖的介绍 1 springboot项目的总 父 依赖大全
  • Java8中List转Map的实现方法

    在Java编程开发中 经常会遇到将List转换为Map的需求 List是一种有序的集合 而Map则是一种键值对的映射关系 在Java8中 我们可以使用Stream API提供的新特性来实现这一转换 Java8中List转Map的实现方法 在
  • C++编译过程详述

    对于编译过程的总结 源于我的一个突然的好奇 编译头文件和编译头文件对应的源文件有没有区别 因为写makefile的时候依赖即可以写头文件 也可以写源文件 在网上查了半天 估计我的这个问题比较stupid 也没有明确的回答 索性顺藤摸瓜看了看
  • 游戏王大师规则3

    自己一年前翻译的老物了 放在这里算是做个存档 1 OCG Official Card Game 概要 1 1 决斗 游戏王ARC V OCG 以下略称 OCG 是原则上供2人游玩的游戏 而且 按 OCG 规则决出一局胜负称为 决斗 OCG
  • 前端Sass样式预处理器详解

    Sass 是一款强化 CSS 的辅助工具 它在 CSS 语法的基础上增加了变量 variables 嵌套 nested rules 混合 mixins 导入 inline imports 等高级功能 这些拓展令 CSS 更加强大与优雅 通过
  • ch04游戏对象与图形基础

    目录 一 加载Fantasy Skybox FREE 构建自己的游戏场景 二 写一个简单的总结 总结游戏对象的使用 三 魔鬼与牧师 动作分离版 1 解决方案 2 主要更新 3 链接 一 加载Fantasy Skybox FREE 构建自己的
  • JVM代码缓存区CodeCache原理及用法解析

    这篇文章主要介绍了JVM代码缓存区CodeCache原理及用法解析 文中通过示例代码介绍的非常详细 对大家的学习或者工作具有一定的参考学习价值 需要的朋友可以参考下 一 CodeCache简介 从字面意思理解就是代码缓存区 它缓存的是JIT