0

I know there is a similar question has been answered in this post. However, I am still confused about whether java has the retain cycle problem as java also has the WeakReference class. So, are they serving the same purpose? What the difference between two of them?

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614
user762750
  • 159
  • 7
  • 2
    @user762750 you are asking way too many questions at a time. And your question from that link is a duplicate of an existing one, I am more than sure. – Eugene Jun 14 '21 at 15:40
  • 1
    An essential feature of Java and .NET weak references is that their usage cannot lead to dangling references to seemingly-valid objects. If code attempts to retrieve the target of a weak reference at a time when no strong references to the target exist, the attempt is guaranteed to either create a strong reference to the object (preventing it from being collected) or yield a null pointer. I don't think Swift's "weak" keyword offers such a guarantee. – supercat Jun 14 '21 at 15:44
  • 2
    As explained in [this answer](https://stackoverflow.com/a/51538486/2711488), attempts to solve reference cycles with weak references lead to fundamental restrictions to the way, the software has to be designed, which do not apply to Java. See [How does Java Garbage Collection work with Circular References?](https://stackoverflow.com/q/1910194/2711488) – Holger Jun 14 '21 at 15:44
  • 1
    @supercat it seems, Swift’s `weak` references get cleared when the referent is disposed. There’s another keyword, `unowned` that behaves like you described. Though, that begs the question, how the clearing of weak references is implemented. It sounds like you’ll get the worst of both worlds, traversing gc and reference counting. – Holger Jun 14 '21 at 16:00
  • @Holger: Normal usage patterns for weak references in reference-counted systems may ensure that they don't dangle, but it's impossible to efficiently handle multi-threaded code in a way that can guarantee that even an errant program can't create dangling references. By contrast, except in parts of a Java or .NET program that are marked as "unsafe", creation of dangling references will be impossible for code running in a "safe" context, even if that code is erroneous or maliciously crafted. – supercat Jun 14 '21 at 18:03
  • 1
    @supercat yes, multithreading is adding fuel to the flames. But even without it, when an object’s counter goes to zero, additional effort is needed to find existing weak references pointing to it, to clear them. With a tracing garbage collector, there’s no challenge, as the weak references are discovered in the process anyway. But with reference counting, no such mechanism exists and adding it means paying precisely those costs it actually tries to avoid. Plus having the disadvantages of reference counting. That’s what I meant with “worst of both worlds”. – Holger Jun 15 '21 at 11:07
  • @Holger: In the absence of threading issues, objects could hold a pointer to a linked list of weak references, and clean up all such references without having to search through all of memory to find them, and in general the cost of memory-management operations on references to an object would be a function of how many references there are to that same object, rather than the total number of live objects and whether the generational model is a good fit for their usage pattern. So I wouldn't say "worst of both worlds", but threading adds nasty complications. – supercat Jun 15 '21 at 16:33
  • @Holger: To my mind, the biggest advantage of a tracing GC is that code running in a "safe" context is incapable of creating dangling references,* even if it abuses threading in a malicious effort to create dangling references*. I don't think any other memory-management strategy can allow multi-threaded code to be sandboxed anywhere near as efficiently. – supercat Jun 15 '21 at 16:37
  • 1
    @supercat I suppose, a reference counting system that collaborates with the code generator the same way, the garbage collector does in a JVM, could reduce threading issues dramatically. However, maintaining a linked list of weak references is quite some complication to a system whose strength is the simplicity of “just maintain a counter”, especially, when you try to use it anywhere, to solve the reference cycle problem, rather than use it for rare corner cases as in Java. Think of a doubly linked list using a weak prev pointer to avoid cycles; each node will get an additional backref list… – Holger Jun 16 '21 at 06:28
  • @Holger: Mult-threaded reference counting will pose substantial unavoidable run-time expense. It avoids, however, the build-system complexity needed to ensure that the GC will know, for every register, *at every point in the program*, that a particular one of two things will always be true if/when that point in the program is reached: 1. The register will never hold the last live reference anywhere in the universe to an object, or 2. The register will either be zero or hold a valid object reference. If the requisite built-system complexity is acceptable, a tracing GC is IMHO a clear win. – supercat Jun 17 '21 at 15:20

1 Answers1

6

Java does not have the "retain cycle problem".

This problem exists for systems that use reference counting, which the Java GC does not use.

Therefore in Java the WeakReference class has nothing to do with those. It's simply a way to hold on to a reference to something while also not preventing it from being garbage collected

In other words, you can use it to remember an object as long as something else (strongly) references it.

This functionality is quite similar to what the weak keyword does in Swift. However, as described above, reference cycles don't stop objects from being collected in Java, so WeakReference is not needed in this specific case.

This SO question lists some practical uses for weak references and this question discusses uses specifically in an Java/Android environment.

Joachim Sauer
  • 302,674
  • 57
  • 556
  • 614