java编程优化-内存管理
2010-11-28 22:03
260 查看
[ 2010-05-13 19:34:32.0 | 作者: 随想 类别: 基础强化 ] 来源:原创 浏览 2311
labels:java编程优化-内存管理 强引用 软引用 弱引用 java中的析构方法 jvm中对象的生命周期 垃圾回收
内存管理 垃圾回收,Jvm中的垃圾对象定义: 理解1:一个对象创建后放置在jvm的堆内存中.当永远不再引用这个对象时,他将被jvm在堆内存中回收,被创建对象不能再生, 同事也没办法通过程序语句释放他们. 理解2:当对象在jvm运行空间中无法通过根集合到达时,这个对象就被称作垃圾对象. 根集合是由类中的静态引用域与本地引用组成的. jvm中对象的生命周期,分为7个阶段 创建阶段,应用阶段,不可视阶段,不可到达阶段,可收集阶段,终结阶段,释放阶段. 创建对象的几个规则: (1) 避免在循环体中创建对象,即使该对象占用内存空间不大. for(int i = 0; i < 10000; i++){ Object obj = new Object(); //应当避免 System.out.println("obj "+obj); } Object o = null; for(int i = 0; i < 100000; i++){ o = new Object(); //仅在内存中保存一份对象的引用,可取 System.out.println("obj "+o); } ----------------------------------------------------------------------------- public class demo{ private List list = new ArrayList(); public demo(){ list = new ArrayList(); //将对象初始化了2次,大大影响效率 } } (2) 尽量及时使对象符合垃圾回收标准 不要采用过深的继承层次 访问本地变量优于访问类中变量 强引用 jvm内存管理器从跟引用集合出发遍寻堆中所有到达对象的路径.当到达某对象的任意路径都不含有引用对象时.被称为强引用. 软引用 主要特点是具备较强的引用功能,只有当内存不够的时候,才会回收这类内存,因此在内存足够的时候,他们通常不被回收. 另外,这些引用对象还能保证java跑出OutOfMemory异常之前,被设置成null.它可以用于实现一些常用的资源缓存, 实现Cache的功能.保证最大限度的使用内存不引起OutOfMemory. public static void main(String[] args) { A1 a1 = new A1(); //使用a1 System.out.println(a1.c); System.out.println(a1); //使用完a1 将它设置为soft引用类型,并且释放强引用 java.lang.ref.SoftReference sr = new java.lang.ref.SoftReference(a1); a1 = null; System.out.println(a1); //下次使用的时候 if(sr != null){ a1 = (A1) sr.get(); }else{ //GC 由于低内存,已经释放a1 因此需要重新装在 a1 = new A1(); sr = new java.lang.ref.SoftReference(a1); } System.out.println(a1); } 弱引用 对象与Soft引用对象的最大不同就在于,gc在进行回收时,需要通过算法检查是否回收soft引用对象, 而对weak引用对象,gc总是进行回收,weak引用对象更容易,更快的呗gc回收.虽然,gc在运行时一定回收 weak对象,但是复杂关系的weak对象群常常需要好几次gc的运行才能完成.weak引用对象常常用于 map结构中.引用占用内存空间较大的对象.一旦该对象的强引用为null时,对这个对象引用就不存在了, gc能够快速地回收该对象空间. public static void main(String[] args) { Demo demo = new Demo(); //使用.... System.out.println(demo+" "+demo.c); //...使用完事将它设置为weak引用类型,并释放强引用 java.lang.ref.WeakReference wr = new java.lang.ref.WeakReference(demo); demo = null; System.out.println("demo 没了 "+demo); //...下次使用的时候 if(wr != null){ demo = wr.get(); }else{ demo = new Demo(); } //再次使用 System.out.println(demo+" "+demo.c); } 虚引用 用途较少,主要用于辅助finalize函数的使用. 强调: 在实际程序设计中一般很少使用弱引用和虚引用,使用软件的情况较多,这是因为软件引用可以加上jvm 对内存的回收速度,可以维护系统的运行安全,防止内存溢出(OutOfMemory)等问题产生 不可视阶段 当一个对象处于不可视阶段,说明我们在其他区域的代码中已经不可以在引用它了, 强引用已经消失.例如,本地变量超出了可视范围. public void pore(){ if(true){ Object object = new Object(); object.getClass(); } if(true){ //这个区域对于object对象来说已经是不可视的了. //因此下面的代码在编译时就会引发错误 object.getClass(); } } 如果一个对象在使用完之后,而且在其可视范围区域不在使用,此时应该主动将其设置为空, 可以在object.getClass();下行加上object = null;这样一行代码强制将object对象设置为空值. 这样做的意义在于,可以帮jvm及时地发现这个垃圾对象,并且可以及时地回收该对象所占用 的系统资源. 数组空间的申请分为显示申请and隐式申请. public static void main(String[] args) { int[] as = new int[1024]; //上面这行代码就是显示的相系统一次性的申请了大小为1kb的整数类型的内存空间 //如果实际需要放入的字眼不足1024 就会浪费资源应该尽可能的用完就马上体现jvm回收 String[] strs = new String[222222]; SoftReference sf = new SoftReference(strs); //用完..... strs = null; } 不要提前创建对象 尽量在需要的时候在创建对象,重复的分配,构造对象可能会因为垃圾回收做额外的工作, 降低性能. void fn(){ int i; A a = new A(); // 类A的对象a被创建 //在判断语句之外并没有应用过a. if(true){ // 类A的对象a再次应用 a.findMethod(); ... } ... } 应该这么写 void fn(){ int i; ... if(true){ A a = new A(); a.findMethod(); ... } }
而在java语言中只有构造的概念,却没有析构的概念,这是因为理论上jvm负责对象的
析构方法,由于在java应用中开发的所有类都为Object的子类,因此用户类都从Object
因此finalize的最后一句通常是super.finalize().通过这种方式买我们可以实现从下到上
<FONT color="#5c585a" face=""">finalize调用.即先释放自身在主机往上释放.
package com.iwgod.chapter02.finalize; public class A { Object a = null; public A(){ a = new Object(); System.out.println("构建A对象"); } protected void destory(){ a = null; System.out.println("释放a对象"); } protected void finalize() throws Throwable{ destory(); super.finalize(); //递归调用超类的finalize方法 } }
package com.iwgod.chapter02.finalize; public class B extends A { String b = null; public B(){ b = "aa"; System.out.println("构建B对象"); } protected void destory(){ b = null; System.out.println("释放b对象"); super.destory(); } protected void finalize() throws Throwable{ destory(); super.finalize(); } }
package com.iwgod.chapter02.finalize; public class C extends B { Object c = null; public C(){ c = new Object(); System.out.println("创建C对象"); } protected void destory(){ c = null; System.out.println("释放c对象"); super.destory(); } protected void finalize() throws Throwable{ destory(); super.finalize(); } }
package com.iwgod.chapter02.finalize; public class Test { /** * @param args * @throws Throwable */ public static void main(String[] args) throws Throwable { // TODO Auto-generated method stub C c = new C(); c.destory(); } /** * 注意到test类中实例化C对象的时候,其构造器产生了递归调用,并且是由几类开始 * 一次调用,初始化成员对象,而当调用c类的destory方法时系统通用产生了递归调用 * 但调用的顺序恰好相反.释放资源由子类开始, * 由此可见我们在设计类时尽量避免在类的默认构造器中创建,初始化大量的对象,防止在调用其自身的构造器 * 时造成不必要的内存浪费,因为即使我们没有像调用父类的构造器创建大量无用的对象,但是喜用都会自动去 * 创建它们,而这些操作都是隐含的 */ }
相关文章推荐
- Java优化编程--内存管理
- 【JAVA优化编程】内存管理之——(1)垃圾回收
- 【JAVA优化编程】内存管理之——(2)JVM中对象的生命周期
- 【JAVA优化编程】内存管理之——(3)Java中的析构方法finalize
- 【JAVA优化编程】内存管理之——(4)数组的创建
- 【JAVA优化编程】内存管理之——(5)共享静态变量存储空间
- 【JAVA优化编程】内存管理之——(6)对象重用与GC
- 【JAVA优化编程】内存管理之——(7)瞬间值
- JAVA 数据库编程中的性能优化
- Java并发编程:Synchronized底层优化(偏向锁、轻量级锁)
- java代码优化编程
- java的properties文件-jdbc优化编程(五)
- Java的无锁编程和锁优化
- 探索并发编程(六)------Java多线程性能优化
- 优化Java动画编程中的显示效果
- CORBA对象生命周期之实现和内存管理-Java基础-Java-编程开发
- Java并发编程:Synchronized底层优化(偏向锁、轻量级锁)(转)
- Java 技术: 使您轻松地进行多线程应用程序编程(生产者消费者模式的优化)
- Java 多线程编程 — 锁优化
- Java并发编程:Synchronized底层优化(偏向锁、轻量级锁)