Learn the Java memory area and exception _java of the JVM

Source: Internet
Author: User
Tags exception handling garbage collection static class throwable

First, the preface

Java is an object-oriented high-level programming language that spans the hardware platform, Java programs run on a Java Virtual machine (JVM), which manages memory by the JVM, which is the biggest difference from C + +; Although memory has JVM management, we must understand how the JVM manages memory; the JVM is not just a , the current virtual machine may be up to dozens of, but a compliant virtual machine design must follow the Java Virtual Machine specification, this article is based on the hotspot virtual machine description, for and other virtual machines have a difference will be mentioned; This article mainly describes how memory is distributed in the JVM, The object of the Java program is how to store access, exceptions that may occur in each memory region.

Ii. memory distribution in the JVM (region)

When the JVM executes the Java program, it divides the memory into different data regions for management. These areas have different roles, creation, and destruction times, some of which are allocated when the JVM process is started, and some are related to the lifecycle of the user's thread (the program itself), and, according to the JVM specification, The memory area managed by the JVM is divided into the following runtime data regions:


1. Virtual Machine stack

This area of memory is thread-private, created with thread start, thread destroyed; memory model of Java methods described by the virtual machine stack: Each method creates a stack frame (a stack frame) at the beginning of execution to store local variable tables, operand stacks, dynamic links, method exits, and so on. Each method's call execution and return ends with a stack frame on the virtual machine stack in the stack and out of the stack process.

A local variable table is the name of an area of memory where local variables are stored: the base data type (8 Java basic data Types), the reference type, the return address, and the 64-bit long and double type data occupy 2 local variable spaces, while the other data types occupy only 1 , because of the type size determination and the number of variables compiled, the local variable table is known at the time it was created, and this part of the memory space can be allocated at compile time, and the local variable table size does not need to be modified during the method run.

In the virtual machine specification, two exceptions are specified for this area of memory:

1. If the stack depth requested by the thread is greater than the depth allowed by the virtual machine (? ), throws an StackOverflowError exception;

2. If the virtual machine can dynamically expand, when the extension is unable to request enough memory, will throw an OutOfMemory exception;

2. Local Method Stack

The local method stack is also thread-private and is almost identical to the virtual machine stack: The virtual machine stack provides an access stack for Java method execution, while the local method stack provides services for the virtual machine to perform the native method.

In the virtual machine specification, the local method stack implementation method is not mandatory, can be realized by the specific virtual machine; hotspot virtual machine is directly to the virtual machine stack and the local method stack together to achieve, for other virtual machines to achieve this piece of method, the reader is interested in the relevant information can be queried;

As with virtual machine stacks, the local method stack throws exceptions as well StackOverflowError和OutOfMemory .

3. Program Calculator

The program calculator is also a thread-private memory area. The line number indicator (pointing to an instruction) that the thread executes the byte code can be considered to be the next instruction that needs to be executed by changing the value of the counter, and the execution order of branching, looping, jumping, exception handling, thread recovery and so on is dependent on this counter to complete. The multithreading of virtual machines is achieved by rotating and allocating processor execution time, the processor (which is a kernel for multi-core processors) can only execute one command at a time, so the thread needs to revert to the correct execution location after a switch is performed, and each thread has a separate program calculator.

When executing a Java method, this program calculator records (points to) the byte-code instruction address that the current thread is executing, and if the native method is executing, the value of the calculator is undefined because the hotspot virtual machine threading model is the native threading model. That is, each Java thread directly maps the OS (operating system) of the thread, the implementation of the native method, by the OS directly, the value of this counter virtual machine is useless; because this calculator is a small footprint memory area, the thread is private, do not need to expand, is the only area in the virtual machine specification that does not specify any OutOfMemoryError exceptions.

4, heap memory (HEAP)

The Java heap is a thread-shared memory region. Can be said to be a virtual machine management of the largest area of memory, created when the virtual machine started; Java heap memory is primarily a storage object instance, and almost all object instances (including arrays) are stored here, so this is also the main memory area of garbage collection (GC). The contents of the GC are not described here;

According to the virtual machine specification, Java heap memory can be in discontinuous physical memory, as long as it is logically contiguous and the space extension is not limited, it can be either a fixed size or an extension, and an exception will be thrown if the heap memory does not have enough space to complete the instance allocation and cannot be extended OutOfMemoryError .

5. Method area

