Skip to content

Commit

Permalink
Update TROUBLESHOOT.md
Browse files Browse the repository at this point in the history
  • Loading branch information
polina-c authored Jul 28, 2023
1 parent 6bf48bb commit 35fa7b7
Showing 1 changed file with 19 additions and 12 deletions.
31 changes: 19 additions & 12 deletions doc/TROUBLESHOOT.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ switch to [more complicated troubleshooting](#more-complicated-cases).

## General rules

Follow these general rules to avoid/fix notGCed and notDisosed leaks:
Follow the rules to avoid/fix notGCed and notDisosed leaks:

1. **Ownership**. Every disposable object should have clear owner that manages its lifecycle.
2. **Disposal**. The owner should dispose the disposable.
3. **Release**. The owner should release all links to the disposed object (unless disposal happens
in owner's `dispose`, because in this case links to the owner should be released and
thus enable garbage collection).
4. **Weak referencing**. Not owners should either store WeakReference for the object, or make sure to
release the references becore owner disposed the objec.
4. **Weak referencing**. Non-owners should either link the object with WeakReference, or make sure to
release the references becore the owner disposed the object.

## Known simple cases

Expand Down Expand Up @@ -97,27 +97,34 @@ or, if it is a test, by clicking `Debug` near the test name in IDE.
If you see notGCed leaks, where the retaining path starts with a global or static variable,
this means that some objects were disposed, but references to them were never released.

In this example, as `disposedD` is not needed anymore, it should stop being referenced when disposed.
In this example, as `disposedC` is not needed anymore, it should stop being referenced when disposed.
If `A` and `B` are still needed, `B` should assign null to the variable that references `disposedD`.
Otherwise, the reference to the first non-needed object on the path (`staticX`, `A` or `B`) should be released.

```
root -> staticX -> A -> B -> disposedD
root -> staticX -> A -> B -> disposedC
```

To fix the leaks, you need to release closest to the root object on retaining path
(first check `staticX`, then `A`, then `B`), that is not needed any more.
To fix the leaks, you need to release the closest to the root object on the retaining path
(starting with `staticX`, then `A`, then `B`), that is not needed any more.
This will make all objects, referenced from it, unreachable, and thus available for garbage collection.

If object is held by owner, null it out:
If the object is disposed by owner in the owner's dispose, check who holds the owner and release the reference to it:
```
_leakingObject?.dispose();
_leakingObject = null;
void dispose() {
_disposedC.dispose();
}
```

If the object is disposed earlier than owner's disposal, null the reference out:
```
_disposedC?.dispose();
_disposedC = null;
```

If object is held by non-owner, convert the reference t weak:
If the object is held by non-owner, make the reference weak:
```
final WeakReference<MyClass> leakingObject;
final WeakReference<MyClass> disposedC;
```


Expand Down

0 comments on commit 35fa7b7

Please sign in to comment.