简体   繁体   English

为什么要收集垃圾

[英]Why is this being garbage collected

My developers and I are having an issue with objects being garbage collected in our application when we don't want them to be. 我和我的开发人员遇到一个问题,就是当我们不希望对象成为对象时,它们就会被垃圾回收到应用程序中。 We are using Java with Weblogic 10g3. 我们将Java与Weblogic 10g3一起使用。 We are programming a singleton pattern to handle all of our JMS connections. 我们正在编写一个单例模式来处理我们所有的JMS连接。

There are two classes involved: 涉及两个类:

public class JMSObject {
...
private MessageProducer _producer;
private MessageConsumer _consumer;
...
// standard get/set procs... etc.
}

public class JMSFactory {
...
// Hashmap sessions with key == ConnectionFactory Name
    Hashmap<String, List<Session>> _sessions;

// Hashmap of JMSObjects with key == ConnectionFactory Name + JMS Queue Name
    Hashmap<String, List<JMSObject>> _jmsobjects;
...
// standard get/set & necessary sington functions
}

The init method of the Servlets calls the JMSFactory singlton method, any new Sessions are placed in the _sessions Hashmap and new MessageConsumer/MessageProducers are created as a JMSObject and placed in the _jmsobjects Hashmap, in the appropriate List. Servlet的init方法调用JMSFactory singlton方法,任何新的Session都放置在_sessions Hashmap中,新的MessageConsumer / MessageProducers被创建为JMSObject并放置在_jmsobjects Hashmap中,在适当的List中。

The problem is that when the system is running the JMSObjects in the list get garbage collected after some time (sometimes in 5 minutes other times after a few hours.) We looked at this for a few days but could not find any reason for the JMSObjects to be garbarge collected. 问题是,当系统运行列表中的JMSObject时,会在一段时间后(有时是在5小时后的5分钟内,有时是在5分钟后的其他时间)收集垃圾。我们花了几天的时间,但找不到JMSObjects的任何原因被垃圾收集。 Since the JMSFactory has a reference to them why would the gc destroy them? 既然JMSFactory引用了它们,为什么gc会销毁它们?

In the end we fixed it by changing the classes as follows(without changing method interfaces): 最后,我们通过如下更改类来修复它(不更改方法接口):

public class JMSObject {
...
private List<MessageProducer> _producers;
private List<MessageConsumer> _consumers;
...
// standard get/set procs... etc.
}

public class JMSFactory {
...
// Hashmap sessions with key == ConnectionFactory Name
    Hashmap<String, List<Session>> _sessions;

// Hashmap of JMSObjects with key == ConnectionFactory Name + JMS Queue Name
    private Hashmap<String JMSObject> _jmsobjects;
...
// standard get/set & necessary sington functions
}

So far in testing the JMSObjects are not being gc'ed. 到目前为止,尚未对JMSObjects进行测试。 It has been running for 2 days. 它已经运行了2天。

Can someone explain why the indirect reference is causing the JMSObject to get gc'ed? 有人可以解释为什么间接引用导致JMSObject获得gc'ed吗? And why the Sessions in the _sessions Hashmap was not getting gc'ed? 以及为什么_sessions Hashmap中的Sessions没有得到gc'ed? Does it have anything to do with the fact the Sessions are built in Javax types and the JMSObject is something we wrote? 会话是用Javax类型构建的,而JMSObject是我们编写的,这与事实是否有关系?

Since the JMSFactory has a reference to them why would the gc destroy them? 既然JMSFactory引用了它们,为什么gc会销毁它们?

Well, are any objects still holding reference to the JMSFactory at this point? 那么,此时是否还有任何对象保留对JMSFactory的引用?

Typical singleton pattern keeps the reference to the singleton object in a static member: 典型的单例模式将对单例对象的引用保留在静态成员中:

public class Singleton {
    private static Singleton instance = new Singleton();

    private Singleton() {
        //constructor...
    }

    public static Singleton getInstance() { return instance; }
}

Is this not the pattern you are following? 这不是您遵循的模式吗? It is not possible to tell from the code you provided in your post, as you left out the actual singleton code... 由于您遗漏了实际的单例代码,因此无法从帖子中提供的代码中分辨出来...

