详解jvm中的标量替换
#代码知识 发布时间: 2026-01-12
概述

通常在java中创建一个对象,大家都认为是在堆中创建。 在jdk6开始有逃逸分析,标量替换等技术,关于在堆中创建对象不再绝对。
关于标量替换,通过以下几点进行概述:
- 逃逸分析
- 标量替换是什么
- 测试标量替换
逃逸分析
逃逸分析是一种分析技术,分析对象的动态作用域,供其他优化措施提供依据。比如分析一个对象不会逃逸到方法之外或线程之外,其它优化措施(栈上分配,标量替换等)根据逃逸程度进行优化。
逃逸分析示例
public class EscapeAnalysis {
public Person p;
/**
* 发生逃逸,对象被返回到方法作用域以外,被方法外部,线程外部都可以访问
*/
public void escape(){
p = new Person(26, "TomCoding escape");
}
/**
* 不会逃逸,对象在方法内部
*/
public String noEscape(){
Person person = new Person(26, "TomCoding noEscape");
return person.name;
}
}
static class Person {
public int age;
public String name;
... // 省略构造方法
}
标量替换是什么
标量可以理解成一种不可分解的变量,如java内部的基本数据类型、引用类型等。 与之对应的聚合量是可以被拆解的,如对象。
当通过逃逸分析一个对象只会作用于方法内部,虚拟机可以通过使用标量替换来进行优化。
比如上述noEscape()方法中person对象只会在方法内部,通过标量替换技术得到如下伪码:
/**
* 不会逃逸,对象在方法内部
*/
public String noEscape(){
int age = 26;
String name = "TomCoding noEscape";
return name;
}
测试标量替换
接下来我们通过对noEscape()方法进行测试,主要测试两种场景:
- 不使用标量替换
- 使用标量替换
以下测试是在jdk8中运行(注jdk8默认是开启逃逸分析,标量替换技术的)
测试代码如下:
void testEliminateAllocationsWithNoEscape() {
int n = 100000000;
long start = System.currentTimeMillis();
EscapeAnalysis escapeAnalysis = new EscapeAnalysis();
for (int i = 0; i < n; i++) {
// noEscape()不会发生逃逸
escapeAnalysis.noEscape();
}
System.out.println("耗时:" + (System.currentTimeMillis() - start));
}
- 不使用标量替换
将jvm参数设置如下:
-Xms5m 最小堆内存5M -Xmx5m 最大堆内存5M -XX:+PrintGC 打印gc日志 -XX:-EliminateAllocations 关闭标量替换优化
运行后在我本机的耗时:3006毫秒,gc发生2000多次。
- 使用标量替换
将jvm参数设置如下:
-Xms5m 最小堆内存5M -Xmx5m 最大堆内存5M -XX:+PrintGC 打印gc日志 -XX:+EliminateAllocations 关闭标量替换优化
运行后在我本机的耗时:20毫秒,gc发生6次。
再来看看发生逃逸的对象使用标量替换效果
测试代码如下:
void testEliminateAllocationsWithEscape() {
int n = 100000000;
long start = System.currentTimeMillis();
EscapeAnalysis escapeAnalysis = new EscapeAnalysis();
for (int i = 0; i < n; i++) {
// escape()发生逃逸
escapeAnalysis.escape();
}
System.out.println("耗时:" + (System.currentTimeMillis() - start));
}
将jvm参数设置如下:
-Xms5m 最小堆内存5M -Xmx5m 最大堆内存5M -XX:+PrintGC 打印gc日志 -XX:+EliminateAllocations 关闭标量替换优化
运行后在我本机的耗时:3705毫秒,gc发生2000多次。
总结
- 可以看到通过逃逸分析与标量替换技术有效的减少了gc次数(减少了对象在堆中创建的数量)。
- 实际编码过程中避免对象逃逸情况是一种理想的情况。可以形成一种编码意识,尽量去减少对象逃逸。
思考
标量替换只是利用逃逸分析其中的一种优化措施, 还有其它优化措施吗?
以上就是详解jvm中的标量替换的详细内容,更多关于jvm 标量替换的资料请关注其它相关文章!
代码知识SEO上一篇 : SpringBoot集成Druid监控页面最小化配置操作
下一篇 : 原生JavaScript实现刮刮乐
-
SEO外包最佳选择国内专业的白帽SEO机构,熟知搜索算法,各行业企业站优化策略!
SEO公司
-
可定制SEO优化套餐基于整站优化与品牌搜索展现,定制个性化营销推广方案!
SEO套餐
-
SEO入门教程多年积累SEO实战案例,从新手到专家,从入门到精通,海量的SEO学习资料!
SEO教程
-
SEO项目资源高质量SEO项目资源,稀缺性外链,优质文案代写,老域名提权,云主机相关配置折扣!
SEO资源
-
SEO快速建站快速搭建符合搜索引擎友好的企业网站,协助备案,域名选择,服务器配置等相关服务!
SEO建站
-
快速搜索引擎优化建议没有任何SEO机构,可以承诺搜索引擎排名的具体位置,如果有,那么请您多注意!专业的SEO机构,一般情况下只能确保目标关键词进入到首页或者前几页,如果您有相关问题,欢迎咨询!