The method area, like heap memory, is a thread-shared memory region; Store data that has been loaded by a virtual machine, constants, static variables, compile-time code, and so on; The virtual machine specification does not have too many restrictions on the implementation of the method area and does not require contiguous physical memory space, as well as heap memory, which can be fixed or extensible , you can also choose not to implement garbage collection, and an exception will be thrown when the method area is unable to meet the memory allocation requirements OutOfMemoryError .

6, Direct Memory

Direct memory is not part of the virtual machine management memory, but this part of memory may be used frequently; When Java programs use the native method (such as NIO, which is not described here for NIO), the memory may be allocated directly out of the heap, but the total memory space size is limited, You will also experience a low memory condition that throws an OutOfMemoryError exception.

Second, instance object storage access

The 1th above for the virtual machine in each region has a general description, for each region, there are data is how to create, layout, access problems, we use the most commonly used heap memory as an example based on hotspot say these three aspects.

1. Instance object creation

When the virtual machine executes to a new command, first, the class notation reference of the creation object is positioned from the constant pool, the check class has been loaded initialized, and if it is not loaded, the class loading initialization process (about class loading, which is not described here) is thrown ClassNotFoundException ;

After a class load check, it is actually allocating physical memory (heap memory) to the object, the amount of memory space required by the object is determined by the corresponding class, and after the class is loaded, the memory space required for the object of the class is fixed, and the memory space allocated to the object is equal to the partition of the object from the heap.

Divided into two ways of allocating memory, depending on whether the memory space is contiguous (divided into two parts that have been allocated and unassigned):

1. Continuous memory: Allocated and unassigned between the use of a pointer as a demarcation point, object memory allocation requires only the pointer to the unallocated memory segment to move a certain amount of space, this way is called "pointer collision."

2. Non-contiguous memory: The virtual machine needs to maintain (record) a list of those memory blocks in the heap that have not been allocated, select a suitable size area of memory allocated to the object when allocating object memory, and update the list, which is called an "idle list."

The allocation of object memory also encounters concurrent problems, and virtual machines use two solutions to solve this thread-safety problem: The first use of CAS (Compare and set) + recognition Retry to ensure the atomicity of the allocation operation; The second is that the memory allocation divides the different spaces according to the thread, That is, each thread allocates a single thread-private memory in the heap, called the local thread allocation buffer (thread native allocation buffer,tlab), that thread allocates memory directly from the Tlab, A synchronization operation is allocated from the heap only if the thread's Tlab allocation needs to be reassigned, which effectively reduces the concurrency of object allocation heap memory between threads, and whether the virtual machine uses Tlab, which is set through JVM parameter-xx:+/-usetlab.

After the memory allocation is complete, in addition to the object header information, the virtual opportunity initializes the allocated memory space to a value of 0, guaranteeing that the field of the object instance can be used directly to the 0 value of the data type, and that the Init method completes the initialization of an instance object, followed by the completion of the code;

2, the object in memory layout

In a hotspot virtual machine, objects are divided into 3 parts in memory: Object Header (header), instance data (Instance), alignment padding (Padding):

The object header is divided into two parts: Some store object run-time data, including hash code, garbage collection generational age, object lock status, thread held lock, biased thread ID, biased time stamp, etc. in 32-bit and 64-bit virtual machines, this part of the data occupies 32-bit and 64-bit, respectively, because of more run-time data, 32-bit or 64-bit is not enough to completely store all the data, so this part is designed to store the Run-time data in a non-fixed format, instead of using different bits to store the data depending on the state of the object, and another part that stores the object type pointer to the object's class, but this is not necessary The object's class metadata is not necessarily to be determined using this part of the store (as described below);

Instance data is the content that stores the various types of data defined by the object, and the data that the program defines is not stored exactly in the order defined, and is determined in the order in which the virtual machine assigns policies and definitions:long/double, int, Short/char, byte/ Boolean, OOP (ordinary Object ponint), you can see that the policy is allocated according to the type of placeholder, the same type will be allocated memory together, and, under these prerequisites, the parent variables order precede the subclass;

But the object fills this part not necessarily to be possible to exist, it only is plays the position alignment the function, in the hotspot virtual Machine memory management is manages according to 8 bytes, therefore when the memory is allocated, the object size is not a multiple of 8, then the alignment fills the complement;

