1

Whenever a new object is created by my JVM I want to print something in the log. I was trying to detect that using Runtime.getRuntime().freeMemory() but unfortunately it does NOT take into account any short-lived object until it is promoted to the heap (check here for more details).

So does anyone know how to detect/track whenever an object is instantiated/created by my JVM? To make it easier, how do we complete the code below:

Feel free to use MemoryPoolMXBean and JMX:

public class MemoryUtils {

    private static Set<String> set = new HashSet<String>();

    public static void main(String[] args) {

        // START

        // now create a bunch of objects and save them in the set
        for (int i = 0; i < 100; i++) {
            set.add(new String("foo" + i));
        }

        // FINISH

        // FIXME: Do something here to detect that a bunch of objects were created!

    }
}

Edit: Trying solution proposed by Vladimir below:

It works, but with a weird side-effect:

long t = totalThreadMemoryAllocated();

// did nothing

t = totalThreadMemoryAllocated() - t;

System.out.println(t); // ==> 48 !!!???

public static long totalThreadMemoryAllocated() {
    com.sun.management.ThreadMXBean tBean = (com.sun.management.ThreadMXBean) ManagementFactory.getThreadMXBean();
    return tBean.getThreadAllocatedBytes(Thread.currentThread().getId());
}

But it DOES account for any object creation so I guess I could use this if I subtract the magic number 48 from it.

Community
  • 1
  • 1
chrisapotek
  • 6,007
  • 14
  • 51
  • 85
  • 2
    Is using AspectJ an option? If so, this question probably contains code that can be modified so that the aspect triggers on any invocation of a constructor: http://stackoverflow.com/questions/6402304/help-with-pointcut-aspectj – Joe23 Mar 21 '12 at 18:07
  • Thanks @Joe23, but I am looking for a more pure java solution. I think using JMX to access all the memory pools and adding the memory used might be the solution so when my total increases I can assume I had objects created somewhere (also assuming GC did not trigger) – chrisapotek Mar 21 '12 at 18:10
  • I think you have a poor understanding of how Java heap works. Outside of a (slow) debug environment there's no way to do what you want. – Hot Licks Mar 21 '12 at 18:20
  • @Hot Licks Nothing is impossible. Check Vladimir answer! – chrisapotek Mar 21 '12 at 18:34
  • Ah, but knowing how many bytes have been allocated is near to useless. – Hot Licks Mar 21 '12 at 20:56

3 Answers3

4

you can use a Java agent to do this, open source implementation can be found via the author's blog - http://jeremymanson.blogspot.co.uk/2012/02/update-to-allocation-instrumenter.html

Matt
  • 8,367
  • 4
  • 31
  • 61
3

Sun JVM (1.6.0u26 and higher) has ThreadMXBean#getThreadAllocatedBytes method that reports total number of bytes allocated by the thread. That will not distinguish between live/dead memory, however that would allow you to detect memory allocations and measure total amount of those allocations.

To use this approach you just lookup regular ThreadMXBean, and either cast it to com.sun.management.ThreadMXBean or use reflection to invoke the method.

Vladimir Sitnikov
  • 1,467
  • 12
  • 31
  • please see my edit above. Even if I don't do anything it reports 48. I tried anything and it is not Thread.currentThread that is allocating anything. I think the call itself to getThreadAllocatedBytes creates 48 bytes somehow. – chrisapotek Mar 21 '12 at 19:00
  • As far as I understand those 48 bytes come from two long[1] arrays: http://www.docjar.com/html/api/sun/management/ThreadImpl.java.html#321 – Vladimir Sitnikov Mar 21 '12 at 19:54
  • @chrisapotek: if I understnand it right, you run 32bit JVM, so each array consumes 8(header)+4(length)+8(1 item -- long)+4(padding for 8 byte alignment)=24 bytes. If you test getThreadAllocatedBytes in 64bit JVM, that magic 48 would change to something like 2 arrays*(16+4+8+4) = "magic 64" – Vladimir Sitnikov Mar 21 '12 at 20:03
  • I am trying to avoid creating memory and the method that will tell me that creates memory. :) And there is no escape because one of the long arrays are being created with native code. :( – chrisapotek Mar 28 '12 at 18:57
0

I wrote an open source tool to track object allocation and object lifetimes: http://mchr3k.github.com/org.inmemprofiler/

My tool won't let you log all object allocations to your own log but will perform its own analysis on the assumption that you want to actively track down things like object leaks or excessive object allocation.

mchr
  • 6,161
  • 6
  • 52
  • 74