转自:青竹少年
最近在看Java优化这方面的书,那必然会涉及到内存管理,我想和大家共同提高,于是写出来,如果有问题,希望能提出来,共同进步嘛!呵呵,不说这些了,好,现在开始你的知识之旅吧!
在做Java开发的时候常用的JVM内存管理有两种,一种是堆内存,一种是栈内存。堆内存主要用来存储程序在运行时创建或实例化的对象与变量,例如:我们通过new MyClass()创建的类MyClass的对象。而栈内存则是用来存储程序代码中声明为静态(或非静态)的方法。下面我给大家举个例子:
public class Test{ 2 static Vector list = new Vector(); 3 static void makeThings(){ 4 Object object = new Object(); 5 list.add(object); 6 } 7 public static void main(){ 8 makeThings(); 9 } 10 }
就拿上面的例子来说,放在栈内存中的有:main,makeThings,放在堆内存中有:Test,list,object。
JVM中对象的生命周期大致可以分为7个阶段:创建阶段、应用阶段、不可视阶段、不可到达阶段、可收集阶段、终结阶段与释放阶段。
1.创建阶段:
(1)为对象分配存储空间。
(2)开始构造对象。
(3)递归调用其超类的构造方法。
(4)进行对象实力初始化与变量初始化。
(5)执行构造方法体。
还有就是你在创建对象的时候需要注意的地方:
(1)避免在循环体中创建对象,即使该对象占用内存空间不大。
(2)尽量及时使对象符合垃圾回收标准。
(3)不要采用过深的继承层次。
(4)访问本地变量优于访问类中的变量。
2.应用阶段:
在应用阶段涉及到4个引用:
(1)强引用:是指JVM内存管理器从根引用集合出发遍寻堆中所有到达对象的路径。
(2)软引用:是具有较强的引用功能,只有当内存不够的时候,才回收这类内存,因此内存足够的时候,不会被回收。
(3)弱引用:弱引用与软引用对象的最大不同在于:GC在进行回收时,需要通过算法检查是否回收软引用对象,而对于弱引用来说,GC总是进行回收。
(4)虚引用:主要用于辅助finalize函数的使用。虚引用主要适用于以某种比Java终结机制更灵活的方式调度pre-mortem清除操作。
3.不可视阶段:
先看一段代码:
public void process(){ 2 try{ 3 Object obj = new Object(); 4 obj.doSomething(); 5 } 6 catch(Exception e){ 7 e.printStackTrace(); 8 } 9 while(isLoop){ 10 //这个区域对于obj对象来说已经是不可视的了 11 //因此下面的代码在编译时会引发错误 12 obj.doSomething(); 13 } 14 }如果一个对象已使用完了,应该主动将其设置为null,可以在上面的代码行obj.doSomething();下添加代码行obj=null;这样一行代码强制将obj对象置为空值,这样做的意义就是帮助JVM及时的发现这个垃圾对象,并且可以及时的回收该对象占用的系统资源。
4.不可到达阶段:
处于不可到达阶段的对象,在虚拟机所管理的对象引用根集合中再也找不到直接或间接的强引用,这些对象通常是指多有线程栈中的临时变量,所有已装载的类的静态变量或者对本地代码接口(JNI)引用。
5.可收集阶段、终结阶段与释放阶段:
当对象处于这个阶段的时候,可能处于下面三种情况:
(1)垃圾回收器发现该对象已经不可到达。
(2)finalize方法已经被执行。
(3)对象空间已被重用。
当对象处于上面三种清空的时候,虚拟机就可以直接将该对象回收了。