Java中的栈,堆,方法区和常量池

要说Java中的栈,堆,方法区和常量池就要提到HotSpot,HotSpot是Sun JDK 和 Open JDK中所带的虚拟机。   

(Sun JDK 和 Open JDK除了注释不同,代码实现基本上是一样的)

Stack(栈)分为VM Stack(虚拟机栈)和Native Method Stack(本地方法栈),不过HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一了。 

虚拟机栈: 线程私有的, 描述的是Java方法执行的内存模型,方法调用的同时创建一个栈帧储存局部变量表,操作数栈,方法出口等等),每个方法的调用直到执行完成对应的是栈帧在虚拟机中入栈和出栈的过程。

局部变量表(通常说的栈其实是栈里面的局部变量表):存放基本数据类型变量和对象的引用(所需内存在编译时期完成分配,方法运行时期不改变局部变量表大小,四个字节占用一个局部变量空间)

栈中的数据可以共享,例如:int a=3; int b=3;

   编译器先处理int a = 3;首先它会在栈中创建一个变量为a的引用,然后查找栈中是否有3这个值,如果没找到,就将3存放进来,然后将a指向3。接着  处理int b = 3;在创建完b的引用变量后,因为在栈中已经有3这个值,便将b直接指向3。这样,就出现了a与b同时均指向3的情况。这时,如果再令  a=4;那么编译器会重新搜索栈中是否有4值,如果没有,则将4存放进来,并令a指向4;如果已经有了,则直接将a指向这个地址。因此a值的改变不  会影响到b的值。要注意这种数据的共享与两个对象的引用同时指向一个对象的这种共享是不同的,因为这种情况a的修改并不会影响到b, 它是由编译  器完成的,它有利于节省空间。而一个对象引用变量修改了这个对象的内部状态,会影响到另一个对象引用变量。 

包装类数据,如Integer, String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中,Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。

"==" 比较的是对象的地址,也就是是否是同一个对象;

"equal" 比较的是对象的值。

int 变为Integer 时,如果值在-128~127之间  则不会创建新的integer对象 储存常量池中,这么做的目的是提高效率.

Heap(堆):

Java堆是被所有线程共享的一块区域,在虚拟机启动时创建 ,此内存的唯一目的就是存放对象实例和数组,同时也是GC管理的主要区域。

分为新生代(Eden Survivor Survivor8:1:1)和老年代,Java堆可以处于物理上不连续的内存空间中,只要逻辑连续即可。

方法区:

不等价于永久代,但hotspot用永久代实现方法区 在jdk1.7的HotSpot中 已经把原本放在永久代中的字符串常量池移出,放入堆内存中 ), 与堆一样是线程共享的一块内存区域。用于储存 已被虚拟机加载 信息、常量、静态变量、即时编译器编译后的代码等数据。
垃圾收集行为在方法区很少出现,这块区域回收的主要目标是针对常量池的回收和对类型的卸载 
           

运行时常量池:方法区的一部分

常量池用于存放 编译期 生成的各种 字面量 符号引用(还有翻译出来的直接引用) ,这部分内容在类加载后进入方法区的运行时常量池中存放。 
运行时常量池相对于 Class文件常量池 的另一个重要特征是具备动态性, 运行期间也可能将新的常量放入池中

字面量:如文本字符串,声明为final的常量值等。

public stick final int i =3;

String s="abc";

符号引用:类和接口的全限定名、字段的名称和描述符、方法的名称和描述符

String 是一个特殊的包装类数据。即可以用String str = new String("abc");的形式来创建,也可以用String str = "abc";的形式来创建

(1)String str = "abc"创建对象的过程
1 首先在常量池中查找是否存在内容为"abc"字符串对象
2 如果不存在则在常量池中创建"abc",并让str引用该对象
3 如果存在则直接让str引用该对象

(2)String str = new String("abc")创建实例的过程
1 首先在堆中(不是常量池)创建一个指定的对象"abc",并让str引用指向该对象
2 在字符串常量池中查看,是否存在内容为"abc"字符串对象
3 若存在,则将new出来的字符串对象与字符串常量池中的对象联系起来
4 若不存在,则在字符串常量池中创建一个内容为"abc"的字符串对象,并将堆中的对象与之联系起来

String str1 = "abc"; String str2 = "ab" + "c"; str1==str2是ture
是因为String str2 = "ab" + "c"会查找常量池中时候存在内容为"abc"字符串对象,如存在则直接让str2引用该对象,显然String str1 = "abc"的时候,上面说了,会在常量池中创建"abc"对象,所以str1引用该对象,str2也引用该对象,所以str1==str2
String str1 = "abc"; String str2 = "ab"; String str3 = str2 + "c"; str1==str3是false                ---------//可参考Java编程思想第四版P284,285
是因为String str3 = str2 + "c"涉及到变量(不全是常量)的相加,所以会生成新的对象,其内部实现是先new一个StringBuilder,然后 append(str2),append("c");然后让str3引用toString()返回的对象




评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值