要说Java中的栈,堆,方法区和常量池就要提到HotSpot,HotSpot是Sun JDK 和 Open JDK中所带的虚拟机。 (Sun JDK 和 Open JDK除了注释不同,代码实现基本上是一样的) 以下说的内容都是围绕HotSpot。
Stack(栈):分为VM Stack(虚拟机栈)和Native Method Stack(本地方法栈),不过HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一了。 虚拟机栈: 线程私有的, 描述的是Java方法执行的内存模型,方法调用的同时创建一个栈帧(储存局部变量表,操作数栈,方法出口等等),每个方法的调用直到执行完成对应的是栈帧在虚拟机中入栈和出栈的过程。 局部变量表(通常说的栈其实是栈里面的局部变量表):存放基本数据类型变量和对象的引用(所需内存在编译时期完成分配,方法运行时期不改变局部变量表大小,四个字节占用一个局部变量空间)
--------栈中的数据可以共享: int a = 3; 包装类数据,如Integer,
String, Double等将相应的基本数据类型包装起来的类。这些类数据全部存在于堆中,Java用new()语句来显示地告诉编译器,在运行时才根据需要动态创建,因此比较灵活,但缺点是要占用更多的时间。
==比较的是对象的地址,也就是是否是同一个对象; equal比较的是对象的值。 int 变为Integer 时 如果值在-128~127之间 则不会创建新的integer对象 储存常量池中,这么做的目的是提高效率----->记得在别的地方看过不知道对不对
Java代码 JAVA堆: Java堆是被所有线程共享的一块区域,在虚拟机启动时创建 ,此内存的唯一目的就是存放对象实例和数组 GC 管理的主要区域。 分为新生代(Eden Survivor Survivor8:1:1)和老年代 Java堆可以处于物理上不连续的内存空间中,只要逻辑连续即可 关于对象的创建请参考:http://note.youdao.com/yws/public/redirect/share?id=5177014ee5ad1ac3f0af9fdab3b011a3&type=false
方法区: 不等价于永久代hotspot用永久代实现方法区(在jdk1.7的HotSpot中 已经把原本放在永久代中的字符串常量池移出)
与堆一样是线程共享的一块内存区域。
用于储存已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
垃圾收集行为在方法区很少出现,这块区域回收的主要目标是针对常量池的回收和对类型的卸载
运行时常量池: 方法区的一部分
常量池用于存放编译期生成的各种字面量和符号引用(还有翻译出来的直接引用),这部分内容在类加载后进入方法区的运行时常量池中存放。
运行时常量池相对于Class文件常量池的另一个重要特征是具备动态性,运行期间也可能将新的常量放入池中
字面量:如文本字符串,声明为final的常量值等。 public stick final int i =3; String s='abc'; 符号引用:类和接口的全限定名 字段的名称和描述符 方法的名称和描述符
String 的本质是字符数组。
String 的标准实现含有4个实例变量
指向字符数组的引用
int类型 偏移量
int类型 字符串的长度
int类型 散列值
public class String{
private char[]value;
private int offset;
private int count;
private int hash;
...
}
一个String对象总共使用40字节(16字节对象本身开销 8字节的引用 三个int类型(12字节) 4字节(填充字节)),因为String的char数组常常是在多个字符串之间共享的,因此String对象是不可变的
String是一个特殊的包装类数据。即可以用String str = new String('abc');的形式来创建,也可以用String str = 'abc';的形式来创建 String str = 'abc'创建对象的过程
String str1 = 'abc'; String str2 = 'ab' 'c'; str1==str2是ture
String s = new String(“abc”); 产生几个对象? 一个或两个,如果常量池中原来没有 ”abc”, 就是两个(参考栈中的数据共享)。
|
|
来自: Levy_X > 《JAVAWEB学习资料》