8

Consider the simple example in Java below. What happens if I create an object by calling new B(0)? First, an object of type B in created in memory. Then, the expression 1/n will throw an exception. But the created object will never become finalized according to the Java spec (§12.6.1) below. So do we get a memory leak?

Please note that I am not asking "can a constructor throw an exception", but "what happens if a constructor throws an exception in a particular situation."

An object o is not finalizable until its constructor has invoked the constructor for Object on o and that invocation has completed successfully (that is, without throwing an exception).

class A {
    int n;
    A(int n) {
        this.n = n;
    }
}

class B extends A {
    B(int n) { 
        super(1/n);
    }
}
  • 2
    I think "finalizable" refers to `finalize()` being called when the object is GCed, *not* whether or not the object will get GCed. – David Ehrmann Mar 05 '16 at 17:10
  • 3
    Possible duplicate of [Can constructors throw exceptions in Java?](http://stackoverflow.com/questions/1371369/can-constructors-throw-exceptions-in-java) – mawalker Mar 05 '16 at 17:10
  • @DavidEhrmann Exactly. Whether or not an object is finalizable is largely irrelevant as there are almost no scenarios where you should use finalizers. – biziclop Mar 05 '16 at 17:15
  • 2
    @DavidEhrmann: If true, that would answer my question, but the spec says: "Before the storage for an object is reclaimed by the garbage collector, the Java virtual machine will invoke the finalizer of that object." –  Mar 05 '16 at 19:12
  • 1
    @Lancel Good point. The spec may be a bit unclear on this but if the finalizer can't be called, GC proceeds anyway. – biziclop Mar 05 '16 at 19:33
  • There is a lot of very interesting information about this in http://stackoverflow.com/questions/1371369/can-constructors-throw-exceptions-in-java (don't focus on the title) – Jean-Baptiste Yunès Mar 05 '16 at 21:56
  • @Jean-BaptisteYunès What is interesting about the finalizer attack mentioned there is that it does not work in this case. If the exception is thrown **before** the constructor of `Object` is reached, `finalize()` is not invoked (though the object seems to be collected correctly in my tests). – biziclop Mar 05 '16 at 22:02
  • @biziclop On the other hand, when an exception is thrown before `Object` is initialised, there is no way the object can hold any non-trivial state, so for all intents and purposes it doesn't exist yet. The allocated memory can be reclaimed straight away without even going to GC. – biziclop Mar 05 '16 at 22:16
  • If an object isn't constructed, it's not "collected" by the GC. Nothing references it, and memory allocated for it can be immediately reclaimed. – erickson Mar 05 '16 at 22:42
  • @erickson That isn't always true, only if the exception is thrown before `super()` is called. Otherwise the constructor can leak the reference to `this`, so GC must become involved. It does seem though that GC is invoked in both cases. – biziclop Mar 05 '16 at 22:57
  • @biziclop I see, that makes sense. Thanks! – erickson Mar 06 '16 at 00:12

1 Answers1

4

The section you're quoting distinguishes between reachability and finalizability:

Every object can be characterized by two attributes: it may be reachable, finalizer-reachable, or unreachable, and it may also be unfinalized, finalizable, or finalized.

So an object can be reachable or unreachable, and finalizable or not finalizable, independently.

In the case you mention, the Object constructor has never run, so the object isn't finalizable, but OTOH the constructor has thrown an exception so the assignment of the new result to a variable never happens, so it is unreachable.

So there is no memory leak.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • 1
    You can run [this little test](http://pastebin.com/A5tMhAxw) with `-verbose:gc` to verify this. In fact the "failing" case runs much faster and clears out the memory much faster, which only sounds surprising until you look into how finalization is implemented, and how it holds up GC and slows everything down – biziclop Mar 05 '16 at 22:38