📜  如何防止类的对象从Java中的垃圾收集

📅  最后修改于: 2022-05-13 01:55:01.889000             🧑  作者: Mango

如何防止类的对象从Java中的垃圾收集

Java中的垃圾收集器是自动的,即用户不必手动释放动态分配的占用内存。垃圾收集器如何决定要删除哪个对象?这很简单:失去它的引用的对象,被标记为从堆内存中删除。例如,看下面的一段代码:

// Java code to demonstrate when an object would
// be deleted by the garbage collector
  
class A {
    void f()
    {
        A x = new A(); /*object created locally
              It's scope remains valid till the
              termination of this function*/
    }
    public static void main(String a[])
    {
        f();
  
        /* function f() terminates, 
           and hence the object 'x' 
           too gets collected 
           by the garbage collector*/
    }
}

上面的代码表明引用变量“x”的作用域仅限于函数“f()”。因此,在上述函数终止后,变量也无法识别。因此,创建的对象失去了它的引用,因此被垃圾收集器收集。

垃圾收集器收集的对象被收集以释放堆内存,其中分配了动态内存。下图解释了Java程序中的不同内存段及其用途:

但是,有时经常会出现这样的问题: “有没有一种方法可以防止垃圾收集器收集对象?”

有几种方法可以使Java中的对象不可删除。下面讨论它们:

通过增加堆内存

Java在称为“堆”的分区中为其对象分配内存(字符串和其他一些在池中分配内存的特殊对象除外)。由于堆内存是有限的,所以总是需要释放一些内存来容纳新对象的空间。但是,我们可以在一定程度上通过增加堆大小使对象不可删除。以下 jvm 命令行参数可以完成工作:

  • 毫秒
  • xmx

    Xmx 指定Java虚拟机 (JVM) 的最大内存分配池,而 Xms 指定初始内存分配池。下面是一个例子:

    java -Xms256m -Xmx2048m classfile

    在这里,在上面的示例中,您从最初分配的 256 MB 堆内存开始,可以将其扩展到最大 2048MB 的堆大小。

    这种方法导致垃圾收集器不经常运行,但是当它运行时,完成垃圾收集任务所需的时间会比以前更长。

    通过使用单例类

    在单例类的情况下,创建的唯一对象的引用可以存储在静态引用中。由于静态成员存储在类区域(内存段)中,因此它们的生命周期跨越程序的生命周期。以下程序解释了如何做到这一点:

    public class Singleton {
      
        /* static class member which 
           will store the object reference*/
        private static Singleton uniqueInstance;
      
        private Singleton()
        {
        }
      
        public static synchronized Singleton getInstance()
        {
            if (uniqueInstance == null) {
                uniqueInstance = new Singleton();
            }
            return uniqInstance;
        }
    }
    

    上面的例子表明,由于对象的引用已经被传递到一个静态变量中,所以它永远不会丢失。因此,直到程序结束,对象才会被删除。但是,唯一的问题仍然是在这里只能创建一个对象。

    使用 public void finalise()

    Finalize 是一个回调方法(由 JVM 调用的方法,而不是由用户调用的方法),即在对象上执行的最后一个方法。子类可以覆盖 finalize 方法来处理系统资源或执行其他清理。

    如何使用 finalize 防止垃圾收集?

    可以重写类的 finalize 方法以保留即将被删除的对象的引用。以下程序演示了如何:

    // Java code to demonstrate how to prevent garbage collection
    // of an object using finalize method
    class A {
        static A y;
        void f()
        {
            A x = new A();
        }
        pubic void finalize()
        {
            y = this; // Putting the reference id
            // of the current object
            // into the static variable y
      
            System.out.println("Object reference saved. The object
                  won't be collected by the garbage collector");
        }
        public static void main(String a[])
        {
            f(); // function called
        }
    

    输出:

    Object reference saved. The object won't be collected by the garbage collector

    如前所述,finalize 是在对象上执行的最后一个方法。在上面的程序中,函数'f()'创建了一个类A的本地对象。当函数调用终止时,变量'x'的作用域也终止,因此被标记为被垃圾回收集电极。但是,在垃圾收集器可以删除对象之前,finalize 会运行。

    在方法“finalize”的主体中,可以看到类 A 的静态成员“y”被分配了当前对象的引用 id。结果,要删除的对象的引用id被保留,因此,该对象没有被删除。

    但是,重要的是要知道使对象不可删除是有风险的,并且会增加内存泄漏的机会。因此,不建议这样做。