java标量替换_JAVA逃逸分析、栈上分配、标量替换、同步消除
一、逃逸分析
逃逸分析是编译语言中的一种优化分析,而不是一种优化的手段。通过对象的作用范围的分析,为其他优化手段提供分析数据从而进行优化。
逃逸分析包括:
全局变量赋值逃逸
方法返回值逃逸
实例引用发生逃逸
线程逃逸:赋值给类变量或可以在其他线程中访问的实例变量. public class EscapeAnalysis {
public static Object object;
public void globalVariableEscape(){//全局变量赋值逃逸
object =new Object();
}
public Object methodEscape(){ //方法返回值逃逸
return new Object();
}
public void instancePassEscape(){ //实例引用发生逃逸
this.speak(this);
}
public void speak(EscapeAnalysis escapeAnalysis){
System.out.println("Escape Hello");
}
}
使用方法逃逸的案例进行分析: public StringBuffer createString(String ... values){
StringBuffer stringBuffer = new StringBuffer();
for (String string : values) {
stringBuffer.append(string+",");
}
return stringBuffer;
}
public static void main(String[] args) {
StringBuffer sb = new EscapeAnalysis().createString("Escape","Hello");
System.out.println(sb.toString());
}
从上面的案例我们看出stringBuffer是属于方法返回值逃逸。我们可以通过改变返回值得类型为String限定了StringBuffer的作用域在createString方法中从而不发生逃逸。 public String createString(String ... values){
StringBuffer stringBuffer = new StringBuffer();
for (String string : values) {
stringBuffer.append(string+",");
}
return stringBuffer.toString();
}
public static void main(String[] args) {
String string = new EscapeAnalysis().createString("Escape","Hello");
System.out.println(string);
}
一、标量替换 1.标量和聚合量
标量即不可被进一步分解的量,而JAVA的基本数据类型就是标量(如:int,long等基本数据类型以及reference类型等),标量的对立就是可以被进一步分解的量,而这种量称之为聚合量。而在JAVA中对象就是可以被进一步分解的聚合量。 2.替换过程
通过逃逸分析确定该对象不会被外部访问,并且对象可以被进一步分解时,JVM不会创建该对象,而会将该对象成员变量分解若干个被这个方法使用的成员变量所代替。这些代替的成员变量在栈帧或寄存器上分配空间。
二 、栈上分配
我们通过JVM内存分配可以知道JAVA中的对象都是在堆上进行分配,当对象没有被引用的时候,需要依靠GC进行回收内存,如果对象数量较多的时候,会给GC带来较大压力,也间接影响了应用的性能。为了减少临时对象在堆内分配的数量,JVM通过逃逸分析确定该对象不会被外部访问。那就通过标量替换将该对象分解在栈上分配内存,这样该对象所占用的内存空间就可以随栈帧出栈而销毁,就减轻了垃圾回收的压力。
测试逃逸分析后堆内存对比: private int count = 1000000;
public static void main(String[] args) throws InterruptedException, IOException {
EscapeAnalysis escapeAnalysis = new EscapeAnalysis();
for (int i = 0; i < escapeAnalysis.count ; i++) {
escapeAnalysis.getAge();
}
Thread.sleep(500);
for (int i = 0; i < escapeAnalysis.count ; i++) {
escapeAnalysis.getAge();
}
System.in.read();
}
public int getAge(){
Person person = new Person("小明",18,28.1);
return person.getAge();
}
class Person {
private String name;
private int age;
private double weight;
public Person(String name, int age, double weight) {
super();
this.name = name;
this.age = age;
this.weight = weight;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public double getWeight() {
return weight;
}
public void setWeight(double weight) {
this.weight = weight;
}
}
1.通过jps查看Class的Main进程的PID: 关闭逃逸分析的数据 C:\Users\li>jps
13216
16592 EscapeAnalysis
5640
17308
17916 Jps
9308 RemoteMavenServer 启用逃逸分析的数据,在JDK1.8是默认开启逃逸分析 C:\Users\li>jps
13216
13412 Jps
5640
17308
6460 EscapeAnalysis
7100 EscapeAnalysis
9308 RemoteMavenServer
2.通过jmap -histo [pid]查看java堆上的对象分布情况: 关闭逃逸分析的数据 C:\Users\li>jmap -histo 16592
num #instances #bytes class name
----------------------------------------------
1: 980000 31360000 test.EscapeAnalysis$Person
2: 154 785000 [I
3: 2158 288504 [C
4: 489 55832 java.lang.Class
5: 2017 48408 java.lang.String
6: 839 33560 java.util.TreeMap$Entry 启用逃逸分析的数据 C:\Users\li>jmap -histo 7100
num #instances #bytes class name
----------------------------------------------
1: 229881 7356192 test.EscapeAnalysis$Person
2: 446 756944 [I
3: 3105 442024 [C
4: 2408 57792 java.lang.String
通过上面数据可以看出没有开启逃逸分析时,Person在堆的内存是31360000 ,而开启逃逸分析时,Person在堆中的内存为7356192。 两者之间相差24003808。证明了启用了逃逸分析,可以减少堆内存的使用和减少GC。
三、同步消除
同步消除是java虚拟机提供的一种优化技术。通过逃逸分析,可以确定一个对象是否会被其他线程进行访问
如果对象没有出现线程逃逸,那该对象的读写就不会存在资源的竞争,不存在资源的竞争,则可以消除对该对象的同步锁。 public String createString(String ... values){
StringBuffer stringBuffer = new StringBuffer();
for (String string : values) {
stringBuffer.append(string+" ");
}
return stringBuffer.toString();
}
public static void main(String[] args) {
long start = System.currentTimeMillis();
EscapeAnalysis escapeAnalysis = new EscapeAnalysis();
for (int i = 0; i < 1000000; i++) {
escapeAnalysis.createString("Escape", "Hello");
}
long bufferCost = System.currentTimeMillis() - start;
System.out.println("craeteString: " + bufferCost + " ms");
} -server -XX:+DoEscapeAnalysis -XX:-EliminateLocks
craeteString: 202 ms
-server -XX:+DoEscapeAnalysis -XX:+EliminateLocks
craeteString: 173 ms
我们可以通过测试结果看出,如果开启了同步消除,在开启同步消除的执行效率比没有开启同步消除的高。
Reference:
java标量替换_JAVA逃逸分析、栈上分配、标量替换、同步消除相关推荐
- 3.内存分配、逃逸分析与栈上分配、直接内存和运行时常量池、基本类型的包装类和常量池、TLAB、可达性分析算法(学习笔记)
3.JVM内存分配 3.1.内存分配概述 3.2.内存分配–Eden区域 3.3.内存分配–大对象直接进老年代 3.3.1.背景 3.3.2.解析 3.4.内存分配–长期存活的对象进去老年代 3.5. ...
- JVM逃逸分析(同步省略、标量替换、栈上分配)
在Java的编译体系中,一个Java的源代码文件变成计算机可执行的机器指令的过程中,需要经过两段编译,第一段是把.java文件转换成.class文件.第二段编译是把.class转换成机器指令的过程. ...
- GC分类、TLAB、逃逸分析、栈上分配、同步消除、标量替换
GC分类 JVM的调优的一个环节,也就是垃圾收集,我们需要尽量的避免垃圾回收,因为在垃圾回收的过程中,容易出现STW(Stop the World)的问题,而 Major GC 和 Full GC出现 ...
- JVM 逃逸分析 (史上最全)
对于JVM"逃逸分析" 特性,也是近年来大厂面试.高薪面试的常见面试题. 和逃逸分析有关的常见面试题: Java中的对象一定是在堆上分配的吗? 注:本文以 PDF 持续更新,最新尼 ...
- 求你了,别再说Java对象都是在堆内存上分配空间的了!
Java作为一种面向对象的,跨平台语言,其对象.内存等一直是比较难的知识点,所以,即使是一个Java的初学者,也一定或多或少的对JVM有一些了解.可以说,关于JVM的相关知识,基本是每个Java开发者 ...
- Java虚拟机-逃逸分析(Escape Analysis)和栈上分配
我们都知道Java中的对象默认都是分配到堆上,在调用栈中,只保存了对象的指针.当对象不再使用后,需要依靠GC来遍历引用树并回收内存.如果堆中对象数量太多,回收对象还有整理内存,都会会带来时间上的消耗, ...
- 对象可以在栈上分配空间吗?_Java面试题之:Java中所有的对象都分配在堆中吗?...
JVM中的内存划分暂不讨论,单说堆(Heap),堆中一般存放的是new出来的对象.但是,随着JIT(即时编译)编译器的发展与逃逸分析(Escape Analysis)技术逐渐成熟,栈上分配.标量替换优 ...
- (九)栈上分配与逃逸分析
一.什么是逃逸? 逃逸是指在某个方法之内创建的对象,除了在方法体之内被引用之外,还在方法体之外被其它变量引用到:这样带来的后果是在该方法执行完毕之后,该方法中创建的对象将无法被GC回收,由于其被其它变 ...
- java创建对象时分配内存方式,是堆上分配还是栈上分配?
创建对象的内存是分配在堆上还是栈上面?大部分童鞋的回答是这样的:"肯定分配在堆内存的嘛,栈内存是属于子线程和基本数据类型专用的内存空间,怎么会分配到栈上面呢?",这个回答嘛,也对, ...
最新文章
- 【程序员基础篇】开源中国私有库代码更新
- python如何爬虫-如何使用python写爬虫程序
- 约瑟夫问题pascal程序
- jaxb需要jar包吗_JAXB –不需要注释
- *printf()格式化串安全漏洞分析(下)
- Kotlin开发细节
- 搭建一个wordpress
- 光伏电池matlab/simulink 搭建模型 可应用于光伏发电最大功率点跟踪 mppt中
- PMP第六版计算题公式整理
- Java高级应用编程——集合练习题
- 在当前目录下 打开cmd
- gee微端服务器系统设置,Gee引擎微端服务器
- js(javascript)和jq(jquery)常见问题(持续更新)
- java抽象类重载_012 JAVA 抽象类、接口、String类的基础了解
- 电视hdr测试软件,短路三分钟 | 你家电视、显示器真的支持HDR么?
- 设计n位乘加器(先乘后加)Design a n-bit multiplier (firstly multiply and then add)
- c语言QQ管理系统四百条,C语言程序设计论文-工会成员信息管理系统.doc
- 玩转Jetson AGX Orin—— Quick Start
- html5火焰字体效果,CSS3文字特效属性text-shadow如何实现火焰文字的效果
- 步步为营——局域网调试NAS软路由“PVE+爱快+lede+黑群晖硬盘直通”并移植到宽带网(超详细,上篇)
热门文章
- 【我想进大厂】Redis夺命连环11问
- 百度Q2智能云增长强劲;据悉史上最大 AI 芯片诞生!中兴与奇瑞成立合资公司一起加快开发5G汽车……...
- Spring精华问答 | 如何集成Spring Boot?
- 电脑编程教学_东莞沙田mastercam编程学习怎么收费
- java static 块 时机_java的static块执行时机
- 【基于XML方式】Spring整合Kafka
- HTTP中GET与POST方法有什么区别
- python-解码 decode 报错的问题
- 设计java application程序_下面哪些步骤是Java Application程序的建立及运行的步骤( )...
- qt中调整弹出框的位置