On Fri, Nov 4, 2022 at 10:05 PM Clebert Suconic <clebert.suco...@gmail.com>
wrote:

> More importantly.. that goes without saying... If we make this happen,
> I am looking for contributors to share the project with me :)
>
> On Fri, Nov 4, 2022 at 4:51 PM Clebert Suconic
> <clebert.suco...@gmail.com> wrote:
> >
> > I have a pet project that I have kept on hold for many years... but I
> > see a need in Artemis... and perhaps I could use this as a push to
> > make it happen..
> >
> > https://github.com/clebertsuconic/d-sect
> >
> >
> > The project is a JVMTI C Agent, that I can use to fetch objects,
> > references and do some reports. It's a lot simpler to write tests to
> > avoid memory leaks with this.. and you can do things like this:
> >
> > @Test
> > void test() {
> >
> >
> > ... do your test thing.. and then.
> >
> >
> > JVMTIInterface jvmti = new JVMTIInterface();
> > Object[] objects = jvmti.getAllObjects("mypackage.MyClass");
> >
> > Assert.assertEquals("My class is leaking", objects.length);
> >
> > }
> >
> > There are reporting methods that will show what would eventually be
> > holding the references.
> >
> >
> > What would be a good way to consume this in ActiveMQ Artemis? We
> > should add a few tests like this but I'm not sure how we would consume
> > the library in there?
>

Isn't there any such library already? Looking for it, I indeed had trouble
finding anything for Java.

In .NET/C# world, there is dotMemory Unit,
https://www.nuget.org/packages/JetBrains.DotMemoryUnit/, (some custom EULA,
not opensource). There are some usage examples in an announcement blog,
https://blog.jetbrains.com/dotnet/2015/03/04/unit-testing-and-memory-profiling-can-they-be-combined/,
and in the docs
https://www.jetbrains.com/help/dotmemory-unit/Introduction.html.

dotMemory.Check(memory =>
        Assert.That(memory.GetObjects(where =>
where.Type.Is<Goo>()).ObjectsCount,
Is.EqualTo(0)));

In JavaScript world, there seem to be some research efforts such as
http://plasma-umass.org/BLeak/,
https://cacm.acm.org/magazines/2020/11/248223-bleak/abstract, which
requires writing UI tests that navigate in a webapp in a loop, and compare
objects in heap snapshots after going through the loop several times. There
is also https://www.npmjs.com/package/memlab from Facebook, and looks like
many more.

For Android Java/Kotlin, there is https://square.github.io/leakcanary/,
(ASL-2.0). Written in Kotlin, not sure if it has a reasonable Java API.
They focus on Android, and the main mode of operation is to instrument the
application during e2e testing (and possibly also in production
deployment). It has knowledge of Android application structure to detect
disposed-off application screens that are stuck in memory for some reason.
https://square.github.io/leakcanary/fundamentals-how-leakcanary-works/.
There is some support for usage on the JVM (not Android)
https://square.github.io/leakcanary/recipes/#detecting-leaks-in-jvm-applications.
They have assertNoLeaks() test rule which apparently works only on android,
and they have a ticket wanting to port over this JVM implementation
https://github.com/cashapp/paparazzi/pull/431/files#diff-7ea5ca018df762ee2392a3ca3afe479a5e9212ab7c7bb36c582331deef6448edR20.
This seems to trigger heap dumps into a file on disk and then uses the
Shark library to analyze the dump and do assertions on object counts:

    Class.forName("com.sun.management.HotSpotDiagnosticMXBean")
      .getMethod("dumpHeap", String::class.java,
Boolean::class.javaPrimitiveType)
      .invoke(mBean, fileName, LIVE)
  }

And I also found
https://github.com/centic9/commons-test/blob/master/src/main/java/org/dstadler/commons/testing/MemoryLeakVerifier.java,
which works by keeping a list of weak references to the objects that are
supposed to be gc'd at the end of the test, and the final check consists of
verifying that all the weak references have been nulled. (This does not
look practical in case the objects are some internal objects not visible to
the test, of course.)

Some people on StackOverflow dislike the JVM Tool Interface API approach,
claiming it is slow, and of course it requires writing in C/C++,
https://stackoverflow.com/questions/67148994/jvm-getting-the-largest-objects-in-the-heap-programmatically.
There they suggest using OpenJDK-specific api in JMX to get object counts.

Looking for existing JVMTI agents, I found
https://github.com/JetBrains/debugger-memory-agent (ASL-2.0), which is
supposed to provide the Memory view feature in IntelliJ,
https://www.jetbrains.com/help/idea/analyze-objects-in-the-jvm-heap.html,
Looks like IntelliJ and Eclipse need this functionality for their debugger,
so there can hopefully be an opportunity to reuse a maintained
implementation. I was hopeful about
https://github.com/GoogleCloudPlatform/cloud-debug-java/tree/main/src/agent
but they don't appear to focus on inspecting the heap, strangely. There was
something called JBoss Profiler JVMTI 2,
https://anonsvn.jboss.org/repos/jbossprofiler/branches/JBossProfiler2/native/src/main/native/agent.cpp,
but it looks dead.

Exposed API for the debugger-memory-agent in previous paragraph is
https://github.com/JetBrains/debugger-memory-agent/blob/b36a6d807da89d330206067ccc772f1487ca8312/test_data/proxy/src/com/intellij/memory/agent/MemoryAgent.java#L65-L98

Btw, while searching for all the above, I found something they call
Lincheck, https://github.com/Kotlin/kotlinx-lincheck, and
https://blog.jetbrains.com/kotlin/2021/02/how-we-test-concurrent-primitives-in-kotlin-coroutines/.
It is able to run a test multiple times, changing thread interleaving, and
assert that the result is the same every time. It seems to be useful for
small tests only (individual classes, not entire programs). The blogs show
Kotlin, but the library should be just fine testing Java classes.
-- 
Mit freundlichen Grüßen / Kind regards
Jiri Daněk

Reply via email to