一、JVM 架构基础

JVM 进程启动时,ClassLoader 会将需要的所有类加载到内存,主要分为以下三步:

  • Bootstrap Class: 核心类库,由 “Bootstrap Class Loader”负责加载, 例如基础的运行时类库 JRE\lib\rt.jar
  • Extension Classjava.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 预热的更多相关文章

  1. 这些不可不知的JVM知识,我都用思维导图整理好了

    JVM是面试中必问的部分,本文通过思维导图以面向面试的角度整理JVM中不可不知的知识. 先上图: 1.JVM基本概念 1.1.JVM是什么 JVM 的全称是 「Java Virtual Machine ...

  2. 你可能不知道的jvm的类加载机制

    引言:在java代码中,类型的加载.连接与初始化过程都是在程序运行期间完成的. 加载:查找并加载类的二进制数据(class文件加载到内存中) 连接:a 验证:确保被加载类的正确性. b准备:为类的静态 ...

  3. 《The java.util.concurrent Synchronizer Framework》 JUC同步器框架(AQS框架)原文翻译

    一.论文简介 闲来无事,看看源码,发现了一篇JDK作者的论文<The java.util.concurrent Synchronizer Framework>主要描述了作者对Abstrac ...

  4. 重磅发布:阿里 OpenJDK终于开源啦! 将长期支持版本 Dragonwell

    前几天的北京阿里云峰会,阿里巴巴正式宣布对外开源 OpenJDK 长期支持版本 Alibaba Dragonwell.作为 Java 全球管理组织 Java Community Process (JC ...

  5. Dubbo 源码分析 - 集群容错之 LoadBalance

    1.简介 LoadBalance 中文意思为负载均衡,它的职责是将网络请求,或者其他形式的负载"均摊"到不同的机器上.避免集群中部分服务器压力过大,而另一些服务器比较空闲的情况.通 ...

  6. JUC同步器框架

    The java.util.concurrent Synchronizer Framework 前提 AQS(java.util.concurrent.locks.AbstractQueuedSync ...

  7. 微服务网关哪家强?一文看懂Zuul, Nginx, Spring Cloud, Linkerd性能差异

      导语:API Gateway是实现微服务重要的组件之一.面对诸多的开源API Gateway,如何进行选择也是架构师需要关注的焦点.本文作者对几个较大的开源API Gateway进行了压力测试,对 ...

  8. 一文讲透Dubbo负载均衡之最小活跃数算法

    本文是对于Dubbo负载均衡策略之一的最小活跃数算法的详细分析.文中所示源码,没有特别标注的地方均为2.6.0版本. 为什么没有用截止目前的最新的版本号2.7.4.1呢?因为2.6.0这个版本里面有两 ...

  9. 阿里开源 OpenJDK 发行版 Dragonwell

    日有消息显示,阿里将于 21 日重磅发布其 OpenJDK 发行版 Alibaba Dragonwell. 我们知道 OpenJDK 是基于 GPL v2/Classpath Exception 的 ...

随机推荐

  1. sql 工具类function

    --判断是否为整数 create or replace function is_number(param VARCHAR2) return NUMBER is v_num NUMBER; begin ...

  2. 在 .NET Core Logging中使用 Trace和TraceSource

    本文介绍了在.NET Core中如何在组件设计中使用Trace和TraceSource. 在以下方面会提供一些帮助: 1.你已经为.NET Framework和.NET Core / .NET Sta ...

  3. jdk 安装过程配置环境变量 error 的解决过程

    jdk 安装过程配置环境变量 error 的解决过程 问题背景: 我在安装 jdk 过程中在JAVA_HOME和path中添加路径后, cmd 中输入java 和javac均出现错误,因为之前在 D ...

  4. 【noi 2.6_6046】数据包的调度机制(区间DP)

    题意:给定一个队列延迟值为Di的任务,以任意顺序入栈和出栈,第K个出栈的延迟值为(K-1)*Di.问最小的延迟值. 解法:f[i][l]表示完成以第i个任务开始,长度为l,到第i+l-1个任务的最小延 ...

  5. AtCoder Beginner Contest 179 D - Leaping Tak (DP)

    题意:给你一个数字\(n\)和\(k\)个区间,\(S\)表示所有区间的并的集合,你目前在\(1\),每次可以从集合中选择一个数字向右移动,问有多少种方法从\(1\)走到\(n\). 题解:我们从1开 ...

  6. Educational Codeforces Round 94 (Rated for Div. 2) B. RPG Protagonist (数学)

    题意:你和你的随从去偷剑和战斧,你可以最多可以拿\(p\)重的东西,随从可以拿\(f\)重的东西,总共有\(cnt_{s}\)把剑,\(cnt_{w}\)把战斧,每把剑重\(s\),战斧重\(w\), ...

  7. C#中word导出功能骚操作

    马上过牛年了,先祝大家新年好,身体好,心情好!!! 年前最后写一篇之前项目开发的一个功能,自己根据系统业务,想到的一个解决办法,效率还是不错的,废话不多说,开整!!! 需求:企业填报自己的企业信息到系 ...

  8. C - dlopen dlsym

    -----------------------------------------------------------------------------dlsym------------------ ...

  9. 关于free和delete的使用

    上一篇篇幅太长,这里再区分free和delete的用法. 两个同时存在是有它的原因的,我们前面说过,free是函数,它只释放内存,但不会调用析构函数,如果用free去释放new申请的空间,会因为无法调 ...

  10. springboot(五)Scheduling demo

    在项目开发过程中,经常会使用到定时任务(跑批),springboot默认已经实现了,只需要添加相应的注解就可以实现 在启动类上加入注解,开启定时任务 @SpringBootApplication @E ...