Java中变量、对象的存储位置
Java内存分配时涉及5个区域,分别是寄存器、栈(stack)、堆(heap)、常量池、非RAM存储。
Java中数据类型
一种是基本类型
字节型byte 整形int,short, long. 字符型char, 浮点型float,double 布尔型boolean
一种是引用类型
如Integer、String、Double等将相应的基本数据类型包装起来的类,存储在堆中
String 是一种特殊的包装类数据
寄存器
寄存器是最快的存储区,位于处理器内部,由于寄存器的数量非常有限,所以寄存器都是按需分配,我们在程序中无法控制。
栈
栈位于通用RAM(随机访问存储器)中,栈由编译器自动分配和释放,栈存放的是基本数据类型(基本数据类型包括:int、short、double、long、float、boolean、char、byte,注意没有String)以及对象的引用。栈的优势是存取速度比堆快,仅次于CPU中的寄存器。
栈有一个很大的特点就是栈中的数据可以共享
比如定义两个int类型的变量:int a = 3; int b = 3;这里a和b是一个指向int型的引用,指向"3"这个字面值。编译器先处理int a = 3;这句语句的时候,先在栈中创建一个变量为a的引用,然后查找有没字面值为3的地址,如果没有就开辟出一个存储3的地址,然后将a指向这个3对应的地址。接着处理int b = 3;,也是先创建一个变量b的引用,由于栈中已经有字面量3了,于是就把b也指向3对应的这个地址,所以a和b都指向了一个地址。当我们执行 b = 4;的时候,首先还是去栈中查找有没字面量值为4对应的地址,如果没有就开辟个,然后将b指向这个新开辟的地址。如果已经有了就直接将b指向这个地址,此时a还是指向3,但b指向4了,而且他俩不再指向同一个地址了。实际上形参,局部变量都存储在栈中。
堆
堆是一种通用的内存池,也位于RAM中,堆用于存储所有的java对象。Java中所有对象的存储空间都是在堆中分配的,但是这个对象的引用却是在堆栈中分配,也就是说在建立一个对象时从两个地方都分配内存,在堆中分配的内存实际建立这个对象,而在栈中分配的内存只是一个指向这个堆对象的指针(引用)而已。
static 声明的代码存储在堆中。
String是一个特殊的包装类数据,可以用String a = new String("A");的形式创建,也可以用String a = "A";创建。
String a = "A";内部创建工作如下:
- 先定义一个名为a的String类的对象引用变量,a存放在栈中。
- 在栈中查找有没有存放值为“A”的地址,如果没有则开辟一个存放字面值为“A”的地址,接着创建一个新对象String b,并将b的字符串值指向这个地址,而且在栈中这个地址旁边记下这个引用的对象b;如果有了值“A”,则查找对象b,并返回吧的地址。
- 将a指向对象b的地址。
例子:
String a = "A";
String b = "A";
System.out.println(a == b) // true
new()来新建对象的,都会在堆中创建
当比较包装类里面的数值是否相等时,用equals()方法;当测试两个包装类的引用是否指向同一个对象时,用==
常量池
常量池用于存放常量
非RAM存储
非RAM存储用于存放持久化对象
JAVA的JVM的内存可分为3个区:堆(heap)、栈(stack)和方法区(method)
堆区:
1.存储的全部是对象,每个对象都包含一个与之对应的class的信息。(class的目的是得到操作指令)
2.jvm只有一个堆区(heap)被所有线程共享,堆中不存放基本类型和对象引用,只存放对象本身
栈区:
1.每个线程包含一个栈区,栈中只保存基础数据类型的对象和自定义对象的引用(不是对象),对象都存放在堆区中
2.每个栈中的数据(原始类型和对象引用)都是私有的,其他栈不能访问。
3.栈分为3个部分:基本类型变量区、执行环境上下文、操作指令区(存放操作指令)。
方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。