2

On interview I got a question - "How to help garbage collector when writing code?".

In my opinion GC works really good and we don't need to use anything more than basic good code practices, later added that closing resources in finally clause help GC for sure but generally got suprised with such question.

Is there a good reply? Do we need to do something incredible to help garbage collector?

Michu93
  • 5,058
  • 7
  • 47
  • 80
  • Seems very vague for an interview question. Also depends which garbage collector is in use. – khelwood May 30 '19 at 07:49
  • When we prevent garbage collector to do his work? when we leaking objects that not in use anymore(with anonymous classes or static references) – Pavel Poley May 30 '19 at 08:20
  • It is really weird question. Does not preventing collector's work count as helping? Because that's what most of those things do. – Amongalen May 30 '19 at 08:24

3 Answers3

2

The Garbage Collector is a "task" that periodically scans your objects to detect what is not in use (in reality it is a mechanism to emulate a machine with an infinite memory).

For this reason, when you are holding a reference to an object instance you no longer need, you must set it to null in order to let the Garbage Collector know that you are no longer interested in that instance (and possibly its descendants).

This does not mean that you have to set every variable to null after use, but you have to watch for fields. As Java does not have a dispose pattern (see here for more information), you have to design your APIs to mimic it: when you are finished using an object instance which holds a reference you want to free, you have to add an appropriate method to perform such action.

Consider the following example:

class MyClass1
{
    int Field1;
    int Field2;
    int Field3;
    int Field4;
}

class MyClass2
{
    private MyClass1 m_MyReference;

    public MyClass2()
    {
        m_MyReference = new MyClass1();
    }

    public void DoSomething()
    {
        // do something here that uses m_MyReference.
    }
}

If an instance of MyClass2 is held but some other reachable instance of your program (e.g. a singleton, or some instance currently in the stack), you will never release the memory associated to MyClass1 as it is still referenced by m_MyReference.

Is this bad? It depends on that MyClass2 and MyClass1 are truly doing.

If you know that MyClass2 could have a very long lifespan and you want to retain the reference to MyClass2 but to release the memory associated to MyClass1, you have to do something similar to the code below:

class MyClass2
{
    private MyClass1 m_MyReference;

    public MyClass2()
    {
        m_MyReference = new MyClass1();
    }

    public void DoSomething()
    {
        // do something here that uses m_MyReference.
    }

    public void Dispose()
    {
        m_MyReference = null;
    }

}

This way you expose to the caller a way to signal that you are no longer holding a reference to instances you do not need.

Remember that simply assigning null to a variable or field, does not automatically release the memory. The Garbage Collector is asynchronous and runs when it decides so. Hope to have given the idea without going too deeper.

Yennefer
  • 5,704
  • 7
  • 31
  • 44
  • Most of the time you don't need to explicitly null references *to help the GC*, because object lifetimes are usually related. I.e. an instance of `MyClass2` in your case often becomes unreachable shortly after ending its lifecycle (dispose) anyway. There are exceptions of course. But it is rare that you keep using an object and only set one of its fields to null for no other reason than to help the GC. see https://stackoverflow.com/q/449409/1362755 for more details. – the8472 May 30 '19 at 14:08
  • You are right, the level and the precision of the reply is to match the answer. In my point of view, just doing the "right thing" is sufficient, therefore my answer was in that direction. Including the details like tree reachability, closures, etc... doesn't help writing good code, but simply tells you about non contractual details about the GC, which, after all, is an optimization. – Yennefer May 31 '19 at 11:31
  • Actually, you make matters worse, as now, the optimizer is required to recognize that your `m_MyReference = null;` is obsolete, as otherwise, this assignment is keeping the `MyClass2` instance alive longer than necessary. When you expect that someone will keep a reference to a `MyClass2` instance despite having invoked `dispose()` on it, you should rethink the software design. Recommended reads: [Can java finalize an object when it is still in scope?](https://stackoverflow.com/a/24380219/2711488) • [finalize() called on strongly reachable objects](https://stackoverflow.com/q/26642153/2711488) – Holger Jun 03 '19 at 14:11
1

Garbage collector is very efficent and dexterous in its work but we can enchance its's ability to collect garbage by pointing the variables and objects to null, which are not being used any more and there are no more references to them. During file handling use the close() and flush() methods. And in thread handling destroy the thread when not in use.

Michu93
  • 5,058
  • 7
  • 47
  • 80
  • Do you mean setting for example `anyVariable = null;` when we don't use it anymore? I don't think it's a good practice. – Michu93 May 30 '19 at 08:25
  • 1
    @Michu93 It's what Yash meant. If there are no references to the object then it can be garbage collected. If you're following other good practices (small methods, local variables etc.) it isn't' really needed - if variable's scope is as small as possible then that is not an issue. – Amongalen May 30 '19 at 08:30
  • If this does not work then to help gc we could limit the object creation by singleton class.Whats say about it – Yash Singhal May 30 '19 at 09:02
  • It really seems bit awkward question as java is known for its garbage collection technique – Yash Singhal May 30 '19 at 09:10
1

The question is phrased oddly. The GC does not need help with its work. It will work with whatever constraints are imposed on it or fail if the constraints cannot be met.

Of course the work can be altered, but this is not done out of a desire to ease the burden on the GC – it is not a human that can be bored by its work – but due to some ulterior motive, such as improving overall program performance.

These things are normally framed as latency, energy consumption, throughput or memory footprint optimizations. But those are not the only metrics a programmer cares about. Simplicity and code readability also matter.

Naive code can be more readable but less performant. If your goal is easy-to-read code then performing complex optimizations that reduce the GC load could be counter-productive and thus "helping the GC" is not a goal in itself.

Now if your goal is to improve some performance metrics then some optimizations also involve writing code that reduces the work done by the memory management (allocation + GC) subsystem. Some possible optimizations are avoiding finalizers, finding memory leaks, reducing unnecessary allocations, avoiding humongous Object[] arrays, tuning GC parameters, buying better hardware and reducing object lifetimes. Which optimization is applicable depends on the application and can best be figured out with profilers, GC logging and related

the8472
  • 40,999
  • 5
  • 70
  • 122