Java 卸载静态字段

Java 卸载静态字段,java,static,initialization,Java,Static,Initialization,我有一个java类,它使用复杂的静态字段,这些字段需要特殊操作,如close(),以便GC安全地清理它们 对于静态字段的初始化,我使用static块。但是我现在不知道如何安全地卸载静态字段,以便在GC清理字段之前调用close()方法 是否有类似于静态初始化块的方法卸载静态字段?否 静态类在您第一次使用它时在运行时加载,并且仅在程序退出时卸载(afaik) 因此,您可以在清理静态成员的类本身中创建一个静态方法close,并在退出时调用它。您可以设置一个来完成此操作,但可能无法完成所有操作。您可能

我有一个java类,它使用复杂的静态字段,这些字段需要特殊操作,如
close()
,以便GC安全地清理它们

对于静态字段的初始化,我使用
static
块。但是我现在不知道如何安全地卸载静态字段,以便在GC清理字段之前调用
close()
方法

是否有类似于静态初始化块的方法卸载静态字段?

静态类在您第一次使用它时在运行时加载,并且仅在程序退出时卸载(afaik)

因此,您可以在清理静态成员的类本身中创建一个静态方法
close
,并在退出时调用它。

您可以设置一个来完成此操作,但可能无法完成所有操作。您可能已经耗尽了内存,或者进程可能在没有清理机会的情况下被终止,等等


最好确保您的数据一致性不依赖于此代码和/或将其移动到在应用程序生命周期内定期清理的代码中。

没有办法执行您所要求的操作,因为加载类时静态块会初始化,finalize()只对对象起作用

考虑将静态变量和其中的复杂操作替换为单例类及其实例


这样,您可以使用
finalize()
方法执行
close()
操作。

在web应用程序中,您可以使用。

您考虑过finalize()的使用吗?我考虑过。但据我所知,finalize处理类的对象,而不是该类的静态字段。因此,finalize不是我的选项。可能使用一个静态字段来保存对该类对象的活动引用的数量(在构造函数中递增,在finalize()中递减),并在finalize()时调用close()或任何你对这些“复杂”静态的清理方法在递减后遇到0的引用计数就可以了-不过我还没有尝试过。如果是web应用程序,我如何知道何时退出?
ServletContextListener
比关闭web应用程序的钩子更可取。参见@Kublai,在servlet容器的上下文中,我同意,OP在她的问题中没有提到web应用上下文。但是,她在对Zom-B的回答的评论中提到了这一点-同意问题应该提到这一点。+1这是要走的路,IMO。在取消部署时只调用一次。如果需要,还可以在部署时显式地初始化这些静态字段,而不是等待加载它们的特定类。如果要避免实现单例,这似乎是一个巧妙的技巧。您甚至可以使用私有匿名类。这有什么不好的地方吗?只有在终结器真正被调用的情况下,这才有效。你到底为什么要公开Uninit构造函数?(显然,对于finalize(),您别无选择)正如阿基米德·特拉亚诺所说,终结器是不安全的,因为GC没有一致地调用它。我在创建OpenGL程序时犯了这个错误,必须重新处理所有内容。现在不推荐使用主循环(或应用程序使用的任何地方)清理upfinalize后,只需调用
close()
方法即可。如果您需要做一些事情来清理非内存资源,那么您必须做一个关闭钩子、servlet上下文侦听器或平台支持的其他关闭机制。
private static Uninit cleanup = new Uninit();
....
private static class Uninit { 
    public Uninit() {} 

    public void finalize() {

                     //whatever you need done

    }
}