通常Java内存分配会涉及到以下几个区域:
- 寄存器:在CPU内部,通常开发人员不能通过代码来控制的部分,主要是有编译器自己来管理的
- 栈:存放基本类型的数据和对象的引用,对象本身不存放在栈中,而是存放在堆中
- 堆:存放对象,也就是通常在Java中new产生的数据
- 静态区域:存放程序中定义的static的静态成员
- 常量池:存放常量,如final定义的
- 非RAM存储:硬盘等永久存储空间,如持久化对象等等
对于理解Java中的内存分配主要是栈(stack)和堆(heap)内存
1、栈——stack
a、在栈中存放的是基本数据类型定义的变量以及对象的引用变量,比如:定义变量int a=3,b=3;定义对象引用String str ;HelloWorld hello;等这样的数据都是存放栈内存中
b、栈中存放的数据是可以共享的,如:int a = 1 ; int b = 1 ;这里不会对数据1存储两次,第二次定义的变量b的值所指向的变量a定义时的值1,如果b=2,那它会先遍历栈中的所有数据是否有值1存在,如果没有,那么它将重新申请一块栈内存资源来存放值2
c、栈的存取速度比堆要快,仅次于寄存器。
d、栈中的内存是随着作用区域来回收的,当这个变量或者对象引用在这个作用范围的代码块执行结束之后就自动释放了
缺点:存在栈中的数据大小与生存期必须是 确定的,缺乏灵活性。
2、堆——heap
a、堆内存是用来存放由new创建的对象和数组的
b、堆中的内存大小是动态分配的,所以它是运行时内存,由Java GC自动回收。
如:
A a = new A();
通常辨别栈内存和堆内存,对于如上的这个表达式,=左边的就是存放在栈内存中,=右边的就是存放堆内存中。A a就是存在在栈内存中的一个对象的引用,这个引用就是指向堆内存中的new A()。
缺点:栈内存是运行到作用范围之外之后释放掉内存,而堆中的数组和对象,及时运行到所在的代码块之外,数组和对象本身占据的内存是不会被释放的,数组和对象在没有引用变量指向它时,就变为垃圾,不能再被使用,但仍旧占据着内存空间不放,在随后一个不确定的时间被垃圾收集器回收走。所以这就是Java比较占内存的原因。
备注:实际上,栈中的引用变量指向堆中的new对象,就是java中的指针。