2013-08-06 81 views
2

像往常一样,如果我的问题已经在其他地方被请求,我很抱歉... 它是相当具体的,因此很难搜索。我是 编程Java和学习语言。我设计了一个名为 的实验,其中我为所有 实验和默认参数定义了常用函数。对于每个特定实验,例如 ExperimentA,然后我将实验分为子类。每次我想运行 实验A时,我创建一个ExperimentA实例,将参数传递给 构造函数,然后覆盖 实验中定义的默认参数。我有两个问题。我知道他们可能是 难以解决没有看代码,但我认为它 值得一试。此外,我在相同的帖子中发布了两个问题,因为我认为它们可能是相关的。Java for循环中的内存泄漏

1)上述设计合理吗?起初我想用 接口,但我发现接口中的值必须是 不变,因此覆盖参数是不可能的。

2)更加迫切和令人费解的是,当 运行多个相同类型的后续实验并更改了 参数时,我遇到了内存泄漏问题。由E1对象中保留了

for(int na:ArrayOfIntegers) { 
    Experiment e1 = new ExperimentA(na,otherArgs); 
    Experiment.runExperiment(e1); 
} 

由于种种原因,对象是在E1已被分配到一个新的ExperimentA对象即使堆维持生命。我知道这是一个非常普遍的问题,但我对Java很陌生,有些猜测问题可能会对我有帮助。我一直在做的唯一一个我所知道的做法是在Experiment中公开默认变量,而不是私有和使用getter,但我不明白在这种情况下应该如何引发任何问题。基本上,在runExperiment()函数执行完成并创建另一个ExperimentA对象后,没有对e1对象的引用。有任何想法吗?

预先感谢您!

+0

看看[这个问题](http://stackoverflow.com/questions/13531004/java-outofmemoryerror-strange-behaviour) –

+0

你究竟知道对象是如何保持活着?你用堆检查什么? – Sethiel

+0

我使用内存分析工具,并去泄漏的嫌疑人报告。 – onkel

回答

0

您的Experiment类是静态的,您将e1传递给它的方法。

runExperiment是什么内容?例如,你有任何代码将参数存储在数组中吗?

如果有任何对创建对象的引用,它不能被垃圾收集。尽管Experiment是静态的,但我认为它的内部结构应该有一些管理例程来清理已经完成并且一次性的实验。

+0

是的,传递给构造函数的参数存储在内部公共变量中。 for循环后没有对e1的引用,所以在runExperiment()完成后不应该清理对象? runExperiment()负责创建许多对象,但这些对象仅由实验类引用。但是,我能看到的是,ExperimentA的每个实例创建的所有对象都是* not *垃圾回收......并且我对此感到非常困惑,因为它们不是由ExperimentA以外的任何对象引用的。 – onkel

0

1)您是否考虑过通过名为Experiment的类和单独的IExperiment接口来创建默认参数,该接口只有一个类似“run”的方法?这样你可以让你的默认参数更具可配置性。可能还有其他选择,您遇到的问题的一些示例会很有帮助。

2)当你从一个getter返回一个对象时,你正在为调用者提供对该对象的引用。因此,在这个例子中“吧”会流连,直到它被getBar(的调用者不再需要):

public class Foo { 
    private Bar bar; 
    ... 
    public Bar getBar() { return bar; } 
} 

你可以改为返回酒吧的克隆。您可能需要覆盖Bar类的clone()的默认实现,以确保它是深层副本(所有私有值独立于原始Bar)。

+0

我的任务是我必须运行更改参数的重复实验。每个实验都将一堆数据写入磁盘,并在关闭所有写入程序后,for循环移至下一个实验。由于我确定日志已关闭,因此我不需要实验创建的所有对象,因此应该销毁它们,但由于某些原因它们不是。 – onkel

+0

Woops,我想做一个换行符,但结束了发布。我的架构中有一个抽象父类的原因是由特定的实验实现分类的,因为每个实验可能必须覆盖不同的参数。当实验不覆盖参数时,它应该始终使用在抽象父类中指定的预定义的默认值。如果我使用接口来定义参数,那么当实验不覆盖这些参数时,我将不具有恢复默认参数的灵活性,因为接口变量是常量。 – onkel

+0

我也做到了!好吧,听起来像你的实验逻辑,你需要提供给实验的值是可分离的。这里有一个非常常见的设计:一个类表示数据,一个类使用这些数据做一些事情。创建默认为默认参数的POJO,添加setters以允许调用者根据需要修改这些值,并让您的实验实现一些接受您的参数对象的接口。 – Hanra091