JVM堆栈的理解

关于Java堆栈的理解与说明

说到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堆栈的理解与说明

说到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则是在常量池中进行的拼接(若存在,则直接指向;若不存在,拼接创建)


  严重声明,这篇文章也是在各种网站上面看的,总结下来的。地址是真的不知道了。希望博主看见之后不要生气。本人已经表明,这篇文章不是本人原创只是转载,有与时间原因,不知出处(主要是拼凑的)。


  • 9
    点赞
  • 69
    收藏
    觉得还不错? 一键收藏
  • 8
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 8
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值