一个对象创建的时候,到底是在堆上分配,还是在栈上分配呢?这和两个方面有关:对象的类型和在 Java 类中存在的位置。
Java的对象可以分为基本数据类型和普通对象。
- 对于普通对象来说,JVM会首先在堆上创建对象,然后在其它地方使用的其实是它的引用。比如把这个引用保存在虚拟机栈的局部变量表中。
- 对于基本数据类型来说(byte、short、int、long、float、double、char)有两种情况。当你在方法体内声明了基本数据类型的对象,就会在栈上直接分配;其他情况都是在堆上分配。
但是随着JIT编译器的发展与逃逸分析技术的成熟,栈上分配
、标量替换
优化也会使我们的对象可能在栈上分配。
一、栈上分配
那么什么情况下,我们的对象会在栈上分配呢?就是我们的逃逸分析技术发现这个对象没有逃逸出一个方法,那么这个对象就是可以在栈上分配的,这样我们的对象就会在栈内,它会随着我们方法的结束会消亡,这样就不需要我们的GC进行回收的,它会随着方法自行销毁,可以提升性能。
逃逸分析的原理: 分析对象动态作用域,当一个对象在方法中定义后,它可能被外部方法所引用。
比如:调用参数传递到其他方法中,这种称之为方法逃逸。甚至还有可能被外部线程访问到,例如赋值给其他线程中访问的变量,这个称之为线程逃逸。 从不逃逸到方法逃逸到线程逃逸,称之为对象由低到高的不同逃逸程度。
如果确定一个对象不会逃逸出线程之外,那么让对象在栈上分配内存可以提高 JVM 的效率。
public class Client {
public User newUser(){
User user = new User();
user.setName("Rocky");
user.setAge(18);
return user;
}
public static class User{
private String name