3, Access to objects
In the Java program, we created an object, and we actually get a reference type variable that actually operates an instance in the heap memory, and in the virtual machine specification, only the reference (reference) type is a reference to the object, without stipulating how the reference is positioned, Access to instances in the heap; In the current mainstream virtual machines, there are two main ways to achieve object access:

1. Handle mode: The heap memory is divided into a field as a handle pool, the reference variable is stored in the object's handle address, and the handle stores the sample object and object type of specific address information, so the object header can not contain the type of object:



2. Pointer Direct access: the reference type stores directly the address information of the instance object in the heap, but this must require the object's type to be in the layout of the instance object:


These two ways of accessing each have an advantage: when the object address changes (memory collation, garbage collection), handle way access to the object, reference variables do not need to change, only to change the object in the handle of the address value can be, and the use of direct access to the pointer, you need to modify the object all references; Can reduce the first addressing operation, in the case of a large number of object access, the advantages of this approach is obvious; the hotspot virtual machine is the direct access method using this pointer.

Third, run-time memory exceptions

There are two kinds of abnormal situations in the Java program that can occur mainly in the runtime: OutOfMemoryError, Stackoverflowerror; what happens to that memory area, which is simply mentioned, that other memory areas will occur except for the program counter. This section mainly demonstrates the occurrence of an exception in each memory area through an instance code, which uses many common virtual machine startup parameters to better illustrate the situation. (How to use parameters to run programs do not describe here)

1, Java heap memory overflow

Heap memory overflow Occurs when an object is created after the heap capacity reaches the maximum heap capacity, as long as the objects are created in the program and are guaranteed to not be garbage collected:

/**
 * Virtual machine parameters:
 *-xms20m Minimum heap capacity
 *-xmx20m Maximum heap capacity
 * @author HWZ
 * * *
 /Public
class Headoutofmemoryerror {public

  static void Main (string[] args) {
    //Use container to save objects to ensure that objects are not garbage collected
    list< headoutofmemoryerror> listtoholdobj = new arraylist 
 

Here can add virtual machine parameters :-XX:HeapDumpOnOutOfMemoryError , in the sending Oom exception when the virtual machine dump the current heap of snapshot files, follow-up can pass this file participle exception problem, this does not do detailed description, follow up to write a blog detailed description using the Mat tool to analyze memory problems.

2, virtual machine stack and local method stack Overflow

In the hotspot virtual machine, these two stack of methods are not implemented together, according to the virtual machine specification, these two areas of memory will occur two kinds of exceptions:

1. If the thread request stack depth is greater than the maximum depth allowed by the virtual machine, throw the stackoverflowerror exception;

2. If the virtual machine in the expansion stack space, can not request large memory space, will throw OutOfMemoryError exception;

These two situations are actually overlapping: when the stack space cannot continue to be allocated, whether the memory is too small or the stack depth used is too large, this is not a good distinction.

Test your code in two different ways

1. Use-XSS parameters to reduce stack size, infinite recursive call a method, unlimited stack depth:

/**
 * Virtual machine parameters:<br>
 *-xss128k stack capacity
 * @author HWZ
 * */public
class Stackoverflowerror {

  private int stackdeep = 1;

