关于Java堆栈的理解与说明

关于Java堆栈的理解与说明说到java的堆和栈就想起来了,java内存中的分配结构。作为一个Java的程序员,我们肯定知道Java的程序是运行在java虚拟机上的,也就是平时所说的JVM。程序中所有的方法、变量、常量、实例、静态存储都是由JVM在内存中进行分配的。1.寄存器:JVM中运行最快的,JVM内部的虚拟的存储器和CPU有关,我们无法控制。2.堆栈(也就是平时所说的栈stack):用来存放基本数据类型和引用数据类型的实例的(也就是实例对象的在堆中的首地址,Personp=newPerson;p…

说到java的堆和栈就想起来了,java内存中的分配结构。作为一个Java的程序员,我们肯定知道Java的程序是运行在java虚拟机上的,也就是平时所说的JVM。程序中所有的方法、变量、常量、实例、静态存储都是由JVM在内存中进行分配的。

1.    寄存器:JVM中运行最快的,JVM内部的虚拟的存储器和CPU有关,我们无法控制。

2.    堆栈(也就是平时所说的栈stack):用来存放基本数据类型和引用数据类型的实例的(也就是实例对象的在堆中的首地址,Person p = new Person; p存贮在堆栈中,值为@23651dff。还有就是堆栈是线程独享的。每一个线程都有自己的线程栈。

3.    堆(也叫做对内存或者对空间deap):用来存放程序动态生成的数据。(new 出来的对象的实例存储在堆中,但是仅仅存储的是成员变量,也就是平时所说的实例变量,成员变量的值则存储在常量池中。成员方法是此类所实现实例共享的,并不是每一次new 都会创建成员方法。成员方法被存储在方法区,并不是存储在第一个创建的对象中,因为那样的话,第一个对象被回收,后面创建的对象也就没有方法引用了。静态变量也存储在方法区中。局部变量在栈内存中,JVM为每一个类分配一个栈帧,然后引用类型的局部变量指向堆内存中的地址),堆是内存中共享的区域,要考虑线程安全的问题。

4.    方法区(non-deap,(非堆),在堆中为其分配的一部分内存):里面存储的是一些。类类型加载的东西(也就是反射中的.class之后的Class),用于存储已经被虚拟机加载的类的信息、常量、静态变量等。与堆一样,是被线程共享的内存区域,要注意线程安全问题。

5.     常量池:上面已经说了,存储在堆中的。JVM会对每一个加载的类维护一个常量池。用于存储成员变量中的数值。(String str= “aa”, aa也是存储在String.class类中的常量池中的。Str只是在栈中作为aa的首地址)

6.    代码段:这个就是用来存储代码片段的

7.    数据段:这个是用来存储静态成员的,包括静态变量,静态常量(存储在这里面的常量池当中),静态方法,静态类。

 

**下面就是java内存中的分配情况

里面还少一个方法区,存储在堆中。

说完JVM中的内存分配,我们来说一说堆和栈之间的区别。

1.堆

·存放new之后的实例

·每一个变量都有默认值(char:’/u0000’)

·生命周期未知,存储顺序未知。JVM有垃圾回收系统,GC会根据4种(强、软、弱、虚)引用进行不同程度的回收。

2.栈

·栈中存放的是基本数据类型和存放类对象的引用

·栈中的存放是有顺序的,而且JVM分配的空间是固定的,不能改变。这样使栈失去了灵活性。当局部变量使用完之后,JVM就会进行清除(也就是出栈)。

接下来使用一个小例子来对堆栈进行更深一步的了解

例子:

String str = “a”;

String strr = “bc”;

String str1 = “abc”;     //定义字符串变量str1
        Stringstr2 = “abc”;      //定义字符串变量str2
        Stringstr3 = new String(“abc”); //以new的方式定义字符串变量str3
        Stringstr4 = new String(“abc”);//以new的方式定义字符串变量str4

String str5 = str + strr;

String str6 = “a” + “bc”;
       结果:
         * str1 ==str2    true;     ①
         * str2 ==str3    false;     ②
         * str3 ==str4    false;    ③

*str1 == str5  false;       ④

*str1.equals(str5)   true;   ⑤

*str1==str6        true;   ⑥

讲解:

·‘==’比较的是地址

       Str1 和 str2显然指向的是String中常量池中的一个地址。(何灵鸿上次发的String的两种创建方式)

·equals比较的是内容

①  由于地址相同,所以true

②  由于str3 使用的new ,相当于在String类堆中创建了一个堆地址。而str2的地址则是在常量池中。地址对不上,因此false

③  和②的原理是一样的,相当于new了两个对象,也就是各自拥有了自己的地址。因此false。

④  str5使用的是字符串变量的相加。当看String的源码的时候,你会发现str.append()方法。本质上是先new 一个Stringbuilder对象,然后使用这个对象进行append,最后Builder对象toStirng回到String类型。也就是地址发生了变化。

结果:

⑤  比较的是内容,所以为true

⑥  也许看到这个会感到迷茫,一开始我也迷茫。后来一想,这种情况str6则是在常量池中进行的拼接(若存在,则直接指向;若不存在,拼接创建)

今天的文章关于Java堆栈的理解与说明分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/24437.html

(0)
编程小号编程小号

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注