15

I want to run several REST web applications inside one Java process to save memory and scale easily with help of Akka. I would like to estimate how much memory each request handler consume and detect these dangerous for the entire system.

  1. Is it possible to monitor memory usage in almost real time inside that process and find out how much memory is used be each request handler? What I need to achieve that? Are there any tools?

  2. Is it possible to catch out of memory exception and based on memory usage do something, for example crash only request handlers exceeding assumed memory limit? If so, what could be bad with that?

Rafał Sobota
  • 1,468
  • 1
  • 17
  • 32
  • 1
    It's a tough question. See more here: http://stackoverflow.com/questions/52353/in-java-what-is-the-best-way-to-determine-the-size-of-an-object – biziclop May 25 '12 at 12:55

4 Answers4

16

The total used / free memory of an program can be obtained in the program via java.lang.Runtime.getRuntime();

The runtime has several method which relates to the memory. The following coding example demonstrate its usage.

package test;

import java.util.ArrayList;
import java.util.List;

public class PerformanceTest {
  private static final long MEGABYTE = 1024L * 1024L;

  public static long bytesToMegabytes(long bytes) {
    return bytes / MEGABYTE;
  }

  public static void main(String[] args) {
    // I assume you will know how to create a object Person yourself...
    List<Person> list = new ArrayList<Person>();
    for (int i = 0; i <= 100000; i++) {
      list.add(new Person("Jim", "Knopf"));
    }
    // Get the Java runtime
    Runtime runtime = Runtime.getRuntime();
    // Run the garbage collector
    runtime.gc();
    // Calculate the used memory
    long memory = runtime.totalMemory() - runtime.freeMemory();
    System.out.println("Used memory is bytes: " + memory);
    System.out.println("Used memory is megabytes: "
        + bytesToMegabytes(memory));
  }
} 
5

To answer your first question, there are many tools which you can use to monitor memory usage, however i don't know of any application which maps memory usage to threads in "real" time. Within the application you can use the MemoryMXBean and MemoryPoolMXBeans to monitor memory usage,

To answer your second question: no, not really. Besides the fact that it is generally a bad idea to catch OOME, the primary problem is that the thread which receives the exception may not be the actual culprit. the OOME is thrown on the thread which makes the final allocation request. however, some other thread could be the one which filled up most of memory. The other problem is that since OOME can be thrown at any time, it could be thrown inside some critical code within your application, leaving it in a crippled state. long story short, you pretty much always want to restart your application when you receive an OOME.

jtahlborn
  • 52,909
  • 5
  • 76
  • 118
  • Thanks for your answer. 1. So I can only map memory to thread? Can't do something more sophisticated? 2. The problem of OOME source I wanted to handle based on informations about memory usage, so I could know if problem is inside one of my request handlers. If no, I could escalate exception and restart whole JVM. Is it still a bad idea? – Rafał Sobota May 25 '12 at 14:10
  • i'm not sure i understood anything in your comment. 1. as i said, i don't know of any solution to map memory usage to thread programmatically or in "real" time. 2. i don't understand what you mean. – jtahlborn May 25 '12 at 14:19
  • Ach, I misunderstood you. I assumed that it is possible to track memory usage by individual component and use this information while catching OOME (who thrown and how much memory each component is using) to determine if one component can be killed safely for the rest of them. – Rafał Sobota May 25 '12 at 14:37
  • So in java.lang.management is all I can get. These informations are shared via JMX with all tools for monitoring? There is nothing more? Am I right? http://docs.oracle.com/javase/6/docs/api/java/lang/management/package-summary.html – Rafał Sobota May 25 '12 at 16:54
  • @RafałSobota - the information you can get from java.lang.management is all you can get _from the standard jdk_ (these values are available from within the jvm and to any external jmx tools). a specific jvm implementation may have other _proprietary_ monitoring abilities, but i don't know of any specifically. – jtahlborn May 25 '12 at 17:00
3

A good and easy tool to monitor your application is VisualVM. You may try it: http://visualvm.java.net/

stzoannos
  • 938
  • 4
  • 10
2

You may also add in your code statements to monitor free memory like:

Runtime runtime = Runtime.getRuntime();
System.out.println("Free memory: " + runtime.freeMemory() + " bytes.");

It's not possible to handle this exception. The problem is that if you are running all your web services in a common app server (e.g. tomcat), then if there is an "out-of-memory" exception, JVM will go down. Try to see if there is any memory leak or bad memory handling in your program. You might use profiling inside Netbeans or Eclipse. Also, code analysis with a tool like "findbugs" or "sonar" might show you possible bad practices inside your code.

In any case, using java options regarding Garbage Collection or JVM Memory (like -Xmx) can reduce such exceptions and improve performance.

Freek de Bruijn
  • 3,552
  • 2
  • 22
  • 28
stzoannos
  • 938
  • 4
  • 10
  • An important thing to be aware of when using Runtime.freeMemory() is that it includes garbage currently on the heap and hence might not give you exactly what you want. – K Erlandsson May 25 '12 at 13:08
  • Precisely, you are right. Thanks for the remark. However, it might be indicative in many cases of bad memory handling. – stzoannos May 25 '12 at 13:09