views:

226

answers:

6

Hi,

I'd like to measure memory allocation data from my java application, i.e. the sum of the size of all objects that were allocated. Since object allocation is done in young generation this seems to be the right place.

I know jconsole and I know the JMX beans but I just can't find the right variable... Right at the moment we are parsing the gc log output file but that's quite hard. Ideally we'd like to measure it via JMX...

How can I get this value?

Additional info after comment of Chadwick:

I want to know how much memory my application is using. It's quite a big software running in a JBoss Appserver. Every 4 weeks there is a new release of the software and we need to compare the memory consumption between old and new version. It's not enough to compare the current value of the old generation at a specific time. It's very useful to know how much more / or less memory gets allocated. Since many objects are getting collected in the young generation I need to measure it there.

In the meantime I have an estimate for this. I will post it as an answer.

Thanks, Marcel

+1  A: 

Yourkit profiler provides a good breakdown on memory usage. There's an evaluation version at http://www.yourkit.com/download/index.jsp

Ceilingfish
I know various profilers. None of them can be used in production environments. But I want to measure in production!
Marcel
Indeed, I suggested it because I use it in production on a high volume site with minimal impact
Ceilingfish
Ok, but it isn't usable because we then need > 30 licences. I'd like to go with a cheaper solution instead.
Marcel
+2  A: 

You can monitor the Young Generation using the MemoryPool MBeans, and more specifically

http://java.sun.com/j2se/1.5.0/docs/api/java/lang/management/MemoryPoolMXBean.html

See the code examples at http://www.javadocexamples.com/java_source/com/sun/enterprise/admin/mbeans/jvm/MemoryReporter.java.html and http://www.java2s.com/Code/Java/Development-Class/ThisVerboseGCclassdemonstratesthecapabilitytogetthegarbagecollectionstatisticsandmemoryusageremotely.htm

JoseK
I know JMX remoting. I know the Memory-MBeans. But where do I get the requested value: The total sum of the size of all allocated objects?
Marcel
+2  A: 

If you are using the Sun JDK, you can simply enable GC logging with -verbose:gc -Xloggc:gc.log and analyze the file. Or, if you need the total amount only occasionally, get the GCViewer by Tagtraum, which computes the number you are looking for.

Roland Illig
Yes, I know both tools. Doesn't solve it. I need this value at runtime in my application.
Marcel
+1  A: 

I havent used it personally, but have you tried jmap?

the -heap option prints generation wise heap usage.

its a tool bundled with jdk, so its free and probably does not have lot of overhead.

Mihir Mathuria
Yes, I know jmap. But I want to determine the values from my java application itself. So jstat is no option.
Marcel
+1  A: 

What about this code, it gives you sum of bytes used in all spaces (eden, survivor, old & perm) which is pretty much is all memory used by your instance of JVM.

public static void main(String[] args) {
    for (GarbageCollectorMXBean bean : ManagementFactory.getGarbageCollectorMXBeans()) {
        if (bean instanceof com.sun.management.GarbageCollectorMXBean) {
            com.sun.management.GarbageCollectorMXBean internal = (com.sun.management.GarbageCollectorMXBean) bean;
            Runtime.getRuntime().gc();
            GcInfo gcInfo = internal.getLastGcInfo();
            for (Map.Entry<java.lang.String,java.lang.management.MemoryUsage> e : gcInfo.getMemoryUsageBeforeGc().entrySet()) {
                System.out.println(e.getKey() + ": " + e.getValue());
            }
        }
    }
}
Victor Sorokin
Right, but so I have to poll the memory usage and when there are 2 or more gcs between my polls I will miss them. I thought of either a "event based" mechanism (get informed with every gc) or of an existing value that holds the total sum of allocated in young generation.
Marcel
A: 

That's my idea of an estimation. It basically returns the value of "number of young collections x size of young generation". It's not perfect but works quite well for my use case.

public long getYoungGenAllocatedMB() {
  long youngMaxMemory;
  long youngUsedMemory;
  long youngCollectionCount;

  List<MemoryPoolMXBean> beans = ManagementFactory.getMemoryPoolMXBeans();
  for (MemoryPoolMXBean bean : beans) {
    if ("Par Eden Space".equals(bean.getName())) {
      MemoryUsage usage = bean.getUsage();
      youngMaxMemory = usage.getMax();
      youngUsedMemory = usage.getUsed();
      break;
    }
  }

  List<GarbageCollectorMXBean> gBeans = ManagementFactory.getGarbageCollectorMXBeans();
  for (GarbageCollectorMXBean bean : gBeans) {
    if ("ParNew".equals(bean.getName())) {
      youngCollectionCount = bean.getCollectionCount();
      break;
    }
  }

  return (youngCollectionCount * youngMaxMemory + youngUsedMemory) / 1024 / 1024;
}

Thanks to all other posters!

Marcel

Marcel