一、内存管理:
C、C++需要负责对象内存空间的及时释放,java有虚拟机自动内存管理机制,可以较轻松地使用对象。
内存分区,即运行时数据区域:
1.1.1程序计数器,线程私有。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依赖这个计数器完成。如果线程正在执行的是一个java方法,这个计数器记录的是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,这个计数器值则唯恐。此内存区域是唯一一个在java虚拟机规范中没有规定任何OutOfMemoryError情况的区域。
1.1.2Java虚拟机栈,线程私有。描述java方法执行的内存模型。用于存储局部变量表、操作数栈、动态链接、方法出口等。每一个方法从调用直至完成的过程,对应着一个栈桢在虚拟机栈中入栈到出栈的过程。该区域存在两种异常:如果线程请求的栈深度大于允许的,将抛出StackOverflowError异常;如果虚拟机栈动态扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。
1.1.3本地方法栈,同2,不过是针对调用本地(Native)方法的
1.1.4java堆,被所有线程共享,在虚拟机启动时创建。唯一目的就是存放对象实例。该区域是垃圾收集器管理的主要区域,由于收集器基本都采用分代收集算法,所以java堆还可以细分为:新生代和老年代。如果扩展时无法申请到足够的内存,就会抛出OutOfMemoryError异常。
1.1.5方法区,线程共享,存储已被加载的类信息、常量、静态变量等。OutOfMemoryError异常。运行时常量池属于方法区。
1.1.6直接内存,与调用本地函数库有关。
HotSpot虚拟机对象:基于java堆,
1.2.1创建对象:加载相应类实例——根据java堆是否规整采用“指针碰撞”或“空闲列表”的方式为对象分配内存——将分配到的内存空间初始化为零——对对象进行设置
1.2.2对象的内存布局:分3块区域:对象头、实例数据和对齐填充
1.2.3对象的访问定位:通过栈上的reference数据来操作堆上的具体对象,即一个指向对象的引用,对象访问方式:使用句柄和直接指针两种(图示P49)
二、垃圾收集器与内存分配策略
java内存运行时区域的各个部分,程序计数器、虚拟机栈、本地方法栈随线程而生,随线程灭,垃圾回收一般不会针对他们,而是针对java堆和方法区。
2.1判断对象是否存活的方法:a.引用计数算法;b.可达性分析算法,以一系列的称为"GC Roots"的对象作为起始点,向下搜索,所走过的路径称为引用链,若一个对象到起始点没有引用链,说明此对象不可用,可判定为可回收对象。更深地,即使可达性分析算法中不可达的对象,也并非“非死不可”,要真正判断其死亡,至少需要经历两次标记过程,finalize()方法是对象逃脱死亡的最后一次机会。
2.2 垃圾收集算法:标记-清除算法(1效率不高,2会产生不连续的内存碎片);复制算法(将内存缩小为原先的一半,代价过高);标记-整理算法;分代收集算法(该算法将java堆分为新生代和老年代,新生代每次垃圾收集时都会有大批对象死去,适合采用复制算法;老年代存活率高,必须使用“标记-清理”或“标记-整理”算法)。