java中的逃逸分析
逃逸分析
public static StringBuffer craeteStringBuffer(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb;
}
public static String createStringBuffer(String s1, String s2) {
StringBuffer sb = new StringBuffer();
sb.append(s1);
sb.append(s2);
return sb.toString();
}
第一段代码中的sb就逃逸了,而第二段代码中的sb就没有逃逸。
在Java代码运行时,通过JVM参数可指定是否开启逃逸分析,-XX:+DoEscapeAnalysis : 表示开启逃逸分析
-XX:-DoEscapeAnalysis : 表示关闭逃逸分析 从jdk 1.7开始已经默认开始逃逸分析,如需关闭,需要指定-XX:-DoEscapeAnalysis
作用
使用逃逸分析,编译器可以对代码做如下优化
锁消除
如果一个对象被发现只能从一个线程被访问到,那么对于这个对象的操作可以不考虑同步。
锁消除前
public void f() {
Object o = new Object();
synchronized(o) {
System.out.println(o);
}
}
锁消除后
public void f() {
Object o = new Object();
System.out.println(o);
}
标量替换
分离对象或标量替换。有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分(或全部)可以不存储在内存,而是存储在CPU寄存器中。
标量替换前
public static void main(String[] args) {
alloc();
}
private static void alloc() {
Point point = new Point(1,2);
System.out.println("point.x="+point.x+"; point.y="+point.y);
}
class Point{
private int x;
private int y;
}
标量替换后
private static void alloc() {
int x = 1;
int y = 2;
System.out.println("point.x="+x+"; point.y="+y);
}
栈上分配
在Java虚拟机中,对象是在Java堆中分配内存的,这是一个普遍的常识。但是,有一种特殊情况,那就是如果经过逃逸分析后发现,一个对象并没有逃逸出方法的话,那么就可能被优化成栈上分配。这样就无需在堆上分配内存,也无须进行垃圾回收了。
public static void main(String[] args) {
long a1 = System.currentTimeMillis();
for (int i = 0; i < 1000000; i++) {
alloc();
}
// 查看执行时间
long a2 = System.currentTimeMillis();
System.out.println("cost " + (a2 - a1) + " ms");
// 为了方便查看堆内存中对象个数,线程sleep
try {
Thread.sleep(100000);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
private static void alloc() {
User user = new User();
}
static class User {
}
在alloc方法中定义了User对象,但是并没有在方法外部引用他。也就是说,这个对象并不会逃逸到alloc外部。经过JIT的逃逸分析之后,就可以对其内存分配进行优化。
未开启逃逸分析
Xmx4G -Xms4G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
结果
➜ ~ jps
2809 StackAllocTest
2810 Jps
➜ ~ jmap -histo 2809
num #instances #bytes class name
----------------------------------------------
1: 524 87282184 [I
2: 1000000 16000000 StackAllocTest$User
3: 6806 2093136 [B
4: 8006 1320872 [C
5: 4188 100512 java.lang.String
6: 581 66304 java.lang.Class
堆中共创建了100万个StackAllocTest$User实例。
开启逃逸分析
-Xmx4G -Xms4G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails -XX:+HeapDumpOnOutOfMemoryError
结果
➜ ~ jps
709
2858 Launcher
2859 StackAllocTest
2860 Jps
➜ ~ jmap -histo 2859
num #instances #bytes class name
----------------------------------------------
1: 524 101944280 [I
2: 6806 2093136 [B
3: 83619 1337904 StackAllocTest$User
4: 8006 1320872 [C
5: 4188 100512 java.lang.String
6: 581 66304 java.lang.Class
开启了逃逸分析之后(-XX:+DoEscapeAnalysis),在堆内存中只有8万多个StackAllocTest$User对象
java中的逃逸分析的更多相关文章
- 深入理解Java中的逃逸分析
在Java的编译体系中,一个Java的源代码文件变成计算机可执行的机器指令的过程中,需要经过两段编译,第一段是把.java文件转换成.class文件.第二段编译是把.class转换成机器指令的过程. ...
- JVM中启用逃逸分析
-XX:+DoEscapeAnalysis 逃逸分析优化JVM原理我们知道java对象是在堆里分配的,在调用栈中,只保存了对象的指针.当对象不再使用后,需要依靠GC来遍历引用树并回收内存,如果对象数量 ...
- Java之JVM逃逸分析
引言: 逃逸分析(Escape Analysis)是众多JVM技术中的一个使用不多的技术点,本文将通过一个实例来分析其使用场景. 概念 逃逸分析,是一种可以有效减少Java 程序中同步负载和内存堆分配 ...
- JVM中的逃逸分析
逃逸分析(Escape Analysis)是目前Java虚拟机中比较前沿的优化技术. 逃逸分析的基本行为就是分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递 ...
- java中synchronized关键字分析
今天我们来分析一下java中synchronized关键字.首先来看一段java代码:(本地编译环境为mac,jdk1.8的环境) Demo.java package com.example.spri ...
- java中Thread类分析
创建线程的方式有三种,一是创建Thread实例,二是实现Runnable接口,三是实现Callable接口,Runnable接口和Callable接口的区别是一个无返回值,一个有返回值:不管是Runn ...
- java虚拟机的逃逸分析
逃逸分析作为其他优化手段提供依据的分析技术,其基本行为就是分析对象动态作用域:当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他方法中,称为方法逃逸.甚至还有可能被外部线程 ...
- GO中的逃逸分析
1.什么是逃逸分析 以前写c/c++代码时,为了提高效率,常常将pass-by-value(传值)“升级”成pass-by-reference,企图避免构造函数的运行,并且直接返回一个指针. 那么这里 ...
- Java中CAS原理分析(volatile和synchronized浅析)
CAS是什么? CAS英文解释是比较和交换,是cpu底层的源语,是解决共享变量原子性实现方案,它定义了三个变量,内存地址值对应V,期待值E和要修改的值U,如下图所示,这些变量都是在高速缓存中的,如果两 ...
随机推荐
- node实现后台权限管理系统
本文面向的是node初学者,目标是搭建一个基础的后台权限系统.使用的node框架是上手最简单的express,模板是ejs,这些在node入门的书籍中都有介绍说明,所以应该是难度较低的. 对于node ...
- tf.nn.l2_loss()的用法
https://blog.csdn.net/yangfengling1023/article/details/82910536
- 随笔编号-07 JS针对时间操作
//获取完整的当前日期 var date=new Date; var year=date.getFullYear(); var month=date.getMonth()+1; month =(mon ...
- 设计模式(C#)——02简单工厂模式
推荐阅读: 我的CSDN 我的博客园 QQ群:704621321 工厂模式主要是为创建对象提供过渡接口,以便将创建对象的具体过程屏蔽隔离起来.通俗来说,你只关心怎么用,不用关心怎么做 ...
- Leetcode之分治法专题-169. 求众数(Majority Element)
Leetcode之分治法专题-169. 求众数(Majority Element) 给定一个大小为 n 的数组,找到其中的众数.众数是指在数组中出现次数大于 ⌊ n/2 ⌋ 的元素. 你可以假设数组是 ...
- Socket I/O模型之select模型
socket网络编程中有多种常见的I/O模型: 1.blocking阻塞 2.nonblocking非阻塞 3.I/O multiplexing复用 4.signal driven 5.asynchr ...
- 过滤掉Abp框架不需要记录的日志
该文章是系列文章 基于.NetCore和ABP框架如何让Windows服务执行Quartz定时作业 的其中一篇. 问题 ABP.WindowsService/Demo.MyJob/4.0.0该项目不仅 ...
- 2019DX#6
Solved Pro.ID Title Ratio(Accepted / Submitted) 1001 Salty Fish 16.28%(7/43) OK 1002 Nonsense Tim ...
- SPOJ - 3267. D-query 主席树求区间个数
SPOJ - 3267 主席树的又一种写法. 从后端点开始添加主席树, 然后如果遇到出现过的元素先把那个点删除, 再更新树, 最后查询区间就好了. #include<bits/stdc++.h& ...
- BALNUM - Balanced Numbers(数位dp)
题目链接:http://www.spoj.com/problems/BALNUM/en/ 题意:问你在[A,B]的闭区间内有几个满足要求的数,要求为每个出现的奇数个数为偶数个,每个出现的偶数个数为奇数 ...