Java内存分配涉及到的区域:
静态域:存放对象中static定义的静态成员
栈:存放基本数据类型和对象的引用
堆:存放用new创造的对象
常量池:存放常量
Java内存分配中的栈:
在函数中定义的一些基本类型的变量数据和对对象(String,数组,对象等)的引用都存放在栈中,在执行函数时,Java就在栈中为这些定义的变量分配空间,当函数执行完毕时,Java会释放掉为这些变量所分配的内存
栈有一个很重要的特性,即栈中的数据可以共享
如:int a = 3; int b = 3;
在栈中创建了一个a变量的引用,然后查找栈中有没有3这个值,如果有,则将a指向3,如果没有则创建后将a指向3。再创建一个b变量的引用,查找有3这个值,则将b指向3,即a与b变量同时指向3。
要注意的是这种数据共享与两个对象引用指向同一个对象的共享是不同的,a值的修改并不会影响b的值。
字符串是一个特殊的包装类,其引用是存放在栈里的,而对象内容必须根据创建方式的不同而确定,有的是编译期已经创建好的,放在常量池中,有的是在运行时才被创建,使用new关键字,放在堆中。
(String的例子:
- String a = "ab";
- String bb = "b";
- String b = "a" + bb;
- System.out.println((a == b)); //result = false
分析:JVM对于字符串引用,由于在字符串的"+"连接中,有字符串引用存在,而引用的值在程序编译期是无法确定的,即"a" + bb无法被编译器优化,只有在程序运行期来动态分配并将连接后的新地址赋给b。所以上面程序的结果也就为false。
)
Java内存分配中的堆:
在堆内存中分配的数据,由Java垃圾回收站自动回收
在堆中产生的数组或对象后,可以在栈中定义一个特殊的变量,让栈中的这个变量的取值等于数组或对象在堆内存中的首地址,栈中的这个变量就成了数组或对象的引用变量。数组或对象在没有引用变量指向它时,才变成垃圾,但仍然占用着内存,在随后一个不确定的时间内才能被垃圾回收掉,这也是Java比较占内存的原因。