2

I am wondering if there is any lightweight approach to (roughly) measure how much memory a given Java class is using. Let's consider the following interface:

interface MyAction <T, R> {
    R execute(T item);
}

I would like to know how much memory all the objects instantiated as fields or as variables in the overrided execute method are using. Of course, it should also take into account every object created when invoking other methods. As far as I could understand (reading this reply) the best option would be to:

  • Patch JVM bytecode through ASM framework and place hooks before any of the following instructions: new, newarray, anewarray, multianewarray.

  • Intercept all JNI calls (if any) by altering JNI function table.

  • Intercept all VMObjectAlloc events.

Those 3 steps would cover every possible allocation, however I could not figure out if there is any good method for tracking objects deallocation.

I would patch the finalize method bytecode in order to get notified about object gc deallocation and intercept all ObjectFree events (only for tagged objects). I am quite sure that this will not cover all the deallocation event, thus I wonder if there is some known technique (which I could not find out) that may help me in solving this problem.

Thank you in advance.

Community
  • 1
  • 1
  • 1
    Just wondering: why do you want to know all that? – GhostCat Nov 14 '16 at 13:58
  • If you want to do some manual analysis you could create a heapdump and analyze it with a tool like Eclipse MAT. Besides that deallocations should be trackable via `finalize()` but since the vm doesn't guarantee that objects which aren't needed are ever finalizes I'd not count on that. In fact you could any object that's not reachable from a live thread as being elligible for garbage collection/deallocation but analyzing that at runtime might cost quite a bit and existing heap dump analyzers will do exactly that for you already. – Thomas Nov 14 '16 at 14:05
  • To be honest, I would like to know such info at runtime because I am trying to optimize a system that has already its own memory management for its internal processing. As there is no control for the code overriding MyAction, an on-the-fly tuning according to real-time statistics would hopefully lead to a better memory manager. Of course, I am still evaluating if the game is worth the candle. @Thomas yes, definitely finalize() is untrustworthy. – Ventura Del Monte Nov 14 '16 at 14:30
  • The system has an internal memory manager for Java? Sounds strange since you'd normally not want to "manually" mess with a managed environment. – Thomas Nov 14 '16 at 15:06
  • Sorry, my previous answer may sound misleading. Being a distributed system, its core developers found wiser (and faster) to work with java.nio.ByteBuffer for internal processing, rather than plain java objects. I meant the system has an internal memory manager, not that it introduces a Java memory manager. Sorry for the misunderstanding. – Ventura Del Monte Nov 14 '16 at 15:27

1 Answers1

0

Since you are interested in the amount of allocated memory, not the every single allocated object, you may use a simpler approach.

There is a method ThreadMXBean.getThreadAllocatedBytes that returns the cumulative amount of memory allocated by the given thread. You just need to record the counter before calling execute and after. The difference will be the estimated total memory allocated by the method (considering that it does not span several threads).

Here is how to get the instance of com.sun.management.ThreadMXBean:

    com.sun.management.ThreadMXBean mxBean =
            (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();

There is no such event as object deallocation in Java. You cannot find whether an object is reachable or not until full GC. Even GC does not "deallocate" objects - it usually just walks through live objects, and treats everything else as free space.

If you need to find how Java heap changes after calling a method, you may create a heap snapshot before and after the call.

apangin
  • 92,924
  • 10
  • 193
  • 247
  • Thank you for your reply. Unfortunately, this is not my case because I need to monitor the allocation during the execution of my method. Moreover, I cannot have a dedicated thread only for that method invocation. The idea is to adjust the number of java.nio.ByteBuffer used in the system according to the memory consumption in the execute() method. However, your idea regarding heap snapshots could be interesting as long as it would be possible to take per thread heap dumps, which I believe it's not feasible. – Ventura Del Monte Nov 14 '16 at 22:46