详解jvm中的标量替换

网友投稿 222 2022-11-19


详解jvm中的标量替换

概述

通常在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 关闭标量http://替换优化

运行后在我本机的耗时: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毫http://秒,gc发生2000多次。

总结

可以看到通过逃逸分析与标量替换技术有效的减少了gc次数(减少了对象在堆中创建的数量)。

实际编码过程中避免对象逃逸情况是一种理想的情况。可以形成一种编码意识,尽量去减少对象逃逸。

思考

标量替换只是利用逃逸分析其中的一种优化措施, 还有其它优化措施吗?

以上就是详解jvm中的标量替换的详细内容,更多关于jvm 标量替换的资料请关注我们其它相关文章!


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:String实例化及static final修饰符实现方法解析
下一篇:SpringBoot集成Druid监控页面最小化配置操作
相关文章

 发表评论

暂时没有评论,来抢沙发吧~