JVM的栈上分配

栏目: Java · 发布时间: 5年前

内容简介:栈上分配是JVM的一个优化选项。Java的对象一般都是分配在堆内存中的,而JVM开启了栈上分配后,允许把线程私有的对象(其它线程访问不到的对象)打散分配在栈上。这些分配在栈上的对象在方法调用结束后即自行销毁,不需要JVM触发垃圾回收器来回收,因此提升了JVM的性能。栈上分配在

栈上分配是JVM的一个优化选项。

Java的对象一般都是分配在堆内存中的,而JVM开启了栈上分配后,允许把线程私有的对象(其它线程访问不到的对象)打散分配在栈上。这些分配在栈上的对象在方法调用结束后即自行销毁,不需要JVM触发垃圾回收器来回收,因此提升了JVM的性能。

栈上分配在 JDK6u23 后默认是开启了的。下面通过代码来验证这一点。

验证

写一段代码:

public class OnStackTest {
    // User类
    public static class User{
        public int id=0;
        public String name="";
    }
    // 创建User类对象
    public static void alloc(){
        User u=new User();
        u.id=5;
        u.name="geym";
    }
    // 程序入口
    public static void main(String[] args) throws InterruptedException {
        long b=System.currentTimeMillis();
        // 创建大量的对象
        for(int i=0;i<99999999;i++){
            alloc();
        }
        long e=System.currentTimeMillis();
        // 打印执行时间
        System.out.println(e-b);
    }
}
复制代码

JDK6u22 环境下执行的结果:

-Xmx :指定最大堆内存

-Xms :指定最大堆内存

-XX:+PrintGC :打印GC日志, + 号表示启用, - 号表示禁用

D:\develop\jdk\6u22\bin\java.exe -Xmx5m -Xms5m -XX:+PrintGC geym.zbase.ch2.onstackalloc.OnStackTest
[GC 2048K->288K(5824K), 0.0049399 secs]
[GC 2336K->288K(5824K), 0.0013872 secs]
[GC 2336K->320K(5824K), 0.0026034 secs]
......
[GC 3280K->720K(6080K), 0.0001026 secs]
3304
复制代码

JDK6u23 环境下执行的结果:

D:\develop\jdk\6u23\bin\java.exe -Xmx5m -Xms5m -XX:+PrintGC geym.zbase.ch2.onstackalloc.OnStackTest
70
复制代码

从以上两个执行的结果可以看出,JDK6u22默认是没有开启栈上分配的,所以 alloc() 方法中new出来的User对象,是存放在堆上的。由于指定了最大堆内存只有5m,当堆内存不足就会触发GC。从JDK6u22的GC日志可以看出执行过程频繁触发GC,执行耗时3304,明显比JDK6u23的长。

而JDK6u23的执行过程中没有打印任何GC日志,证明这时候 alloc() 方法中new出来的User对象,是存放在 alloc() 方法对应的栈帧上的。当每一次执行 alloc() 方法,线程会向 Java 栈压入一个栈帧, new User() 创建的对象就存放在这个栈帧上; alloc() 方法执行结束,栈帧从Java栈弹出,user对象随栈帧的弹出销毁。

示意图:

JVM的栈上分配

相关JVM参数

JDK6u22及之前的版本 如果需要使用栈上分配来优化,可以加入以下参数:

java -server -Xmx5m -Xms5m -XX:+PrintGC -XX:+DoEscapeAnalysis -XX:-UseTLAB -XX:+EliminateAllocations  geym.zbase.ch2.onstackalloc.OnStackTest
复制代码

-XX:+DoEscapeAnalysis :开启逃逸分析

-XX:-UseTLAB :禁用TLAB(Thread Local Allocation Buffer)

-XX:+EliminateAllocations :开启标量替换

关于逃逸分析

逃逸分析的作用就是判断一个对象的作用域有没有可能逃出一个Java方法的作用域。请看下面例子演示:

// u对象逃出alloc的作用域,不符合栈上分配的条件
public class OnStackTest {
    private static User u;
    public static void alloc(){
        u=new User();
    }
}
复制代码
// u对象没有逃出alloc的作用域,符合栈上分配的条件
public class OnStackTest {
    public static void alloc(){
        User u=new User();
    }
}
复制代码

关于标量替换

启用标量替换后,允许把对象打散分配在栈上。 比如user对象有id和name属性,在启用标量替换后,user对象的id和name属性会视为局部变量分配在栈上

注意:逃逸分析和标量替换是栈上分配的前提,所以,在jvm参数中关闭了二者其中一个选项,栈上分配都不会生效。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

数据结构基础

数据结构基础

[美]Ellis Horowitz 霍罗维兹 / 朱仲涛 / 清华大学出版社 / 2009-3 / 49.00元

《数据结构基础(C语言版)(第2版)》是最经典数据结构教材的最新版本,国内外大多数的同类教材都是以《数据结构基础(C语言版)(第2版)》为蓝本编写而来的。《数据结构基础(C语言版)(第2版)》用C作为描述语言,全面而生动地介绍了数据结构的有关知识,如数组、栈、队列、链表、树和图,以及构成所有软件基础的排序散列技术。此外,《数据结构基础(C语言版)(第2版)》还介绍了各种高级或特殊数据结构,如优先级......一起来看看 《数据结构基础》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

SHA 加密
SHA 加密

SHA 加密工具

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具