jvm internals & runtime data areas

Upload: kannangce

Post on 04-Apr-2018

226 views

Category:

Documents


0 download

TRANSCRIPT

  • 7/31/2019 JVM Internals & Runtime Data Areas

    1/13

    JVM Runtime Data Areas

    The Java virtual machine defines various runtime data areas that are used during executionof a program. Some of these data areas are created on Java virtual machine start-up and

    are destroyed only when the Java virtual machine exits. Other data areas are per thread.Per-thread data areas are created when a thread is created and destroyed when the thread

    exits

    StackStack is a memory place where the methods and the local variables are stored. Variable

    references (either primitive or object references) are stored in the Stack. Each thread has aprivate stack, which stores frames.

    The following exceptional conditions are associated with Java virtual machine stacks

    If the computation in a thread requires a larger Java virtual machine stack than is

    permitted, the Java virtual machine throws a StackOverflowError.

    If Java virtual machine stacks can be dynamically expanded, and expansion is

    attempted but insufficient memory can be made available to effect the expansion, or

    if insufficient memory can be made available to create the initial Java virtual machine

    stack for a new thread, the Java virtual machine throws an OutOfMemoryError

    Heap

    Heap is a memory place where the objects and its instance variable are stored. Each timean object is created in Java it goes into the area of memory known as heap.

    Information about HEAP

    The heap is created on virtual machine start-up. Heap storage for objects is reclaimed by an automatic storage management system

    (known as a garbage collector); objects are never explicitly deallocated.

    The heap may be of a fixed size or may be expanded as required by the computationand may be contracted if a larger heap becomes unnecessary.

    The memory for the heap does not need to be contiguous.

    A Java virtual machine implementation may provide the programmer or the user control

    over the initial size of the heap, as well as, if the heap can be dynamically expanded orcontracted, control over the maximum and minimum heap size.

    The following exceptional condition is associated with the heap:

    If a computation requires more heap than can be made available by the automaticstorage management system, the Java virtual machine throws an OutOfMemoryError

    Heap and stack are the two main memories that JVM is concerned as far as memory

    allocation by the OS (operating system) is concerned. Stack and heap are the memoriesallocated by the OS to the JVM that runs in the system.

    JVM Internals & Runtime Data Areas.doc Page 1

  • 7/31/2019 JVM Internals & Runtime Data Areas

    2/13

    The primitive variables like int and double are allocated in the stack, if they are localmethod variables and in the heap if they are member variables (i.e. fields of a class). In

    Java methods local variables are pushed into stack when a method is invoked and stackpointer is decremented when a method call is completed. In a multi-threaded application

    each thread will have its own stack but will share the same heap. This is why care should betaken in your code to avoid any concurrent access issues in the heap space. The stack is

    threadsafe (each thread will have its own stack) but the heap is not threadsafe unlessguarded with synchronization through your code.

    Method Area

    It is shared among all threads. It stores per-class structures such as the runtime constantpool, field and method code. It is logically part of the heap. Memory for class (static)

    variables and methods declared in the class is also taken from it.

    Runtime Constant Pool Or Constant PoolIt is a per-class or per-interface runtime representation of the constant_pool table. The JVM

    maintains a per-type constant pool, including literals (string, integer, and floating pointconstants). Each runtime constant pool is allocated from the JVM method area.

    Frame or Stack FrameFrame holds local variables (including parameters), operand stack and partial results, andplays a part in method invocation and return. A new frame is created each time a method is

    invoked and is destroyed on method completion. Each frame has a reference to the runtimeconstant pool of the class of the current method.

    PC Register

    The Java virtual machine can support many threads of execution at once. Each Java virtualmachine thread has its own pc (program counter) register. At any point, each Java virtual

    machine thread is executing the code of a single method, the current method for thatthread. If that method is not native, the pc register contains the address of the Java virtual

    machine instruction currently being executed. If the method currently being executed by the

    thread is native, the value of the Java virtual machine's pc register is undefined. The Javavirtual machine's pc register is wide enough to hold a returnAddress or a native pointer on

    the specific platform.

    An Example class Memory {

    static int x; /* static stack storage*/public static void main(String[] args){

    Memory memory = new Memory(); /* dynamic heap storage*/int y =0; /* dynamic stack storage */String myString = new String(Memory); /* dynamic heap storage

    */}

    }

    When you create an object using the new operator, for example memory = new Memory();, it

    allocates memory for the memory object on the heap. The stack memory space is used when youdeclare automatic variables.

    Note, when you do a string initialization, for example String myString;, it is a reference to an object

    so it will be created using new and hence it will be placed on the heap.

    JVM Internals & Runtime Data Areas.doc Page 2

  • 7/31/2019 JVM Internals & Runtime Data Areas

    3/13

    Memory space for objects is always allocated in heap. Objects are placed on the heap. Built-in

    datatypes like int, double, float and parameters to methods are allocated on the stack.

    JVM Performance Tuning

    The application server, being a Java process, requires a Java virtual machine (JVM) to run,and to support the Java applications running on it. As part of configuring an application

    server, you can fine-tune settings that enhance system use of the JVM

    Heap Size

    The allocation of memory for the JVM is specified using -X options

    Options Meaning

    -Xms initial java heap size

    -Xmx maximum java heap size

    -Xmn the size of the heap for the young

    generation

    It is good practice with server-side Java applications like Resin to set the minimum -Xms

    and maximum -Xmx heap sizes to the same value.

    For efficient garbage collection, the -Xmn value should be lower than the -Xmx value.

    Heap size does not determine the amount of memory your process uses. If you monitoryour java process with an OS tool like top or taskmanager, you may see the amount of

    memory you use exceed the amount you have specified for -Xmx. -Xmx limits the java heapsize, java will allocate memory for other things, including a stack for each thread. It is not

    unusual for the total memory consumption of the VM to exceed the value of -Xmx.

    Stack Size

    Each thread in the VM get's a stack. The stack size will limit the number of threads that youcan have, too big of a stack size and you will run out of memory as each thread is allocated

    more memory than it needs.

    Options Meaning

    -Xss the stack size for each thread

    -Xss determines the size of the stack: -Xss1024k. If the stack space is too small, eventually

    you will see an exceptionjava.lang.StackOverflowError.

    JVM Internals & Runtime Data Areas.doc Page 3

    http://www.caucho.com/resin-javadoc/java/lang/StackOverflowError.htmlhttp://www.caucho.com/resin-javadoc/java/lang/StackOverflowError.html
  • 7/31/2019 JVM Internals & Runtime Data Areas

    4/13

    Internal architecture of the Java virtual machine

    JVM Internals & Runtime Data Areas.doc Page 4

  • 7/31/2019 JVM Internals & Runtime Data Areas

    5/13

    Runtime Data Areas

    JVM

    Dealing with Memory Leaks

    What is it?

    Memory leaks occur when a program never stops using an object, thus keeping a permanent referenceto it. For Example

    class MemoryLeak {private static List memoryLeakList = new ArrayList();public static void main(String[] args){

    double d = 0.0;// infinite loop would eventually run out of memorywhile(true){

    Double dbl = new Double(d);memoryLeakList.add(dbl);d++;

    }}

    }

    If you run this program, When no more memory is remaining, an OutOfMemoryError alert will be thrownand generate an exception like this -

    JVM Internals & Runtime Data Areas.doc Page 5

    THREAD 1

    PC STACK

    OperandStack

    Local Variables

    Partial Results

    HEAP

    Class instances and

    Arrays

    Instance Variable

    Frame Frame

    Referenc

    es

    Per method

    Area

    Per class

    basis

    Method Area

    Runtime Constant

    Pool

    Method Code

    Static Variables

    THREAD 2

    PC STACK

    Local Variables

    Operand

    Stack

    Partial Results

    Frame Frame

    Per method

    Area

    Native Method

    Stack

    Shared among all

    threads

  • 7/31/2019 JVM Internals & Runtime Data Areas

    6/13

    Exception in thread main java.lang.OutOfMemoryError: Java heap space atMemoryLeak.main(MemoryLeak.java:7)

    In the example above, we continue adding new elements to the list memoryLeakArea

    without ever removing them. In addition, we keep references to the memoryLeakArea,thereby preventing GC from collecting the list itself. So although there is GC available, it

    cannot help because we are still using memory. The more time passes the more memory weuse, which in effect requires an infinite amount memory for this program to continuerunning.

    This is an example of unbounded memory leakthe longer the program runs, the morememory it takes. So even if the memory size is increased, the application will still run out of

    memory at a later date.

    Determining if an application has a memory leak

    To understand what is going on, we need to familiarize ourselves with how the JVM uses

    system memory for its heap. When running java.exe, you can use certain options to control

    the startup and maximum size of the garbage-collected heap (-ms and -mx, respectively).The Sun JDK 1.1.8 uses a default 1 MB startup setting and a 16 MB maximum setting. The

    IBM JDK 1.1.8 uses a default maximum setting of one-half the total physical memory size ofthe machine. These memory settings have a direct impact on what the JVM does when it

    runs out of memory. The JVM may continue growing the heap rather than wait for agarbage collection cycle to complete.

    So for the purposes of finding and eventually eliminating a memory leak, we are going toneed better tools than task monitoring utility programs. Memory debugging programs can

    come in handy when you're trying to detect memory leaks. These programs typically giveyou information about the number of objects in the heap, the number of instances of each

    object, and the memory being using by the objects. In addition, they may also provideuseful views showing each object's references and referrers so that you can track down the

    source of a memory leak.

    This example I have taken fromhttp://java.dzone.com

    Not every OutOfMemoryError alert indicates that a program is suffering from a memory

    leak. Some programs simply need more memory to run. In other words, some

    OutOfMemoryError alerts are caused by the load, not by the passage of time, and as a

    result they indicate the need for more memory in a program rather than a memory leak.

    To distinguish between a memory leak and an application that simply needs more memory,

    we need to look at the peak load concept. When program has just started no users have

    yet used it, and as a result it typically needs much less memory then when thousands ofusers are interacting with it. Thus, measuring memory usage immediately after a program

    starts is not the best way to gauge how much memory it needs! To measure how much

    memory an application needs, memory size measurements should be taken at the time of

    peak loadwhen it is most heavily used.

    JVM Internals & Runtime Data Areas.doc Page 6

    http://java.dzone.com/http://java.dzone.com/http://java.dzone.com/
  • 7/31/2019 JVM Internals & Runtime Data Areas

    7/13

    The graph below shows the memory usage in a healthy Java application that does not suffer

    from memory leaks, with the peak load occurring around 10 AM and application usage

    drastically decreasing at 5 PM. Naturally, the peak load on business applications often

    correlates with normal business hours.

    The application illustrated by the chart above reaches its peak load around 10 AM and needsaround 900MB of memory to run. This is normal behavior for an application suffering from

    no memory leaks; the difference in memory requirements throughout the day is caused

    solely by the user load.

    Now, lets suppose that we have a memory leak in the application. The primary

    characteristic of memory leaks is that memory requirements increase as a function of time,

    not as a function of the load. Lets see how the application would look after running for a

    few days with a memory leak and the same peak user loads reached around 10 AM every

    day:

    JVM Internals & Runtime Data Areas.doc Page 7

  • 7/31/2019 JVM Internals & Runtime Data Areas

    8/13

    Because peak loads on the system are similar every morning but memory usage is growing

    over a period of a few days, this picture indicates a strong possibility of memory leaks. If

    the program eventually started suffering from OutOfMemory exceptions, it would be a very

    strong indication that theres a problem with memory leaks. The picture above shows a

    memory leak of about 100MB per day.

    Note that the key to this example is that the only thing changing is the amount of time the

    system is upthe system peak load doesnt change over time. This is not the case for all

    businesses. For example, the peak load for a tax preparation service is seasonal, as there

    are likely more users on the system in April than July.

    There is one special case that should be noted here: a program that needs to be restarted

    periodically in order to prevent it from crashing with an OutOfMemoryError alert. Imagine

    that on the previous graph the max memory size was 1100MB. If the program started with

    about 900MB of memory used, it would take about 48 hours to crash because it leaks about

    100MB of memory per day. Similarly, if the max memory size was set to 1000MB, the

    program would crash every 24 hours. However, if the program was regularly restarted moreoften than this interval, it would appear that all is fine.

    Regularly scheduled restarts may appear to help, but also might make upward sloping

    memory use (as shown in the previous graph) more difficult to notice because the graph is

    cut short before the pattern emerges. In a case like this, youll need to look more carefully

    at the memory usage, or try to increase the available memory so that its easier to see the

    pattern.

    JVM Internals & Runtime Data Areas.doc Page 8

  • 7/31/2019 JVM Internals & Runtime Data Areas

    9/13

    Monitoring Memory in Java

    There are a couple of options for measuring the amount of memory a program uses. The

    simplest one, which does not require any tools and works even with production systems, is

    the Verbose GC log.

    Verbose GC Log

    The Verbose GC log is defined when the JVM process is started. There are a couple of

    switches that can be used:

    1. -verbose:gc prints basic information about GC to the standard output

    2. -XX:+PrintGCTimeStamps prints the times that GC executes

    3. -XX:+PrintGCDetails prints statistics about different regions of memory in the JVM

    4. -Xloggc: logs the results of GC in the given file

    The following is an example of the output generated for Tomcat running in the default

    configuration with all of the previous switches enabled:

    1.854: [GC 1.854: [DefNew: 570K->62K(576K), 0.0012355 secs] 2623K->2175K(3980K), 0.0012922 secs]

    1.871: [GC 1.871: [DefNew: 574K->55K(576K), 0.0009810 secs] 2687K->2229K(3980K), 0.0010752 secs]

    1.881: [GC 1.881: [DefNew: 567K->30K(576K), 0.0007417 secs] 2741K->2257K(3980K), 0.0007947 secs]

    1.890: [GC 1.890: [DefNew: 542K->64K(576K), 0.0012155 secs] 2769K->2295K(3980K), 0.0012808 secs]

    The most important set of numbers is located in the second column after the second ->

    (e.g., in the top line shown it is 2623K->2175K(3980K). These numbers indicate that as a

    result of GC, we are using around 2200K of memory at the end of each GC cycle.

    This trace is not an indication of a memory leakit shows a short-term trend with less then

    a second between samples, and thats why we must observe long-term trends. However, ifthe Verbose GC log showed that the program was using around 2200K of memory after

    running for two days, and after running for 10 days it was using 2GB of memory (even after

    GC had just run), we could then conclude that theres a memory leak.

    All the information that needs to be collected in order to determine if a memory leak exists

    can be found in the results of the Verbose GC logs.

    Monitoring the Java Process

    The following approach works for any Java process, including standalone clients as well as

    application servers like JBoss and servlet containers like Tomcat. It is based on starting theJava process with JMX monitoring enabled and attaching with the JMX monitoring tools.

    Well use Tomcat in the following example.

    To start Tomcat or the Java process with JMX monitoring enabled, use the following options

    when starting JVM:

    -Dcom.sun.management.jmxremote enables JMX monitoring

    JVM Internals & Runtime Data Areas.doc Page 9

    https://olex.openlogic.com/packages/jbosshttps://olex.openlogic.com/packages/jboss
  • 7/31/2019 JVM Internals & Runtime Data Areas

    10/13

    -Dcom.sun.management.jmxremote.port= controls the port for JMX

    monitoring

    Note that if youre on a production system, youll most likely want to secure your JVM

    before running it with these parameters. For that, you can specify these additional options:

    com.sun.management.jmxremote.ssl

    com.sun.management.jmxremote.authenticate

    Once started, you can use JConsole or VisualVM to attach to the process. Note that later

    JDK 6 versions include VisualVM.

    Heap Dump

    A heap dump is a list of objects in the memory of JVM as well as the content of the memory

    occupied by those objects. It preserves the value of any attributes of the objects, including

    references to other objects. In other words, a heap dump gives you a complete picture of

    the memory.

    There are multiple tools that allow you to dump heap in a Java process:

    If youre using JDK 6, you can use tool calledjmap on any platform.

    If youre using JDK 5, the situation is slightly more complex:

    If youre running UNIX (Linux, Solaris, OS X) with JDK 5 you can use jmap.

    If youre using JDK 5 update 14 or later, you can use the -XX:

    +HeapDumpOnCtrlBreak option when starting JVM, then use the CTRL+BREAK key

    combination on Windows (or CTRL + \ on UNIX) to dump the heap.

    If youre running Windows and using JDK 5 pre-update 14, youll soon wish you

    werent. Trying to reproduce the problem with a more recent JDK is probably the

    best bet here.

    Some tools like VisualVM and memory profilers allow you to initiate a heap dump from the

    GUI, but you dont need any fancy tools herejmap will do just fine. As it provides the most

    general case, well use jmap in the next example.

    Before you dump heap, be sure to keep the following issues in mind:

    Programs in the JVM should be paused for the duration of the heap dump, which

    might take anywhere from ten seconds to several minutes. Many enterprise

    applicationsand users of those applicationsdont take kindly to pauses that long,which may cause various timeouts to expire. So dont try this at home or in

    production (unless the application is already a goner)!

    Heap dumps are saved on disk, and the files might be fairly large. A good rule is to

    make sure that you have at least twice the size of the physical memory free on the

    disk before you initiate a memory dump.

    JVM Internals & Runtime Data Areas.doc Page 10

    https://visualvm.dev.java.net/https://olex.openlogic.com/packages/jmaphttps://visualvm.dev.java.net/https://olex.openlogic.com/packages/jmap
  • 7/31/2019 JVM Internals & Runtime Data Areas

    11/13

    With those final words of caution out of the way, you should now be ready to run the

    following command:

    jmap -heap:live,format=b,file=FILENAME PID

    Note that the -F option, which will dump non-responsive programs, might be useful on UNIX

    systems, but is not available on Windows. Note also that JDK 6 includes the option +XX:+HeapDumpOnOutOfMemoryError that will dump heap whenever the OutOfMemoryError

    alert is encountered. This can be a useful option, but keep in mind that it has the potential

    to consume significant amounts of disk space.

    You now have a heap dump in the file FILENAME and are ready to analyze it.

    Whats In Leaked Memory?

    With the heap dump complete, we can now take a look at the memory and find out whats

    really causing the memory leak.

    Suppose that objects are holding references to each other as illustrated by the picture

    below. For the sake of easy calculation, lets assume that each object is 100 bytes, so that

    all of them together occupy 600 bytes of memory.

    Now, suppose that the program holds reference to object A for a prolonged period of time.

    As a result, objects B, C, D, E, and F are all ineligible for garbage collection, and we have

    the following amount of memory leaking:

    100 bytes for object A 500 bytes for objects B, C, D, E and F that are retained due to the retention of object

    A

    So, holding reference to object A causes a memory leak of 600 bytes. The shallow heap of

    object A is 100 bytes (object A itself), and the retained heap of object A is 600 bytes.

    JVM Internals & Runtime Data Areas.doc Page 11

  • 7/31/2019 JVM Internals & Runtime Data Areas

    12/13

    Although objects A through F are all leaked, the real cause of the memory leak is the

    program holding reference to object A. So how can we fix the root cause of this leak? If we

    first identify that object F is leaked, we can follow the reference chain back through objects

    D, C and A to find the cause of the memory leak. However, there are some complications to

    this follow the reference chain process:

    Reference chains can be really long, so manually following them can be time

    consuming

    An object is sometimes retained by more than one object, and there can even be

    circles involved as shown in the picture below:

    If we start following inbound references from object F in this example, we have to choose

    between following object C or object D. In addition, theres the possibility of getting caught

    in a circle by repeatedly following the path between objects D, E and B. On this small

    diagram its easy to see that the root cause is holding object A, but when youre dealing

    with a situation that involves hundreds of thousands of objects (as any self-respectingmemory leak does) you quickly realize that manually following the reference chain be very

    complex and time consuming.

    This is where some shortcuts can come in handy:

    If we had a tool that allowed us to play a what would happen if I remove this

    reference type of guessing game, we could run experiments that help locate the

    cause. For example, we could see that if we removed reference from Cause of Leak

    to A in the diagram above, objects A through F would all be freed. Some tools (like

    Quests JProbe) have this capability.

    If the memory leak is large and we have a tool that allows us to sort objects byretained heap, well get an even greater head start because the objects with the

    largest retained heap are usually the cause of large memory leaks.

    Now that we understand what memory leaks are and how they can be corrected, lets find

    out how to fix them by analyzing heap dumps.

    JVM Internals & Runtime Data Areas.doc Page 12

    https://olex.openlogic.com/packages/jprobehttps://olex.openlogic.com/packages/jprobe
  • 7/31/2019 JVM Internals & Runtime Data Areas

    13/13

    Tools for Dealing with Heap Dumps

    Tools often provide a few extra helpful features

    Present a better summary of heap statistics.

    Sort objects by retained heap. In other words, some tools can tell you the memoryusage of an object and all other objects that are referenced by it, as well as list the

    objects referenced by other objects. This makes it much faster to diagnose the cause of

    a memory leak.

    Function on machines that have less memory then the size of the heap dump. For

    example, theyll allow you to analyze a 16GB heap dump from your server on a machine

    with only 1GB of physical memory.

    VisualVM is nice tool that gives you just enough to resolve memory leaks, and it shows

    heap dumps and relations between objects in graphical form.

    Feature-wise, one step above VisualVM is the Eclipse Memory Analyzer Tool (MAT), a free

    tool that includes a lot of additional options. Although its still in incubation phase as of

    publication of this article, MAT is free and weve found it to be extremely useful.

    Commercial products like JProfiler, YourKit, and JProbe are also excellent tools for

    debugging memory leaks. These applications include a few options that go above andbeyond VisualVM and MAT, but theyre certainly not necessary to successfully debug

    memory leaks.

    JVM Internals & Runtime Data Areas.doc Page 13

    http://www.eclipse.org/mat/http://wiki.eclipse.org/Development_Resources/HOWTO/Incubation_Phasehttp://www.eclipse.org/mat/http://wiki.eclipse.org/Development_Resources/HOWTO/Incubation_Phase