`
zhang.jianjun
  • 浏览: 20219 次
  • 性别: Icon_minigender_1
  • 来自: 青岛
最近访客 更多访客>>
社区版块
存档分类
最新评论
  • NGG: 个人建议: 正确的做法应该是把样式放到外部css文件中,使用 ...
    js日期选择器

【JAVA优化编程】内存管理之——(3)Java中的析构方法finalize

阅读更多

3  Java中的析构方法finalize

    在C++程序设计中有构造与析构的概念,并且是内存管理技术中相当重要的一部分,而在Java语言中只有构造的概念,却没有析构的概念。这是因为理论上JVM负责对象的析构工作也就是之前讲到的垃圾回收的概念,其实Java语言中的finalize 方法类似于C++语言中的析构函数。finalize 方法是Java语言根基类Object类的一个方法,这个方法是保护类性质的方法(protected),由于在Java应用中开发的所有类都为Object的子类,因此用户类都从Object对象中继承了该方法。因此我们在子类中可以调用父类中的finalize 方法,由于finalize 方法没有自动实现递归调用,我们必须手动实现,因此finalize函数的最后一个语句通常是super.finalize()。通过这种方式,我们可以实现从下到上finalize 的调用,即先释放用户类自身的资源,然后再释放父类的资源。通常我们可以在finalize 方法中释放一些不容易控制、并且非常重要的资源,例如:一些I/O的操作,数据的连接。这些资源的释放对整个应用程序是非常关键的。

 

    由于GC调用finalize的时间是不确定的,有时我们需要通过其他的手段来释放程序中所占用的系统资源,比如自己在类中声明一个destroy()方法,在这个方法中添加释放系统资源的处理代码,当你使用完该对象后可以通过调用这个destroy()方法来释放该对象内部成员占用的系统资源。并且最好在类的finalize 方法中添加资源释放代码,这样做更为保险、安全。在类深度继承的情况下,这种方法显得就更为有效,我们可以通过递归调用destroy的方法在子类被销毁的时候释放父类所占用的资源,例如下面的代码:

 

    原始基类A

public class A {

    Object a = null;

    public A() {
        a = new Object();
        System.out.println("创建a对象");
    }

    protected void destroy() {
        System.out.println("释放a对象");
        a = null;
        // 释放自身所占用的资源
    }

    protected void finalize() throws java.lang.Throwable {
        destroy();
        super.finalize(); // 递归调用超类中的finalize方法
    }
}

 

 

    一级子类B

public class B extends A {

    Object b = null;

    public B() {
        b = new Object();
        System.out.println("创建b对象");
    }

    protected void destroy() {
        b = null;
        // 释放自身所占用的资源
        System.out.println("释放b对象");
        super.destroy();
    }

    protected void finalize() throws java.lang.Throwable {
        destroy();
        super.finalize(); // 递归调用超类中的finalize方法
    }
}
 

 

    二级子类C

public class C extends B {

    Object c = null;

    public C() {
        c = new Object();
        System.out.println("创建c对象");
    }

    protected void destroy() {
        c = null;
        // 释放自身所占用的资源
        System.out.println("释放c对象");
        super.destroy();
    }

    protected void finalize() throws java.lang.Throwable {
        destroy();
        super.finalize(); // 递归调用超类中的finalize方法
    }
}
 

 

    上面的三个类的继承关系是非常明晰的: A->B->C,类A是原始基类(这是一种习惯叫法),类B继承了类A,类C又继承了类B。其实类A并不是正真意义上的原始基类,之前我们已经提到过Java语言中的原始基类是Object类,尽管我们并没有显式的声明,但这已经是系统约定俗成的了。

 

    为了简单清楚地说明问题,我们在这三个类中分别声明了3个方法,用来论证上面所讲解的知识点,在类A中在其构造器中初始化了一个对象a,在destroy方法中通过a = null;释放其自身所占用的资源。在finalize方法中我们再次调用了destroy方法用来释放其自身所占用的资源,然后调用其超类Object的finalize方法,这是我们以上所提到的“双保险”的内存释放方法;类B与类C的结构与类A极为相似,它们除了释放自身的所占用资源外,它们还在其对应的方法中调用其超类的destroy方法与finalize方法,用来释放超类所占用的资源。

 

    如在类B中调用其超类A的destroy方法与finalize方法,在类C中调用其超类B的destroy方法与finalize方法。但是类A与类B、类C有一点不同的是在其destroy方法中它没有super.destroy();语句,这是因为其超类Object并没有destroy方法。下面看一下当我们调用初始化与销毁类C时会有什么样的情况发生。以下是调用完成这个过程的测试类Test的源代码:

public class Test {

    Object c = null;

    public Test() {
        c = new C();
    }

    public static void main(String args[]) {
        MyClass me = new MyClass();
        me.destroy();
    }

    protected void destroy() {
        if (c != null) {
            c.destroy();
        } else {
            System.out.println("c对象已被释放");
        }
    }
}
 

 

    编译执行Test.java:

        > javac Test.java

        > java Test

    下面是这个程序的运行结果:

        创建a对象

        创建b对象

        创建c对象

        释放c对象

        释放b对象

        释放a对象

 

    我们注意到当在Test类中初始化类C的对象时,其构造器产生了递归调用,并且是由基类开始依次调用、初始化成员对象的,而当调用C类对象的destroy方法时系统同样产生了递归调用,但调用的顺序却与初始化调用的顺序完全相反,释放资源的调用顺序是由子类开始的一次调用其超类的资源释放方法destroy。由此可见我们在设计类时尽可能地避免在类的默认构造器中创建、初始化大量的对象,防止在调用其自类的构造器时造成不必要的内存资源浪费,因为即使我们没有想调用父类的构造器创建大量无用的对象(至少有时候这些对象对我们是没有意义的),但是系统都会自动创建它们,而这些操作与过程对于我们来说是隐含的。

0
0
分享到:
评论

相关推荐

    Java中finalize()的用法

    Java 中的 finalize() 方法是垃圾回收器在回收对象时调用的第一个方法。finalize() 方法相当于析构函数,它是垃圾回收器回收一个对象时第一个要调用的方法。finalize() 方法的主要作用是释放对象占用的系统资源,...

    Java中finalize方法使用.doc

    finalize 方法是 Java 编程语言中一个非常重要的方法,它与 Java 编程中的垃圾回收器有着紧密的关系。当一个对象变成一个垃圾对象的时候,如果此对象的内存被回收,那么就可以调用系统中定义的 finalize 方法来完成...

    java基础优化编程

    可以通过在循环外部创建对象,并在循环内部复用,来优化内存使用。 #### 四、软引用与弱引用 软引用和弱引用是Java中用于实现缓存和内存管理的高级特性。软引用在内存不足时才回收,适合于实现缓存机制,如图片...

    Java中finalize方法.pdf

    Java中的`finalize()`方法是Java语言提供的一种机制,用于在对象被垃圾回收之前进行资源清理。这个方法在Java的`Object`类中被定义为`protected`类型,因此所有Java类都能够覆盖它来实现特定的清理操作。在垃圾回收...

    高性能JAVA开发之内存管理

    ### 高性能JAVA开发之内存管理 在Java开发过程中,内存管理是...在实际开发中,开发者应该尽量减少不必要的对象创建,合理利用现有的对象资源,同时关注垃圾回收机制,以便更好地优化内存使用,提高程序的整体性能。

    java IBM websphere 内存溢出 javacore deapdump CPU内存分析工具

    Java IBM WebSphere应用服务器在运行过程中可能会遇到各种性能问题,其中最常见的挑战之一是内存溢出。内存溢出是指应用程序消耗的内存超过了系统所能提供的限制,导致程序崩溃或性能急剧下降。在这种情况下,开发者...

    Java禁止使用finalize方法共2页.pdf.zip

    在Java编程语言中,`finalize()`方法是一个特殊的方法,它属于`Object`类,主要用于对象销毁前执行一些必要的清理工作。然而,随着Java版本的更新和垃圾收集机制的改进,`finalize()`方法逐渐失去了其原本的重要性,...

    详解Java编程中final,finalize,finally的区别

    Java编程中的`final`, `finalize`, 和`finally`是三个重要的关键字,它们各自在不同的场景下发挥着关键作用。理解这三个关键字的区别对于Java开发者来说至关重要,尤其是在面试中常常会被问及。 首先,`final`是一...

    Java内存泄露检测

    Java内存泄露检测是Java...总之,Java内存泄露检测是一个涉及编程规范、内存管理原理、内存泄露类型以及检测方法的综合问题。通过深入理解和实践,开发者可以有效地防止和解决内存泄露问题,提高程序的健壮性和性能。

    从C++编程转到Java编程

    【Java概述】 Java是一种由Sun Microsystems...尽管两者有许多相似之处,但Java的内存管理、类库支持以及安全性使其成为网络编程的首选语言之一。在实际转换过程中,理解这些差异并熟练掌握Java的新特性是至关重要的。

    Java编程中影响性能的细节

    在Java编程中,优化性能是开发者必须关注的重要环节。以下是一些关键的性能优化细节: 1. **使用单例模式**:单例模式可以确保一个类只有一个实例,从而节省资源和提高效率。不过,过度使用单例可能导致设计复杂性...

    Java并发编程面试题

    Java并发编程是指在Java程序中同时执行多个线程以提高程序的执行效率和响应速度的技术。并发编程可以带来许多优点,如提高程序的执行效率、改善用户体验等。但同时,Java并发编程也存在一些缺点,如线程安全问题、...

    java面试——南京-软通动力-Java中级.zip

    - **构造函数与析构函数**:了解构造函数的作用,何时调用,以及析构函数的概念(Java中没有标准的析构函数,但可以使用 finalize 方法)。 - **访问修饰符**:public、private、protected以及默认修饰符的权限...

    Java SE编程入门教程 java GC(共6页).pptx

    这些Java SE编程入门教程涵盖了从基础的变量和数据类型,到面向对象的特性,如类和对象、继承、封装和多态,再到高级主题如垃圾回收和内存管理,为学习Java编程提供了全面的指导。通过深入理解和实践这些概念,初学...

    jvm内存管理,pdf

    ### JVM内存管理详解 #### 一、引言 在探讨JVM内存管理之前,我们先来看一下为何要深入了解这一主题。对于深入掌握Java的人来说,内存管理是不可或缺的一部分。随着技术的发展,内存管理变得越来越自动化,但这也...

    java编程常见面试题目

    Java 编程语言中,面试时常会涉及到许多关键概念和技术,以下是对这些面试题目的详细解释: 1. **final, finally, finalize的区别** - `final`:用于声明类、方法或变量,表示不可变性。对于类,禁止继承;对于...

    Java专业编程指南

    最后,理解和掌握Java的内存管理,特别是垃圾回收机制,是提高程序性能的关键。了解何时对象会被垃圾收集,以及如何使用finalize()方法,有助于避免内存泄漏和提高程序效率。 总的来说,这个“Java专业编程指南”...

Global site tag (gtag.js) - Google Analytics