一、堆与栈
堆和栈是程序运行的关键,其间的关系有必要理清楚,两者如下图所示:
1. 堆:
所有线程共享,堆中只负责存储对象信息。
2. 栈:
在Java中每个线程都会有一个相应的线程栈与之对应(因为不同的线程执行逻辑有所不同,因此需要一个独立的线程栈),栈是运行单位,因此里面存储的信息都是跟当前线程(或程序)相关的信息,包括局部变量、程序运行状态、方法返回值等;
3. 总结:
栈是运行时的单位,而堆是存储的单位。
二、JAVA对象的大小
在Java中,一个空Object对象的大小是8byte,这个大小只是保存堆中一个没有任何属性的对象的大小。看下面语句:
Object a = new Object();
这样在程序中创建了一个对象a,它所占的空间为:4byte+8byte。4byte是栈中保存引用所需的空间,8byte是Java堆中对象的信息所占的空间。
因为所有的Java非基本类型的对象都需要默认继承Object对象,因此不论什么样的Java对象,其大小都必须是大于8byte。
再如创建如下一个对象:
Class NewObject {
int count;
boolean flag;
Object ob;
}
其大小为:空对象大小(8byte)+int大小(4byte)+Boolean大小(1byte)+空Object引用的大小 (4byte)=17byte。
但Java在对对象内存分配时都是以8的整数倍来分,因此大于17byte的最接近8的整数倍的是24,因此此对象的大小为24byte。
三、引用类型
对象引用类型分为强引用、软引用、弱引用和虚引用。
1. 强引用:
我们一般声明对象是时虚拟机生成的引用,强引用环境下,垃圾回收时需要严格判断当前对象是否被强引用,如果被强引用,则不会被垃圾回收;
2. 软引用:
一般被做为缓存使用。软引用在垃圾回收时,虚拟机会根据当前系统的剩余内存来决定是否对软引用进行回收。
如果剩余内存比较紧张,则虚拟机会回收软引用所引用的空间;如果剩余内存相对富裕,则不会进行回收。
换句话说,虚拟机在发生OutOfMemory时,肯定是没有软引用存在的。
3. 弱引用:
与软引用类似,都是作为缓存来使用。但与软引用不同,弱引用在进行垃圾回收时,是一定会被回收掉的,因此其生命周期只存在于一个垃圾回收周期内。
4. 总结:
我们系统一般在使用时都是用的强引用。而“软引用”和“弱引用”比较少见。他们一般被作为缓存使用,而且一般是在内存大小比较受限的情况下做为缓存,
因为如果内存足够大的话,可以直接使用强引用作为缓存即可,同时可控性更高。