不可不知的 JVM 预热
一、JVM 架构基础
JVM 进程启动时,ClassLoader 会将需要的所有类加载到内存,主要分为以下三步:
- Bootstrap Class: 核心类库,由 “Bootstrap Class Loader”负责加载, 例如基础的运行时类库 JRE\lib\rt.jar。
- Extension Class: java.ext.dirs 路径下的类,由 ExtClassLoader 负责加载。在实际开发中,如果需要添加额外的类库,通常放置于此位置。
- Application Class: 实际应用包含的类,由 AppClassLoader 负责加载。
二、JVM 预热是指什么?
类加载过程完毕后,所有需要的类会进入 JVM cache (native code) ,这样就可以被快速的实时访问。当然,还有许多其它与JVM启动无关的类此时并未被加载。
当应用的第一个请求到来,会触发逻辑相关类的第一次加载,此过程会有一定的耗时,会影响第一次调用的实时响应。这主要是因为JVM的懒加载及JIT机制。因此对于低延迟应用,必须采用特定的策略来处理第一次的预加载逻辑,以保障第一次的请求的快速响应。此过程,我们称之为 JVM 的预热。
三、Tiered Compilation
JVM会将使用频率较高的方法放入本地缓存。以达到快速调用响应的目的。基于此,我们可以通过在应用启动之初,强制加载我们预先认知的高频方法。设置参数包括如下:
-XX:CompileThreshold -XX:TieredCompilation
通常虚拟机会通过解释器来收集反馈到编译器的方法调用信息。
四、自定义实现
基于上一小节所述,我们可以额外实现特定逻辑来进行特定方法的多次调用(-XX:CompileThreshold),以触发JVM的编译。如下示例:
首先,我们定义一个包含基础方法的类:
public class Dummy { public void m() { }
}
其次,我们创建一个加载类,在其内部添加静态方法,循环100000次重复生成Dummy对象,并调用其方法:
public class ManualClassLoader { protected static void load() {
for (int i = 0; i < 100000; i++) {
Dummy dummy = new Dummy();
dummy.m();
}
}
}
现在我们使用如下过程,测试性能:
public class MainApplication { static {
long start = System.nanoTime();
ManualClassLoader.load();
long end = System.nanoTime();
System.out.println("Warm Up time : " + (end - start));
} public static void main(String[] args) {
long start = System.nanoTime();
ManualClassLoader.load();
long end = System.nanoTime();
System.out.println("Total time taken : " + (end - start));
} }
如下为测试结果:
预热之后 |
未预热 |
差别(%) |
1220056 |
8903640 |
730 |
1083797 |
13609530 |
1256 |
1026025 |
9283837 |
905 |
1024047 |
7234871 |
706 |
868782 |
9146180 |
1053 |
预热之后的性能明显好于未预热状态下的调用。
当然,这里只是一个简单的示例测试,具体到实际的应用中,还需要考虑特定的业务逻辑需求。
五、工具
通常用于基准测试,基本使用如下:
依赖 pom.xml:
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>1.19</version>
</dependency> <dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>1.19</version>
</dependency>
maven库连接: Central Maven Repository。
定义预热处理方法,并添加@Benchmark注解:
@Benchmark
public void init() { //code todo }
将需要预热的业务逻辑放置于预热处理方法内。
不可不知的 JVM 预热的更多相关文章
- 这些不可不知的JVM知识,我都用思维导图整理好了
JVM是面试中必问的部分,本文通过思维导图以面向面试的角度整理JVM中不可不知的知识. 先上图: 1.JVM基本概念 1.1.JVM是什么 JVM 的全称是 「Java Virtual Machine ...
- 你可能不知道的jvm的类加载机制
引言:在java代码中,类型的加载.连接与初始化过程都是在程序运行期间完成的. 加载:查找并加载类的二进制数据(class文件加载到内存中) 连接:a 验证:确保被加载类的正确性. b准备:为类的静态 ...
- 《The java.util.concurrent Synchronizer Framework》 JUC同步器框架(AQS框架)原文翻译
一.论文简介 闲来无事,看看源码,发现了一篇JDK作者的论文<The java.util.concurrent Synchronizer Framework>主要描述了作者对Abstrac ...
- 重磅发布:阿里 OpenJDK终于开源啦! 将长期支持版本 Dragonwell
前几天的北京阿里云峰会,阿里巴巴正式宣布对外开源 OpenJDK 长期支持版本 Alibaba Dragonwell.作为 Java 全球管理组织 Java Community Process (JC ...
- Dubbo 源码分析 - 集群容错之 LoadBalance
1.简介 LoadBalance 中文意思为负载均衡,它的职责是将网络请求,或者其他形式的负载"均摊"到不同的机器上.避免集群中部分服务器压力过大,而另一些服务器比较空闲的情况.通 ...
- JUC同步器框架
The java.util.concurrent Synchronizer Framework 前提 AQS(java.util.concurrent.locks.AbstractQueuedSync ...
- 微服务网关哪家强?一文看懂Zuul, Nginx, Spring Cloud, Linkerd性能差异
导语:API Gateway是实现微服务重要的组件之一.面对诸多的开源API Gateway,如何进行选择也是架构师需要关注的焦点.本文作者对几个较大的开源API Gateway进行了压力测试,对 ...
- 一文讲透Dubbo负载均衡之最小活跃数算法
本文是对于Dubbo负载均衡策略之一的最小活跃数算法的详细分析.文中所示源码,没有特别标注的地方均为2.6.0版本. 为什么没有用截止目前的最新的版本号2.7.4.1呢?因为2.6.0这个版本里面有两 ...
- 阿里开源 OpenJDK 发行版 Dragonwell
日有消息显示,阿里将于 21 日重磅发布其 OpenJDK 发行版 Alibaba Dragonwell. 我们知道 OpenJDK 是基于 GPL v2/Classpath Exception 的 ...
随机推荐
- 将插件绑定在某个phase执行,推送镜像
文章目录 将插件绑定在某个phase执行 推送镜像 将插件绑定在某个phase执行 需求:在执行mvn clean package 时,插件自动为构建Docker镜像. 实现:将插件的的goal绑定在 ...
- 1.Centos7修改主机名
1.在CentOS7中,有三种定义的主机名: 静态的(Static hostname):也称为内核主机名,是系统在启动时从/etc/hostname自动初始化的主机名. 瞬态的(Tansient ho ...
- idea中类注释和方法注释的设置
类注释设置 近几年版本的idea在设置类名时从Includes中引用文件,所以只需要在被引用的文件中设置对应注释即可. /** *@className: ${NAME} *@description: ...
- D - Seek the Name, Seek the Fame
The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the l ...
- 【NOIP 2015 D1 T2】信息传递(图论--带权并查集/bfs)
题目:有n个同学(编号为1到n)正在玩一个信息传递的游戏.在游戏里每人都有一个固定的信息传递对象,其中,编号为i的同学的信息传递对象是编号为Ti同学.游戏开始时,每人都只知道自己的生日.之后每一轮中, ...
- 洛谷P3796
题目链接 题意:有n个由小写字母组成的模式串以及一个文本串T.每个模式串可能会在文本串中出现多次.哪些模式串在文本串T中出现的次数最多. 题解:ac自动机模板加强版,开一个数组单独记录各个字符串出现 ...
- Chip Factory HDU - 5536 字典树(删除节点|增加节点)
题意: t组样例,对于每一组样例第一行输入一个n,下面在输入n个数 你需要从这n个数里面找出来三个数(设为x,y,z),找出来(x+y)^z(同样也可以(y+z)^1)的最大值 ("^&qu ...
- Java基础(第一期)
Java基础 1.注释 Java中注释有三种: 单行注释 // 多行注释 /* */ 文本注释(用的较少) /** */ 书写注释是一个非常好的习惯 BAT 平时写代码一定要注意规范 //有趣的代码注 ...
- Centos7 搭建Nginx+rtmp+hls直播推流服务器
1 准备工具 使用yum安装git [root~]# yum -y install git 下载nginx-rtmp-module,官方github地址 // 通过git clone 的方式下载到服务 ...
- C#程序报找不到时区错误
原因:win10电脑里的时区在win7里不全有 解决:将win10时区注册表导出,在win7电脑上安装 时区注册表路径:HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Wi ...