• Java基本类型的内存分配在栈还是堆


    我们都知道在Java里面new出来的对象都是在堆上分配空间存储的,但是针对基本类型却有所区别,基本类型可以分配在栈上,也可以分配在堆上,这是为什么?

    在这之前,我们先看下Java的基本类型8种分别是:

    byte =>8bit
    short => 16bit
    int => 32bit
    long =>64bit
    
    folat => 单精度32位
    double => 双精度64位
    
    boolean => 注意oracle官网文档介绍,boolean代表1bit的信息,但它本身的size却不是精确的,依赖于jvm和os的实现,比较常见的说法是,boolean单独使用的时候,在编译时是使用int代替的,如果是boobean数组,则是使用1byte代替
    
    char => 16bit
    

    注意字符串内部是用char数组实现的,所以属于引用类型。

    基本类型在成员变量和局部(local)变量的时候其内存分配机制是不一样的。

    如果是成员变量,那么不分基本类型和引用类型都是在java的堆内存里面分配空间,而局部变量的基本类型是在栈上分配的。栈属于线程私有的空间,局部变量的生命周期和作用域一般都很短,为了提高gc效率,所以没必要放在堆里面。

    如下代码:

    public class DemoTest {
    
     int y;// 分布在堆上
     public static void main(String[] args) {
         int x=1; //分配在栈上
         String name=new String("cat");//数据在堆上,name变量的指针在栈上
         String address="北京";//数据在常量池,属于堆空间,指针在栈
         Integer price=4;//包装类型同样是引用类型,编译时会自动装拆相,所以数据在堆上,指针在栈
        }
    }
    

    在java里面通过new出来的对象都在堆上分配,这里有两种特殊情况,

    (1)字符串的字面量

    字符串的字面量,没有new关键字,但却是在堆上分配内存的,严格的说是在堆里面的字符串常量池里面。

    (2)基本类型的包装类

    同样的道理,针对各个基本类型的包装类型,如:Integer,Double,Long等,这些属于引用类型,我们直接在局部方法里面使用包装类型赋值,那么数据真正的内存分配还是在堆内存里面,这里有个隐式的拆装箱来自动完成转换,数据的指针是在栈上,包装类型的出现主要是为了基本类型能够用在泛型的设计上和使用null值,而基本类型则拥有更好的计算性能,这一点我们也需要注意。

    思考:
    如果你熟悉java的内存结构的话就会知道,堆 是所有线程共享的内存区域,栈 是每个线程独享的,如果你将一个实例变量放在栈内,那么就不存在多个线程访问同一个对象资源了,这显然是不对的,所以实例变量要在堆上创建,也不是线程安全的。
    但是对于局部变量,是在栈上创建的,每一次方法调用创建一个帧,独享一份内存区域,其他的线程是不会访问到该线程的资源,在 栈上创建也会减轻GC的压力,随着该方法的结束,帧出栈,相对应的内存消除,这种局部变量占用的内存自然就消失了,因此局部变量是线程安全的。

    艾欧尼亚,昂扬不灭,为了更美好的明天而战(#^.^#)
  • 相关阅读:
    快速幂取模
    程序人生系列之新闻发布系统 0105
    JavaWeb之博客系统(四)
    [转]树状数组
    题目:免费午餐
    题目:删数问题
    题目:三元组
    题目:分子团
    题目:[汪老师结婚]婚礼上的袭击
    题目:[SBN号码]
  • 原文地址:https://www.cnblogs.com/lovelywcc/p/14053531.html
Copyright © 2020-2023  润新知