首页 > 编程 > Java > 正文

Java中的栈上分配

2019-11-08 02:38:13
字体:
来源:转载
供稿:网友

博客搬家自https://my.oschina.net/itsyizu/blog/

什么是栈上分配

栈上分配是java虚拟机提供的一种优化技术,基本思想是对于那些线程私有的对象(指的是不可能被其他线程访问的对象),可以将它们打散分配在栈上,而不是分配在堆上。分配在栈上的好处是可以在函数调用结束后自行销毁,而不需要垃圾回收器的介入,从而提供系统的性能。

栈上分配的一个技术基础是进行逃逸分析。逃逸分析的目的是判断对象的作用域是否有可能逃逸出函数体。

下面的代码显示了一个逃逸的对象:

public class PartionOnStack { static class User{ PRivate int id; private String name; public User(){} } private static User user; public static void foo() { user=new User(); user.id=1; user.name="sixtrees"; } public static void main(String[] args) { foo(); }}

因为上面的代码中的User的作用域是整个Main Class,所以user对象是可以逃逸出函数体的。下面的代码展示的则是一个不能逃逸的代码段。

public class PartionOnStack { class User{ private int id; private String name; public User(){} } public void foo() { User user=new User(); user.id=1; user.name="sixtrees"; } public static void main(String[] args) { PartionOnStack pos=new PartionOnStack(); pos.foo(); }}

代码来帮忙

通过上面的分析,我们知道java虚拟机会帮助我们在栈上进行分配,我们设置了1亿次alloc的对象创建,每个User对象实例需要占用16字节的空间,如果没有优化,累计的空间申请将有1.5GB这么大,如果我们的堆空间设置的值小于1.5GB的话,就会发生GC。代码如下:

public class PartionOnStack { class User{ public int id; public String name; } public void foo() { User user=new User(); user.id=1; user.name="sixtrees"; } public static void main(String[] args) { System.out.println("start-----------"); long beginTime=System.currentTimeMillis(); PartionOnStack pos=new PartionOnStack(); for(int i=0;i<100000000;i++) { pos.foo(); } long endTime=System.currentTimeMillis(); System.out.println("总共运行----"+(endTime-beginTime)+"ms"); }}

使用下面的参数运行上面的代码

-server -XMX10m -Xms10m -XX:+DoEscapeAnalysis -XX:+PrintGC -XX:-UseTLAB -XX:+EliminateAllocations

运行的结果如下所示:

image

对于大量的零散小对象,栈上分配提供了一种很好的对象分配策略,栈上分配的速度快,并且可以有效地避免垃圾回收带来的负面的影响,但由于和堆空间相比,栈空间比较小,因此对于大对象无法也不适合在栈上进行分配。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表