2

My question is rather specific, and hence difficult to search for. I am programming Java and learning the language. I have designed one class, called Experiment, in which I define common functions for all experiments, and default parameters.

For each specific experiment, say ExperimentA, I then subclass Experiment. Each time I want to run experiment A, I make an instance of ExperimentA, passing parameters to the constructor which then overrides the default parameters defined in Experiment. I have two questions. I posted both questions in the same post because I thought they might be related.

1) Is the design above reasonable? Initially I wanted to use interfaces, but I found out that values in interfaces must be constant, and it would therefore be impossible to override parameters.

2) I am having a problem of memory leaks when running multiple subsequent experiments of the same type with changed parameters.

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

For some reasons, objects that were retained by the e1 object are kept alive in the heap even after e1 has been assigned to a new ExperimentA object. I know this is a very general question, but I am new to Java, and some guesses as to what the problem might be could help me.

The only malpractice that I've been doing that I am aware of is making the default variables in Experiment public, instead of private and using getters, but I can't see how that should cause any problems in this context. Basically there are no references to the e1 object after the runExperiment() function has been executed and another ExperimentA object is created. Any ideas?

halfer
  • 19,824
  • 17
  • 99
  • 186
halfdanr
  • 373
  • 4
  • 11
  • Take a look at [this question](http://stackoverflow.com/questions/13531004/java-outofmemoryerror-strange-behaviour) – Sotirios Delimanolis Aug 06 '13 at 14:03
  • How exactly do you know that the objects are kept alive? What do you use for heap inspection? – Sethiel Aug 06 '13 at 14:08
  • I use Memory Analyser Tool, and go to the leaks suspects report. – halfdanr Aug 07 '13 at 01:03
  • I checked out the link, and verified that the problem remains, even if I don't use a for loops, like so: `Experiment e1 = new ExperimentA(rootFolder, 30, fixedLatency, nSTOrdersPerRound);` `Experiment.runExperiment(e1);` `Experiment e2 = new ExperimentA(rootFolder, 31, fixedLatency, nSTOrdersPerRound);` `Experiment.runExperiment(e2);` Even though there are no references to e1 after `e1.runExperiment` is executed, all the objects created by e1 are retained. :s – halfdanr Aug 07 '13 at 01:19

2 Answers2

0

Your Experiment class is static and you pass e1 to it's method.

What are the contents of runExperiment? Do you have any code that, for example, stores the parameter in an array?

If there are any references to the created object, it can not be garbage-collected. While the Experiment is static, I assume that that it's inner structures should have some management routines to clean up the experiments that are already done and disposable.

Piotr Zierhoffer
  • 5,005
  • 1
  • 38
  • 59
  • Yes, the parameters passed to the constructor are stored in internal public variables. There are no references to e1 after the for-loop, so shouldn't the object be cleaned up after runExperiment() is completed? runExperiment() is responsible for the creation of many objects, but these objects are only referred by the experiment class. However, what I can see is that all the objects created by each instance of ExperimentA are *not* garbage collected... And I am super puzzled by this, since they are not references by by any objects other than ExperimentA. – halfdanr Aug 07 '13 at 01:02
0

1) Have you considered making the default parameters available via a class called Experiment and a separate IExperiment interface which just has a method like "run"? That way you could have your default parameters more configurable. There are probably other options, some examples of the problems you're facing would be helpful.

2) When you return an object from a getter you are providing the caller with a reference to that object. So in this example "bar" will hang around until it is no longer needed by the caller of getBar() :

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

You could instead return a clone of bar. You may need to override the default implementation of clone() on the Bar class to ensure it is a deep copy (all the private values are independent of the original Bar).

Hanra091
  • 101
  • 5
  • My task is that I have to run repeated experiments with changed parameters. Each experiment writes a bunch of data to the disk, and after closing all the writers, the for-loop moves on to the next experiment. Since I make sure that the logs are closed, I don't need all the many objects created by the experiment, and they should therefore be destroyed, except that they for some reasons aren't. – halfdanr Aug 07 '13 at 01:12
  • Woops, I wanted to make a line break, but ended up posting instead. The reason for my architecture of having an abstract parent class which is subclassed by specific experiment implementations is that each experiment might have to override different parameters. When an experiment does not override a parameter, it should always use a predefined default value, specified in the abstract parent class. If I use an interface to define parameters, I would not have the flexibility of reverting to default parameters when an experiment doesn't override those params, since interface vars are constant. – halfdanr Aug 07 '13 at 01:16
  • I did it too! Ok, sounds like your experiment logic and the values you need to supply to the experiment are separable. There's a quite common design for this: one class to represent data and one class to do something with that data. Create a POJO which defaults to the default parameters, add setters to allow callers to modify those values as required and have your experiment implement some interface which accepts your parameters object. – Hanra091 Aug 07 '13 at 11:12
  • Something has just occurred to me, does Experiment.runExperiment assign any static variables? – Hanra091 Aug 07 '13 at 11:16