一、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. codeblocks下载安装及快捷键

    100MB的下载链接:自带mingw  http://pan.baidu.com/s/1o6BgFP4  13.12版本  gcc 4.7.1的 这是windows版本的 linux下编译安装:参考: ...

  2. MySQL特殊字符的转义处理

    出现问题以及问题分析 这条语句会把user_name不为空的所有记录查询出来 select * from user where user_name like concat('%','_','%') 分 ...

  3. P4587 [FJOI2016]神秘数(主席树)

    题意:给出1e5个数 查询l,r区间内第一个不能被表示的数 比如1,2,4可以用子集的和表示出[1,7] 所以第一个不能被表示的是8 题解:先考虑暴力的做法 把这个区间内的数字按从小到大排序后 从前往 ...

  4. HDU6532 Chessboard (最大费用流)

    题意:棋盘上有n个棋子 每个棋子都有收益 现在给定1e5条线 有横着的 竖着的 规定只能在线的一侧选最多ki个棋子 问最大收益 题解:写自闭的一道题 很容易想到是网络流 但是建图有点难 第一道最大费用 ...

  5. 【poj 1988】Cube Stacking(图论--带权并查集)

    题意:有N个方块,M个操作{"C x":查询方块x上的方块数:"M x y":移动方块x所在的整个方块堆到方块y所在的整个方块堆之上}.输出相应的答案. 解法: ...

  6. python对csv文件读写的两种方式 和 读写文件编码问题处理

    ''' 如果文件读取数据出错,可以考虑加一个encoding属性,取值可以是:utf-8,gbk,gb18030 或者加一个属性error,取值为ignore,例如 open(path, encodi ...

  7. 二叉树增删改查 && 程序实现

    二叉排序树定义 一棵空树,或者是具有下列性质的二叉树:(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值:(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值:(3)左.右子树也 ...

  8. C# 异常重试策略

    using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...

  9. .net面试--值类型和引用类型

    注:下面的示意图主要是为了辅助理解,不代表内存真实情况. Introduction 类型基础是C#的基础概念,了解类型基础及背后的工作原理更有助于我们在编码的时候明白数据在内存中的分配与传递.C#提供 ...

  10. CQRS+Event Sourcing

    using System; using System.Collections.Generic; using System.Linq; namespace CQRS { public class Eve ...