  /**
   * Infinite recursion, infinite increase call stack depth
   * * Public
  void Recursiveinvoke () {
    stackdeep++;
    Recursiveinvoke ();
  }
  public static void Main (string[] args) {
    Stackoverflowerror soe = new Stackoverflowerror ();

    try {
      soe.recursiveinvoke ();
    } catch (Throwable e) {
      System.out.println ("Stack deep =" + Soe.stackdeep);
      throw e;
    }
  }
}

method to define a large number of local variables, increase the length of the local variable table in the method stack, and also infinite recursive invocation:

/**
 * @author hwz
 *
 *
/public class Stackoomerror {

  private int stackdeep = 1;

  /**
   * Defines a large number of local variables, increasing the local variable table in the stack
   * infinite recursion, infinite increase call stack depth
  /public void Recursiveinvoke () {
    Double i;
    Double I2;
    //....... Here omit a large number of variable definitions
    stackdeep++;
    Recursiveinvoke ();
  }
  public static void Main (string[] args) {
    Stackoomerror soe = new Stackoomerror ();

    try {
      soe.recursiveinvoke ();
    } catch (Throwable e) {
      System.out.println ("Stack deep =" + Soe.stackdeep);
      throw e;
    }
  }
}

The above code test shows that whether the frame stack is too large or virtual machine capacity is too small, when the memory can not be allocated, the throw is Stackoverflowerror exception;

3. Method area and run frequent pool overflow

Here's a description of string's Intern method: If the string constant pool already contains a string that is equal to this string object, then returns the String object that represents it, otherwise adds the string object to the constant pool and returns a reference to the string object In this way, the string object is constantly added to the constant pool, causing the overflow:

/**
 * Virtual machine parameters:<br>
 *-xx:permsize=10m Permanent Zone size *
 -xx:maxpermsize=10m Permanent Zone maximum capacity
 * @author HWZ
 *
 *
/public class Runtimeconstancepooloom {public

  static void Main (string[] args) {

    //Save object using container, Ensure objects are not garbage collected
    list<string> List = new arraylist<string> ();

    Use the String.intern method to increase the object for the constant pool
    (int i=1; true; i++) {
      List.add (string.valueof (i). Intern ());
    }
}

However, this test code does not occur in the JDK1.7 run a frequent pool overflow, in JDK1.6 will occur, and then write a test code to verify the problem:

/**
 * String.intern method to test under different JDK
 * @author HWZ * */Public
class Stringinterntest {

  public static void Main (string[] args) {

    String str1 = new StringBuilder ("Test"). Append (""). toString ();
    System.out.println (str1.intern () = = str1);

    String str2 = new StringBuilder ("Test"). Append (""). toString ();
    System.out.println (str2.intern () = = str2);
  }

The result of running under JDK1.6 is false, false;

The result of running under JDK1.7 is true, true;

Originally in JDK1.6, The Intern () method copied the first encountered string instance to the permanent generation, returning the reference to an instance in the permanent generation, while the string instance created by StringBuilder was in the heap, so unequal;

In JDK1.7, the Intern () method does not copy the instance, except for the reference to the instance where the constant pool records the first occurrence, so the intern returns a reference that is the same as the instance created by StringBuilder, so returns true;

Therefore, the test code that overflows the constant pool does not have a constant pool overflow exception, but a heap out-of-memory overflow exception may occur after running;

To test the method area overflow, just keep adding things to the method area, such as class name, access modifier, Chang, and so on. We can allow the program to load a large number of classes to continuously populate the method area causing overflow, which we use cglib to directly manipulate bytecode to generate a large number of dynamic classes:

/**
 * Method Area memory Overflow test class
 * @author hwz
 * * *
/public class Methodareaoom {public

  static void main (String [] args {
    //Use gclib infinite dynamic create subclass while
    (true) {
      enhancer enhancer = new enhancer ();
      Enhancer.setsuperclass (maoomclass.class);
      Enhancer.setusecache (false);
      Enhancer.setcallback (New Methodinterceptor () {
        @Override public
        object Intercept (Object obj. Object[] args,
            methodproxy proxy) throws Throwable {return
          proxy.invokesuper (obj, args);
        }
      });
      Enhancer.create ();
    }

  Static class Maoomclass {}
}

With VISUALVM observations, the number of JVM load classes and the use of Pergen are rising in a straight line:

4. Direct Memory Overflow

The size of the direct memory can be set through the virtual machine parameters :-xx:maxdirectmemorysize, to allow direct memory overflow, only need to continue to request direct memory can be used in Java NIO Direct memory cache test:

/**
 * Virtual machine parameters:<br>
 *-xx:maxdirectmemorysize=30m Direct Memory Size
 * @author hwz
 */public
class directmemoryoom {public

  static void Main (string[] args) {
    list<buffer> buffers = new arraylist<buffer& gt; ();
    int i = 0;
    while (true) {
      //print the current first few times
      System.out.println (++i);
      Direct memory consumption through constant application cache memory
      Buffers.add (Bytebuffer.allocatedirect (1024*1024));//per Request 1M
    }}

In the loop, each request 1M direct memory, set the maximum direct memory is 30M, the program runs to 31 times throws an exception:java.lang.OutOfMemoryError: Direct buffer memory

Iv. Summary

The above is the entire content of this article, this article mainly describes the memory layout structure of the JVM, objects store and access memory exceptions that may occur in each memory area; The main bibliography, "deep understanding of Java Virtual Machines (second edition)", If anything is wrong, please point out in the comments; Thank you for your support to the cloud-dwelling community.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.