java虚拟机有的区域随着虚拟机进程的启动而存在,
有的区域依赖用户线程的启动和结束而建立和销毁。
- 程序计数器:为了线程切换后能恢复到正确的执行位置,每个线程都有一个独立的程序计数器。(针对java方法,即栈)
- 虚拟机栈:为了虚拟机执行java方法,线程创建时就会创建一个栈帧,存储局部变量表、操作数栈、动态链接等。
*Error:线程请求的栈深度大于虚拟机所允许的深度;
OutOfMemoryError:动态扩展是无法申请到足够的内存。
- 本地方法栈:为了虚拟机使用到Native法服务。
- 堆:存放对象实例和数组,为对象实例分配内存。可分为新生代和老年代。可以处于物理上不连续的内存空间中,只要逻辑上连续即可。
-Xmx和-Xms控制大小。
- 方法区:存储类信息、常量、静态变量、编译后的代码等数据。也叫“永久代”,可以像Java堆一样管理这部分内存。
1.6以后将字符串常量池放入了堆空间。
- 运行时常量池:存放编译期生成的各种字面量和符号引用。
intern()方法设计的初衷,就是重用String对象.如下测试验证。
<wiz_code_mirror>
String a1 = new String("dog") + new String("Pig");//不会在常量池创建对象。
// String a1 = new String ("dogPig");//在常量池和堆空间创建对象
System.out.println(a1 == a1.intern());//在常量池查找不存在,1.6直接生成。1.7直接生成后,指向堆空间的引用。
System.out.println(a1 == "dogPig");//true
String str2 = "dogPig";//新加的一行代码,其余不变
System.out.println(a1 == str2);//true
内存分配:
桟:存储对象的引用,局部变量的基本数据类型,速度快,自动销毁;
堆:存储new出来的对象,数组,成员变量的基本数据类型;
常量池:属于方法区,存储final的变量和方法;
静态域:属于方法区,存储static的变量和方法;
方法区:存储二进制class字节码。
Demo demo=new Demo();
这一条语句,其实包括了四个动作:
1)右边的“new Demo”,是以Demo类为模板,在堆空间里创建一个Demo对象。
2)末尾的()意味着,在对象创建后,立即调用Demo类的构造函数,对刚生成的对象进行初始化。
3)左边的“Demo demo”创建了一个Demo类引用变量,它存放在栈空间中。也就是用来指向Demo对象的对象引用。
4)“=”操作符使对象引用指向刚创建的那个Demo对象。