JVM的内存管理(2)

  上次说到了JVM的垃圾回收机制和JVM中对象的生命周期,今天给大家讲个方法,叫做析构方法finalize,我想搞过C++的人都知道,而且是内存管理技术中相当重要的一部分。但是,在Java中好像没有这个概念,这是因为,理论上JVM负责对象的析构(销毁与回收)工作,finalize是Object类中的一个方法,并且是protected,由于所有的类都继承了Object对象,因此,就都隐式的继承了改方法,不过可以重写这个方法,如果重写此方法,最后一句必须写上super.finalize()语句,因为finalize方法没有自动实现递归调用。那我们在什么时候要重写它呢?当有一些不容易控制并且非常重要的资源时,要放到finalize方法中,例如:一些I/O的操作,数据的连接等等,这些资源的释放对整个应用程序是非常关键的。

  我先让大家看一段代码:

  1publicclassTestA{2 Object obj=null;3publicTestA(){4 obj=newObject();5 System.out.println(“创建obj对象”);6 }78protectedvoiddestroy(){9 System.out.println(“释放obj对象”);10 obj=null;11//释放自身所占用的资源12 }1314protectedvoidfinalize()throwsjava.long.Throwable{15 destroy();16//递归调用超类中的finalize方法17super.finalize();18 }19}

  finalize方法最终是由JVM中的垃圾回收器调用的,由于垃圾回收器调用finalize的时间是不确定或者不及时的,调用时机对我们来说是不可控的,因此我们可以在自己的类中声明一个destory()方法,在这个方法中添加释放系统资源的处理代码,但是还是建议你将对destroy()方法的调用放入当前类的finalize()方法体中,因为这样做更保险,更安全。

  我们知道类中的静态变量在程序运行期间,其内存空间对所有该类的对象实例而言是共享的,为了节省系统内存开销、共享资源,应该将一些变量声明为静态变量。通过下面的例子,你就会发现有什么不同。

  代码一:

  1publicclassMemoryTest {2staticclassData{3privateintweek;4privateString name;5 Data(inti, String s){6 week=i;7 name=s;8 }9 }1011 Data weeks[]={12newData(1,”monday”),13newData(2,”Tuesday”),14newData(3,”Wednesday”),15newData(4,”Thursday”),16newData(5,”Friday”),17newData(6,”Saturday”),18newData(7,”Sunday”)19 };2021publicstaticvoidmain(String[] args) {22finalintN=20000;23 MemoryTest test=null;24for(inti=0; i<=N; i++) {25 test=newMemoryTest();26 }27 System.out.println(test.weeks.length);28 }29}

  代码二:

  1 public class MemoryTest {2 static class Data{3 private int week;4 private String name;5 Data(int i, String s){6 week = i;7 name = s;8 }9 }10 11 static Data weeks[] = {12 new Data(1,”monday”),13 new Data(2,”Tuesday”),14 new Data(3,”Wednesday”),15 new Data(4,”Thursday”),16 new Data(5,”Friday”),17 new Data(6,”Saturday”),18 new Data(7,”Sunday”)19 };20 21 public static void main(String[] args) {22 final int N = 20000;23 MemoryTest test = null;24 for (int i = 0; i <=N; i++) {25 test = new MemoryTest();26 }27 System.out.println(test.weeks.length);28 }29 }

  我想大家应该发现上面那两个类的区别了吧!

  代码一会在内存中保存20000个weeks的副本,而代码二则在内存中保存1个weeks的副本,然后共享该副本,这样的话就不会造成内存的浪费。

  虽然静态的变量能节约大量的内存,但是并不是所有的地方都适合用,建议大家在下列条件都符合的情况下,尽量用静态变量:

  (1)变量所包含的对象体积较大,占用内存较多。

  (2)变量所包含的对象生命周期较长。

  (3)变量所包含的对象数据稳定。

  (4)该类的对象实例有对该变量所包含的对象的共享需求。

  如果变量不具备上述特点,建议不要轻易使用静态变量,以免弄巧成拙。

  最后,再提一点内存的优化,就是有关对象的重用,比如:对象池和数据库连接池等。那样的话,是很节约内存空间的,不过,在用的时候要考虑各个方面,比如:运行环境的内存资源的限制等。为了防止对象池中的对象过多,要记得清除。好了,就到这里吧。

  相关链接:

  JVM的内存管理

喜欢就该珍惜,珍惜就别放弃。

JVM的内存管理(2)

相关文章:

你感兴趣的文章:

标签云: