https://github.com/sandec/jmemorybuddy
https://github.com/sandec/jmemorybuddy
java javafx memory-leaks unittest
Last synced: 5 months ago
JSON representation
- Host: GitHub
- URL: https://github.com/sandec/jmemorybuddy
- Owner: Sandec
- License: apache-2.0
- Created: 2019-10-30T19:50:21.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2024-10-29T19:23:29.000Z (about 1 year ago)
- Last Synced: 2025-07-28T09:02:26.394Z (5 months ago)
- Topics: java, javafx, memory-leaks, unittest
- Language: Java
- Size: 430 KB
- Stars: 50
- Watchers: 6
- Forks: 3
- Open Issues: 1
-
Metadata Files:
- Readme: README.md
- Changelog: CHANGELOG.md
- License: LICENSE
Awesome Lists containing this project
README
# JMemoryBuddy

[](https://maven-badges.herokuapp.com/maven-central/one.jpro/jmemorybuddy)
JMemoryBuddy provides an API to unit-test your code for memory leaks.
It also provides an API to monitor a running JVM for memory leaks.
It is used for internal projects at Sandec, especially for [JPro](https://www.jpro.one/).
We've made it public, so everyone can fix and test their code for memory leaks in a **professional** way.
**Together we can fix all memory leaks in the world. :-)**
## Dependency
The library is published at MavenCentral
#### Maven
```
one.jpro
JMemoryBuddy
0.5.6
test
```
#### Gradle
```
dependencies {
compile "one.jpro:JMemoryBuddy:0.5.6"
}
```
## How to use:
#### Write unit tests for memory leaks!
The method `JMemoryBuddy.memoryTest` is the usual way to test for leaks with JMemoryBuddy.
A typicial test might look like the following:
```
@Test
public void simpleTest() {
JMemoryBuddy.memoryTest(checker -> {
A referenced = new A();
checker.setAsReferenced(referenced);
A notReferenced = new A();
checker.assertCollectable(notReferenced); // notReferenced should be collectable
checker.assertNotCollectable(referenced); // referenced should not be collectable
});
}
```
The lambda provided to the memory test method is executed only once. The provided argument named "checker" provides an API to declare how the memory semantic should be.
| Method | |
| ------------- |:-------------:|
| assertCollectable(ref) | After executing the lambda, the provided ref must be collectable. Otherwise, an exception is thrown. |
| assertNotCollectable(ref) | After executing the lambda, the provided ref must be not collectable. Otherwise, an exception is thrown. |
| setAsReferenced(ref) | The provided reference won't be collected, until memoryTest finishes all it's tests.|
#### Other utility methods:
You can also use the method `assertCollectable` and `assertNotCollectable` to check whether a single WeakReference can be collected, but usually, the `memoryTest` method is prefered because it results in more elegant tests.
#### Analyzing the heap dump:
JMemoryBuddy makes it easy to analyze the heap dump because all problematic instances are wrapped inside a class with the name `AssertCollectable`. Just search your heap dump with your prefered tool for this class name:

## Configure JMemoryBuddy
You can configure VisualVM with SystemProperties:
| Tables | Effect | Default |
| ------------- |:-------------:| -----:|
| -Djmemorybuddy.createHeapDump | Should a heap dump created on failure? | true |
| -Djmemorybuddy.output | The folder where the heap dump gets saved. | if target exists, then "target" otherwise "build" |
The following values usually shouldn't be changed but might be useful to make tests more stable or reduce the time required.
| Tables | Effect | Default |
| ------------- |:-------------:| -----:|
| -Djmemorybuddy.steps | Maximum number of times we check whether something is collectable. You probably shouldn't change it. | 10 |
| -Djmemorybuddy.testDuration | Maximum time in ms used to check whether something is collectable. You probably shouldn't change it. | 1000 |
| -Djmemorybuddy.garbageAmount | How much garbage is created to stimulate the garbage collector | 999999 |
## Monitor running systems:
Mark references, where you know they can be collected:
```
JMemoryBuddyLive.markCollectable("description",reference);
```
Afterwards you can create a report during runtime with details about leaks.
```
System.gc();
JMemoryBuddyLive.getReport();
```
or search for AssertCollectableLive in a HeapDump.
If the referent of an AssertCollectableLive is reachable, then you have a memory leak.
It's especially interesting to see which leaks happen, if an application runs for severy hours, days, weeks or months.
## FAQ - Why is no one else writing unit-tests for memory leaks?
There are various reasons for this. By spec the command `System.gc()` doesn't have to do anything,
This makes it hard and undeterministic to test for collectability. Nevertheless, **JMemoryBuddy makes testing for memory leaks reliably!**. Currently, all known cases reliable and don't cause false-negative test results.
* What can i do about SoftReferences? It's hard to check whether they are strongly reachable.
You can use the following JVM arugment: `-XX:SoftRefLRUPolicyMSPerMB=0`. With this argument, SoftReferences behave like WeakReferences.
* I'm getting Leaking references during development, but not during production. What could be the reason?
A common reason might be various debuging features of you IDE. If you use the debugger, the garbage collector doesn't work reliably anymore.
## Real test samples:
* [controlsfx](https://github.com/controlsfx/controlsfx/blob/master/controlsfx/src/test/java/org/controlsfx/control/action/TestActionUtils.java) - A simple test for a isolated JavaFX Components.
* CSSFX ([1](https://github.com/McFoggy/cssfx/blob/master/src/test/java/fr/brouillard/oss/cssfx/test/TestMemoryLeaks.java), [2](https://github.com/McFoggy/cssfx/blob/master/src/test/java/fr/brouillard/oss/cssfx/test/TestURIRegistrar.java)) - Various tests to make sure that a listener based code base doesn't have unwanted changes to the memory semantics.
* [JavaFX](https://github.com/openjdk/jfx/pull/204) - PR for JavaFX itself to simplify some of the existing tests for memory leaks.
## Projects using JMemoryBuddy:
* [jpro.one](https://jpro.one/) - aka JavaFX for the web
* [controlsfx](https://github.com/controlsfx/controlsfx) - A very often used Library for JavaFX
* [CSSFX](https://github.com/McFoggy/cssfx) - Every JavaFX Developer should use this library
* [Your project?](https://github.com/Sandec/JMemoryBuddy/pulls)
##### internal developer
publish local:
```
./gradlew publishToMavenLocal
```
publish to sonatype:
```
./gradlew publishToSonatype closeAndReleaseStagingRepository
```