详解Java使用JMH进行基准性能测试
目录
- 一、前言
- 二、JMH概述
- 1、什么是JMH
- 2、JMH适用的典型场景
- 3、JMH基本概念
- 三、JMH的使用
- 1、快速跑起来
- 2、JMH常用注解详细介绍
- 四、小结
- 附:
一、前言
在日常开发工作当中,开发人员可能有这些困惑:自己写的这个方法性能到底怎么样?在原接口实现方法中添加了新的业务逻辑,对整个接口的性能影响有多少?有多种实现方式(或开源类库),到底哪一种性能更好?…
当遇到类似困惑或者说问题的时候,怎么办呢?当然是测试验证,实践出真知!本文讲述的就是一个方法级别的性能测试工具——JMH。
二、JMH概述
1、什么是JMH
??JMH,即Java Microbenchmark Harness,是专门用于代码微基准测试的工具套件。何谓Micro Benchmark呢?简单的来说就是基于方法层面的基准测试,精度可以达到微秒级。其由Oracle/openjdk内部开发JIT编译器的大佬们所开发,作为java的方法级性能测试工具可以说是根正苗红了。(官方地址:http://hg.openjdk.java.net/code-tools/jmh/ )
2、JMH适用的典型场景
??a、优化热点方法,准确的知道某个方法的执行耗时,以及不同入参与最终实际耗时的关系,从而针对性的进行优化;
??b、寻找最佳方案,验证接口方法不同实现方式的实际吞吐量,从而确定最佳实现方式 。如:选择json转换工具时选fastjson还是gson、字符串连接使用StringBuilder方式还是直接相加;
??c、分析性能损耗,在原接口方法业务逻辑中添加新的业务代码时,对整个业务方法的性能影响。如:在原业务逻辑中,添加一个插入操作日志的操作,可以分析新加操作对整个业务方法的性能影响。
??d、分析百分比内的耗时,即测试方法多次调用时百分比区间内的耗时,如:测试调用某个方法,50%以内的调用耗时是8.2ms/op,90%以内是9.3ms/op,99.99%以内是10.2ms/op,等等。(模式为Mode.SampleTime)
3、JMH基本概念
??a、Mode :表示JMH测试中的模式,默认有5种,分别是Throughput(吞吐量)、AverageTime(平均耗时)、SampleTime(随机采样)、SingleShotTime(单次执行)、All(以上4种都来一次);
??b、Fork:表示JMH将用来测试的进程数;
??c、Warmup : 表示预热,在HotSpot中,JVM的JIT编译器会对热点代码进行编译优化, 因此为了最接近真实的情况,需要先预热测试代码,使JIT编译器完成可能需要的优化,从而令JMH最终测试结果更加准确;
??d、Iteration :表示JMH中的最小测试迭代单位,即测试次数,一般默认值是每次1s;
??e、Benchmark:用于标注JMH将进行测试的方法。(类似Junit中的@Test注解)
三、JMH的使用
1、快速跑起来
??JMH的基本使用只需2步,第1步是引入maven依赖包,第2步是根据工具框架模板编写测试类,以下通过一个简单例子进行详细说明:
例1:测试一个方法的平均耗时
第1步:引入maven依赖: (笔者使用的jmh版本为1.21)
org.openjdk.jmh jmh-core${jmh.version} org.openjdk.jmh jmh-generator-annprocess${jmh.version} provided
第2步:编写测试方法:
package com.xiaojiang; import org.openjdk.jmh.annotations.Benchmark; import org.openjdk.jmh.annotations.BenchmarkMode; import org.openjdk.jmh.annotations.Mode; import org.openjdk.jmh.annotations.OutputTimeUnit; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import java.util.concurrent.TimeUnit; /** * @ Description:jmh使用第一个例子 * @ Author:xiaojiang * @ Date:Created in 2019-06-19 * @ Version:0.0.1 */@OutputTimeUnit(TimeUnit.MILLISECONDS)@BenchmarkMode(Mode.AverageTime)public class JmhDemoOne {public static void main(String[] args) throws Exception{Options options = new OptionsBuilder().include(JmhDemoOne.class.getName()).build(); new Runner(options).run(); }/*** 测试sayHello的平局耗时** @throws Exception*/@Benchmarkpublic void sayHello() throws Exception{//TODO 业务方法 ,此处用休眠的方式模拟业务耗时10 msTimeUnit.MILLISECONDS.sleep(10); }}
代码说明:
通过以上例子可以发现,一个基本的JMH测试实现其实并不是很复杂,非常类似于用Junit做单元测试。具体说明如下:
??a、类名JmhDemoOne 上的@OutputTimeUnit、@BenchmarkMode这两个注解,表明这是一个JMH的测试类;(具体注解含义 ,以及更多注解说明请参考下文JMH常用注解详细介绍)
??b、主函数入口main方法中指定了一些基本测试参数选项;(基本就是固定写法。其实有更多相关参数方法可以添加,但这些参数笔者建议通过注解的方式在类上直接添加,这样来的更加方便)
??c、通过@Benchmark注解标注需要benchmark(基准测试)的具体方法;
直接运行测试方法,控制台输出测试结果如下:(笔者JDK版本为1.8,IDE工具为IDEA2018)
# JMH version: 1.21# VM version: JDK 1.8.0_144, Java HotSpot(TM) 64-Bit Server VM, 25.144-b01# VM invoker: D:\Java\jdk1.8.0_144\jre\bin\java.exe# VM options: -javaagent:D:\Program Files\JetBrains\IntelliJ IDEA 2018.2.5\lib\idea_rt.jar=55987:D:\Program Files\JetBrains\IntelliJ IDEA 2018.2.5\bin -Dfile.encoding=UTF-8# Warmup: 5 iterations, 10 s each# Measurement: 5 iterations, 10 s each# Timeout: 10 min per iteration# Threads: 1 thread, will synchronize iterations# Benchmark mode: Average time, time/op# Benchmark: com.xiaojiang.JmhDemoOne.sayHello# Run progress: 0.00% complete, ETA 00:08:20# Fork: 1 of 5# Warmup Iteration1: 10.716 ms/op# Warmup Iteration2: 10.640 ms/op# Warmup Iteration3: 10.737 ms/op# Warmup Iteration4: 10.693 ms/op# Warmup Iteration5: 10.723 ms/opIteration1: 10.716 ms/opIteration2: 10.724 ms/opIteration3: 10.772 ms/opIteration4: 10.758 ms/opIteration5: 10.709 ms/op# Run progress: 20.00% complete, ETA 00:06:43# Fork: 2 of 5# Warmup Iteration1: 10.744 ms/op# Warmup Iteration2: 10.732 ms/op# Warmup Iteration3: 10.748 ms/op# Warmup Iteration4: 10.728 ms/op# Warmup Iteration5: 10.760 ms/opIteration1: 10.701 ms/opIteration2: 10.709 ms/opIteration3: 10.719 ms/opIteration4: 10.714 ms/opIteration5: 10.703 ms/op# Run progress: 40.00% complete, ETA 00:05:02# Fork: 3 of 5# Warmup Iteration1: 10.729 ms/op# Warmup Iteration2: 10.731 ms/op# Warmup Iteration3: 10.728 ms/op# Warmup Iteration4: 10.700 ms/op# Warmup Iteration5: 10.709 ms/opIteration1: 10.708 ms/opIteration2: 10.701 ms/opIteration3: 10.708 ms/opIteration4: 10.726 ms/opIteration5: 10.698 ms/op# Run progress: 60.00% complete, ETA 00:03:21# Fork: 4 of 5# Warmup Iteration1: 10.724 ms/op# Warmup Iteration2: 10.688 ms/op# Warmup Iteration3: 10.748 ms/op# Warmup Iteration4: 10.732 ms/op# Warmup Iteration5: 10.772 ms/opIteration1: 10.729 ms/opIteration2: 10.688 ms/opIteration3: 10.705 ms/opIteration4: 10.687 ms/opIteration5: 10.709 ms/op# Run progress: 80.00% complete, ETA 00:01:40# Fork: 5 of 5# Warmup Iteration1: 10.688 ms/op# Warmup Iteration2: 10.696 ms/op# Warmup Iteration3: 10.692 ms/op# Warmup Iteration4: 10.684 ms/op# Warmup Iteration5: 10.683 ms/opIteration1: 10.719 ms/opIteration2: 10.720 ms/opIteration3: 10.695 ms/opIteration4: 10.710 ms/opIteration5: 10.760 ms/opResult "com.xiaojiang.JmhDemoOne.sayHello":10.716 ±(99.9%) 0.016 ms/op [Average](min, avg, max) = (10.687, 10.716, 10.772), stdev = 0.021CI (99.9%): [10.700, 10.731] (assumes normal distribution)# Run complete. Total time: 00:08:24REMEMBER: The numbers below are just data. To gain reusable insights, you need to follow up onwhy the numbers are the way they are. Use profilers (see -prof, -lprof), design factorialexperiments, perform baseline and negative tests that provide experimental control, make surethe benchmarking environment is safe on JVM/OS/HW level, ask for reviews from the domain experts.Do not assume the numbers tell you what you want them to tell.BenchmarkModeCntScoreErrorUnitsJmhDemoOne.sayHelloavgt2510.716 ± 0.016ms/opProcess finished with exit code 0
测试结果说明:
整个测试结果分为3大块,测试基本参数信息、测试过程、测试结果,各行含义具体说明如下:
块 | 说明 |
---|---|
参数信息(1-10行) | 1:jmh版本 2:jvm版本信息 3:jvm程序(jdk安装路径) 4:jvm参数配置 5:预热参数:预热次数、每次持续时间 6:测试参数:测试次数、每次持续时间 7:每次测试迭代超时时间 8:每个测试进程的测试线程数 9: 测试的模式 10:测试的方法 |
测试过程(12-75行) | 12-23:第1次fork测试 (fork可以理解为1个独立的进程) 12:测试完成进度,预计剩余需要时间 13:当前第几次fork 14-18:预热执行,每次预热执行耗时 19-23:正式测试执行,每次测试执行耗时 25-36:第2次fork测试 38-49:第3次fork测试 51-62:第4次fork测试 64-75:第5次fork测试 |
测试结果(78-95行) | 78-81:测试结果,包括测试的方法、平均耗时[平局耗时的比例]、最大最小 耗时、测试结果数据离散度(stdev)等 84:测试总耗时 86-90:对测试结果的解释 92-93:测试结论{测试的方法、测试类型(Mode)、测试总次数(Cnt)、测试结果(Score)、误差(Error)、单位(Units)} 95:结束 |
注:
??a、测试结果中的Measurement、Fork、Warmup等参数,是JMH采用了默认的配置值,实际使用中,我们可根据需要指定相关参数。
??b、运行这个测试类可以在IDEA中直接跑,也可以打成 jar 包到服务器上跑。
??c、本测试结果是直接输出在控制台,如有需要,可将测试结果输出到文件中,方法是在options中添加output方法指定测试结果输出目录,如下:
Options options = new OptionsBuilder().include(JmhDemoOne.class.getName()).output("D:/JmhDemoOne.log")//将测试结果输出到指定目录文件.build();
2、JMH常用注解详细介绍
注解 | 介绍 |
---|---|
@BenchmarkMode | 基准测试模式。一共有5种可选值:(其实是4种) Mode.Throughput:吞吐量模式,即单位时间内方法的吞吐量 Mode.AverageTime:平均耗时模式,即一定测试次数内方法执行的平均耗时 Mode.SampleTime:随机采样模式,即最终结果为取样结果分布比例 Mode.SingleShotTime:单次执行模式,即只会执行一次(以上的模式通常会有预热、会迭代执行多次,这个模式可用于测试某些特定场景,如冷启动时的性能) Mode.All:即以上模式都执行一遍 ----------------------------------- 用法示例:(benchmark模式为平均耗时模式) @BenchmarkMode(Mode.AverageTime) |
@OutputTimeUnit | 测试结果的时间单位。其值为java.util.concurrent.TimeUnit 枚举中的值,通常用的值是秒、毫秒、微妙(需要注意的是,在不同测试模式下,需要选择合适的时间单位,从而获取更精确的测试结果。) ------------------------------------ 用法示例:(benchmark结果时间单位为毫秒) @OutputTimeUnit(TimeUnit.MILLISECONDS) |
@Benchmark | 基准测试,方法级注解(配置在方法名上)。用于标注需要进行benchmark (基准测试)的方法 ------------------------------------ 用法示例:(方法需要benchmark) @Benchmark |
@Warmup | 预热参数。配置预热的相关参数,参数含义是:iterations(预热次数)、time (预热时间)、timeUnit (时间单位) ------------------------------------ 用法示例:(预热10次,每次20s) @Warmup(iterations = 10, time = 20, timeUnit = TimeUnit.SECONDS) |
@Measurement | 度量,即benchmark基本参数。参数含义是:iterations(测试次数)、time (每次测试时间)、timeUnit (时间单位) ------------------------------------ 用法示例:(测试5次,每次30s) @Measurement(iterations = 5, time = 30, timeUnit = TimeUnit.SECONDS) |
@Fork | 分叉,即进程数。用于配置将使用多少个进程进行测试 ------------------------------------ 用法示例:(使用3个进程) @Fork(3) |
@Threads | 线程数。每个Fork(进程)中的线程数,一般可设为测试机器cpu核心数。 ------------------------------------ 用法示例:(使用4个线程) @Threads(4) |
@Param | 成员参数,属性级注解。用于测试方法在不同入参情况下的性能表现。 ------------------------------------ 用法示例:(入参值依次为1 、10、100) @Param({“1”, “10”, “100”}) |
@Setup | 设置,方法级注解。用于标注benchmark前的操作,通常用于测试前初始化参数资源,如初始化数据库连接等。 ------------------------------------ 用法示例:(初始化方法) @Setup |
@TearDown | 拆卸,方法级注解。用于标注benchmark后的操作,通常用于测试后回收资源,如关闭数据库连接等。 ------------------------------------ 用法示例:(回收方法) @TearDown |
@State | 状态,表示一个类/方法的可用范围,其值有3个: Scope.Thread:默认状态,每个线程分配一个独享的实例; Scope.Benchmark:测试中的所有线程共享实例;(多线程测试情况下) Scope.Group:同一个组的线程共享实例; ------------------------------------ 用法示例:(默认值,每个线程分配一个实例) @State(Scope.Thread) |
@Group | 测试组,方法级注解。适用分组测试,每组线程数不一样的场景。 ------------------------------------ 用法示例:(组名为“group_name”的一个组) @Group(“group_name”) |
@GroupThreads | 组线程数,方法级注解。通常和@Group搭配使用 ------------------------------------ 用法示例:(组线程数为10) @GroupThreads(10) |
@Timeout | 超时时间。每次测试迭代超时时间 ------------------------------------ 用法示例:(每次测试超时时间为20min) @Timeout(time = 20, timeUnit = TimeUnit.MINUTES) |
以上是使用JMH测试中常用的注解,当然JMH还有一些其它注解,如@CompilerControl、@AuxCounters 等等,这些注解通常可用于满足特定的测试场景需求,具体相关使用如有需要,可参考官方示例,官方demo比较详细,比较好理解学习。
3、更多示例
本小节笔者将通过几个小示例,展示JMH的基本使用。
例2:
测试验证字符串连接处理时,使用StringBuilder方式是否比直接相加好。
package com.xiaojiang; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import java.util.concurrent.TimeUnit; /** * @ Description:jmh使用第二个例子 * @ Author:xiaojiang * @ Date:Created in 2019-06-19 * @ Version:0.0.1 */@OutputTimeUnit(TimeUnit.SECONDS)@BenchmarkMode(Mode.Throughput)@Warmup(iterations = 5, time = 1, timeUnit = TimeUnit.MILLISECONDS)@Measurement(iterations = 10, time = 5, timeUnit = TimeUnit.SECONDS)@State(Scope.Thread)public class JmhDemoTwo {public static void main(String[] args) throws Exception{Options options = new OptionsBuilder().include(JmhDemoTwo.class.getName()).build(); new Runner(options).run(); }/*** 字符串个数*/@Param({"10", "100", "1000"})private int number; /*** 字符串直接相加方式*/@Benchmarkpublic void StringAddMode(){String str = ""; for(int i=0; i
测试结果:
//---省略测试过程结果----------【详解Java使用JMH进行基准性能测试】从测试结果可以看出,在字符串连接数量分别为10、100、1000时,通过StringBuilder处理字符串的方式比直接相加的方式性能都要强一些;如,当字符窜数量为1000时,直接相加方式的方法吞吐量为4023.846 ops/s,StringBuilder的方式方法吞吐量达到 98367.745ops/s 。(当然具体测试结果值和机器配置、JVM配置有关)
Benchmark(number)ModeCntScoreErrorUnits
JmhDemoTwo.StringAddMode10thrpt507670608.558 ±99068.181ops/s
JmhDemoTwo.StringAddMode100thrpt50437133.436 ±7738.031ops/s
JmhDemoTwo.StringAddMode1000thrpt504023.846 ±62.872ops/s
JmhDemoTwo.StringBuilderMode10thrpt5022608867.036 ± 669332.843ops/s
JmhDemoTwo.StringBuilderMode100thrpt501232847.661 ±23742.088ops/s
JmhDemoTwo.StringBuilderMode1000thrpt5098367.745 ±1487.840ops/s
例3:
测试常用序列化json库fastJson、gson、jackson的性能(均为截止2019.06最新版本)。
package com.xiaojiang; import org.openjdk.jmh.annotations.*; import org.openjdk.jmh.runner.Runner; import org.openjdk.jmh.runner.options.Options; import org.openjdk.jmh.runner.options.OptionsBuilder; import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; /** * @ Description:jmh使用第三个例子 * @ Author:xiaojiang * @ Date:Created in 2019-06-19 * @ Version:0.0.1 */@OutputTimeUnit(TimeUnit.MILLISECONDS)@BenchmarkMode(Mode.SingleShotTime)@Warmup(iterations = 5)@Measurement(iterations = 1)@State(Scope.Benchmark)@Fork(1)public class JmhDemoThree {public static void main(String[] args) throws Exception{Options options = new OptionsBuilder().include(JmhDemoThree.class.getName()).build(); new Runner(options).run(); }/*** 序列化次数*/@Param({"100", "10000", "1000000"})private int number; private Userinfo userinfo; private String fastjson_jsonStr; private String gson_jsonStr; private String jackson_jsonStr; /***fastjson bean2Json*/@Benchmarkpublic void fastjson_bean2Json(){for (int i=0; i(); list.add("北京三里屯儿那条街那条巷那一号"); list.add("上海三里屯儿那条街那条巷那一号"); list.add("深圳三里屯儿那条街那条巷那一号"); userinfo.setAddress(list); fastjson_jsonStr = JsonUtil.fastjson_bean2Json(userinfo); gson_jsonStr = JsonUtil.gson_bean2Json(userinfo); jackson_jsonStr = JsonUtil.jackson_bean2Json(userinfo); }}
(其它相关代码后附)
测试结果:
//---省略测试过程结果----------从测试结果可以看出,不论是bean2Json还是json2Bean,fastjson的性能比gson、jackson都要好一些,当然,jackson性能也很不错(不愧是spring默认的序列化和反序列化工具),尤其是当序列化与反序列化次数较多时,fastjson优势尤其明显。当然,由于笔者用于测试的实体bean数据结构还是较为简单,在一些较为复杂的数据结构场景下,其各自的性能表现可能有所不一样。(笔者用的测试Mode是Mode.SingleShotTime,只测试一次,且由于机器等原因,所以误差可能相对较大。有兴趣的读者,可以测试一下不同测试Mode下,更复杂的数据结构场景下,各序列化/反序列化工具的性能表现)
Benchmark(number)ModeCntScoreErrorUnits
JmhDemoThree.fastjson_bean2Json100ss1.586ms/op
JmhDemoThree.fastjson_bean2Json10000ss3.683ms/op
JmhDemoThree.fastjson_bean2Json1000000ss500.924ms/op
JmhDemoThree.fastjson_json2Bean100ss0.978ms/op
JmhDemoThree.fastjson_json2Bean10000ss5.493ms/op
JmhDemoThree.fastjson_json2Bean1000000ss362.337ms/op
JmhDemoThree.gson_bean2Json100ss2.106ms/op
JmhDemoThree.gson_bean2Json10000ss28.693ms/op
JmhDemoThree.gson_bean2Json1000000ss1890.999ms/op
JmhDemoThree.gson_json2Bean100ss7.175ms/op
JmhDemoThree.gson_json2Bean10000ss110.298ms/op
JmhDemoThree.gson_json2Bean1000000ss7310.555ms/op
JmhDemoThree.jackson_bean2Json100ss2.111ms/op
JmhDemoThree.jackson_bean2Json10000ss8.859ms/op
JmhDemoThree.jackson_bean2Json1000000ss376.587ms/op
JmhDemoThree.jackson_json2Bean100ss1.992ms/op
JmhDemoThree.jackson_json2Bean10000ss10.723ms/op
JmhDemoThree.jackson_json2Bean1000000ss714.569ms/op
四、小结
1、JMH官方并没有提供比较详细的使用文档(这也是笔者整理本文的重要原因),但是其提供了许多详细、较容易理解的例子,有问题的可以参考,地址为:http://hg.openjdk.java.net/code-tools/jmh/file/99d7b73cf1e3/jmh-samples/src/main/java/org/openjdk/jmh/samples 。
2、JMH中的参数配置,许多参数可以直接在main方法的options中设置,也可以通过在类上直接添加注解配置。
3、注意:跑测试的时候要直接用run的方式跑,不要用debug的方式跑,否则会出错。
4、JMH适用于方法级别的基准性能测试,并不适用于跨系统、跨服务之间的全链路测试。
5、使用JMH基准测试,虽然精度可以达到微妙级,但是测试结果依然是会存在一定误差的;由于测试机器、场景、jvm配置等不同而引起测试误差是完全可能的,只是这个误差能否在可接受的范围内。
6、最终测试结果是fork参数与每次测试迭代参数的合集,如fork值为3,iterations值为5,那最终测试次数就是 3 * 5 = 15次。
参考文章:
http://hg.openjdk.java.net/code-tools/jmh/file/99d7b73cf1e3/jmh-samples/src/main/java/org/openjdk/jmh/samples
http://java-performance.info/jmh/
https://www.cnblogs.com/tranquillity/p/9488572.html
https://www.xncoding.com/2018/01/07/java/jmh.html
https://blog.csdn.net/lxbjkben/article/details/79410740
http://blog.dyngr.com/blog/2016/10/29/introduction-of-jmh/
http://irfen.me/java-jmh-simple-microbenchmark/
https://www.cnblogs.com/bestzhang/p/10082119.html
附:
json工具pom依赖:
com.alibaba fastjson1.2.58 com.google.code.gson gson2.8.5 com.fasterxml.jackson.core jackson-databind2.9.9 com.fasterxml.jackson.core jackson-core2.9.9 com.fasterxml.jackson.core jackson-annotations2.9.9
Userinfo.java:
package com.xiaojiang; import java.util.Date; import java.util.List; /** * @ Description:用户信息 * @ Author:xiaojiang * @ Date:Created in 2019-06-19 * @ Version:0.0.1 */public class Userinfo {private String username; //用户名private String gender; //用户性别private Integer age; //用户年龄private Date birthday; //用户生日private List address; //用户地址private Long createTime; //用户创建时间public String getUsername() {return username; }public void setUsername(String username) {this.username = username; }public String getGender() {return gender; }public void setGender(String gender) {this.gender = gender; }public Integer getAge() {return age; }public void setAge(Integer age) {this.age = age; }public Date getBirthday() {return birthday; }public void setBirthday(Date birthday) {this.birthday = birthday; }public List getAddress() {return address; }public void setAddress(List address) {this.address = address; }public Long getCreateTime() {return createTime; }public void setCreateTime(Long createTime) {this.createTime = createTime; }@Overridepublic String toString() {return "Userinfo{" +"username='" + username + '\'' +", gender='" + gender + '\'' +", age=" + age +", birthday=" + birthday +", address=" + address +", createTime=" + createTime +'}'; }}
JsonUtil.java:
package com.xiaojiang; import com.alibaba.fastjson.JSON; import com.fasterxml.jackson.core.JsonProcessingException; import java.io.IOException; /** * @ Description:json工具类 * @ Author:xiaojiang * @ Date:Created in 2019-06-19 * @ Version:0.0.1 */public class JsonUtil {private static com.google.gson.Gson gson = new com.google.gson.GsonBuilder().create(); private static com.fasterxml.jackson.databind.ObjectMapper jacksonMapper = new com.fasterxml.jackson.databind.ObjectMapper(); public static String fastjson_bean2Json(Object object){return com.alibaba.fastjson.JSON.toJSONString(object); }public staticT fastjson_json2Bean(String jsonStr, Class objectClass) {return JSON.parseObject(jsonStr, objectClass); }public static String gson_bean2Json(Object object){return gson.toJson(object); }public static T gson_json2Bean(String jsonStr, Class objectClass){return gson.fromJson(jsonStr,objectClass); }public static String jackson_bean2Json(Object object) {try {return jacksonMapper.writeValueAsString(object); } catch (JsonProcessingException e) {e.printStackTrace(); }return null; }public static T jackson_json2Bean(String jsonStr, Class objectClass){try {return jacksonMapper.readValue(jsonStr,objectClass); } catch (IOException e) {e.printStackTrace(); }return null; }}
到此这篇关于详解Java使用JMH进行基准性能测试的文章就介绍到这了,更多相关Java 基准性能测试内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
推荐阅读
- JAVA(抽象类与接口的区别&重载与重写&内存泄漏)
- 由浅入深理解AOP
- 【译】20个更有效地使用谷歌搜索的技巧
- mybatisplus如何在xml的连表查询中使用queryWrapper
- MybatisPlus|MybatisPlus LambdaQueryWrapper使用int默认值的坑及解决
- MybatisPlus使用queryWrapper如何实现复杂查询
- 事件代理
- Java|Java OpenCV图像处理之SIFT角点检测详解
- C语言浮点函数中的modf和fmod详解
- java中如何实现重建二叉树