(BTW, using Singletons for something like this sounds like it would cause pains, besides being hard to test. See Singletons Are Pathlogical Liars ) (顺便说一句,使用Singletons进行此类操作听起来很痛苦,除了难以测试。请参阅Singletons是病理性骗子

I think I know what your problem is, it's something I ran into a while back (on WebLogic 6). 我想我知道您的问题是什么,这是我前一段时间遇到的问题(在WebLogic 6上)。 I believe it has to do with WebLogic's dynamic class reloading, which WebLogic seems to do from time to time, even when you're not in a development environment (I'm guessing the web.xml is somehow getting touched by some service or something). 我认为这与WebLogic的动态类重新加载有关,即使您不在开发环境中,WebLogic也会不时地进行重新加载(我猜想web.xml在某种程度上受到某些服务或某些东西的影响) )。

What happened in our case was that like you, we have a single instance of an object that's defined as a static variable of some class, and just like you, it's initialized by a servlet that has it's load-on-startup parameter set. 在我们的案例中发生的事情是,像您一样,我们有一个对象的单个实例,该实例被定义为某个类的静态变量,并且像您一样,它由一个具有启动时加载参数集的Servlet初始化。 When WebLogic thinks there's a change, it reloads the webapp by garbage collecting the classloader (which is fine) but it doesn't re-initialize all the servlets that are marked "load-on-startup" (in our case, and I'm guessing yours, the servlet serves no purpose other than to initialize the static variable, there are no mappings to it, and so it cannot be invoke, the static variable gets GCed, but not-reinitialized, and the server needs to be restarted. 当WebLogic认为有变化时,它通过垃圾收集类加载器来重新加载webapp(这很好), 但是它没有重新初始化所有标记为“启动时加载”的servlet(在本例中,我是猜你想想,这个servlet除了初始化静态变量,没有映射之外没有其他用途,因此无法调用它,将静态变量放入GC,但不进行重新初始化,并且需要重新启动服务器。

In our case, our solution was to initialize the static variable in a static initializer. 在我们的例子中,我们的解决方案是在静态初始化程序中初始化静态变量。 The original developer used a servlet to initialize the variable because he wanted some servlet context information, which really wasn't necessary. 最初的开发人员使用servlet初始化变量,因为他需要一些servlet上下文信息,这实际上不是必需的。 If you need context information, you could try doing your initialization in a ServletContextListener . 如果需要上下文信息,则可以尝试在ServletContextListener中进行初始化。

Without having all of the code this a tough question to solve. 没有所有代码,这是一个棘手的问题。 But there are tools to help out. 但是有一些工具可以帮助您。

Try this link: http://blog.emptyway.com/2007/04/02/finding-memory-leaks-in-java-apps/ It provides information about using jhat and jmap. 试试这个链接: http ://blog.emptyway.com/2007/04/02/finding-memory-leaks-in-java-apps/它提供了有关使用jhat和jmap的信息。 Although the article is written to find memory leaks, it provides info on how to keep track of references to an object. 尽管写这篇文章是为了查找内存泄漏,但它提供了有关如何跟踪对对象引用的信息。 Maybe you can track down why your references are disappearing. 也许您可以追踪为什么您的参考文献消失了。

You said the Sessions in the _sessions map were not being GC'd, but the JMSObjects were not. 您说过_sessions映射中的Session不是GC,但JMSObject不是。 I doubt it's because it is something you wrote. 我怀疑是因为这是您写的。 It sounds like either the JMSFactory itself is being collected (ie singleton not implemented properly) or something is removing the keys from the maps. 听起来好像JMSFactory本身已被收集(即,单例未正确实现)或某些东西正在从映射中删除键。 In either case, the JMSObjects would be eligible for GC, but the session objects would not because the list still has a reference to them. 在这两种情况下,JMSObjects都可以使用GC,但会话对象不可以,因为列表仍然具有对它们的引用。

是否有可能卸载了加载JMSFactory的类加载器,从而导致JMSFactory类被GC处理(包括单例实例),从而释放了HashMaps及其内容?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM