Java Memory Management

Source: Internet
Author: User
Tags class definition

Java Memory Management mechanism

JAVA Memory Management Summary

    1. How Java manages memory

      The memory management of Java is the allocation and release of objects. (Two parts)

Allocation: The allocation of memory is done by the program, and the programmer needs to request memory space for each object through the keyword new (except for the base type), and all objects allocate space in the heap. Release: The release of an object is determined and executed by the garbage collection mechanism, which does simplify the programmer's work. But it also adds to the JVM's work. Because, in order for the GC to properly dispose of objects, the GC must monitor the running state of each object, including the application, reference, reference, assignment, etc. of the object, which the GC needs to monitor.

    1. What is Java's memory leak?

In Java, the memory leak is the existence of some assigned objects, which have the following two characteristics, first of all, these objects are accessible, that is, in the graph, the existence of the path can be connected to it (that is, the memory object still exists), and second, these objects are useless, that is, the program will no longer use these objects. If the object satisfies both conditions, these objects can be judged as a memory leak in Java, which is not reclaimed by the GC, but it consumes memory.

    1. The memory area of the JVM is composed

Java has two kinds of memory: one is stack memory, the other is heap memory 1. The basic type variables and the reference variables of the objects defined in the function are allocated in the stack memory of the function; 2. When heap memory is used to hold objects and arrays created by new and the instance variables of an object define a variable in a function (code block), Java allocates memory space for the variable in the stack, and when the scope of the variable is exceeded, Java automatically frees the allocated memory space for that variable. The memory allocated in the heap is managed by the Java Virtual machine's automatic garbage collector

Advantages and disadvantages of heap and stack

The advantage of a heap is that it can dynamically allocate memory size, and the lifetime does not have to tell the compiler beforehand because it allocates memory dynamically at run time.

The disadvantage is that the memory is dynamically allocated at run time, the access speed is slow, and the advantage of the stack is that the access speed is faster than the heap, second only to the registers directly in the CPU.

In addition, the stack data can be shared. However, the disadvantage is that the size and lifetime of the data in the stack must be deterministic and inflexible.

    1. How data in Java is stored in memory

A) Basic data types

There are 8 basic data types in Java, namely int, short, long, byte, float, double, Boolean, char (note, and no basic type of string). The definition of this type is defined by a form such as int a = 3; long B = 255L; such as int a = 3; Here A is a reference to the int type, which points to the literal value of 3. The data of these literals, because of the size of the known, the lifetime of the known (these literals are defined in a program block, the program block exits, the field value disappears), for the sake of speed, it exists in the stack.

In addition, the stack has a very important particularity, is that there is data in the stack can be shared. For example: We also define:

int a=3;int b=3;

The compiler processes int a = 3 First, it creates a reference to a variable in the stack, and then looks for an address with a literal value of 3, finds an address that holds the literal value of 3, and then points A to the address of 3. then the int b = 3 is processed, and after the reference variable of B is created, B is pointed directly to the address of 3 because there are already 3 literals in the stack. In this case, A and B both point to 3. After defining the value of a and B, make a = 4, then B will not be equal to 4, or equal to 3. Inside the compiler, it will re-search the stack if there is a 4 literal value, if not, re-open the address to store the value of 4, if already, then direct a to this address. Therefore the change of a value does not affect the value of B.

B) Object

In Java, the creation of an object consists of two steps of declaring and instantiating an object, with an example to illustrate the object's memory model. Suppose there is a class Rectangle defined as follows:

public class Rectangle {double width;double height;public Rectangle(double w,double h){w = width;h = height;}}

(1) The memory model when declaring an object is Rectangle rect; When an object rect is declared, the memory space is allocated in the stack memory as a reference variable to the object, but the value of Rectangle is empty, which is called rect an empty object. An empty object cannot be used because it does not yet reference any of the entities. (2) Memory model when object instantiation when executing rect=new Rectangle (3,5), two things are done: allocating memory for the class's member variable Width,height in heap memory and initializing it to the default value for each data type , followed by an explicit initialization (the initialization value at the time of the class definition), and finally the constructor method, which assigns a value to the member variable. Returns a reference to the object in the heap memory (the same as the first address) to the reference variable rect, which can then be referenced by a rect to the object in the heap memory.

c) Create multiple different object instances

A class can create several different object instances by using the new operator, which will be allocated a different memory space in the heap, changing the state of one of the objects without affecting the state of other objects. For example:

Rectangle r1= new Rectangle(3,5);Rectangle r2= new Rectangle(4,6);

At this point, the memory space is allocated for the member variable width, height of the two objects in heap memory, and the space occupied by the two objects in the heap memory is different from each other. If you have:

Rectangle r1= new Rectangle(3,5);Rectangle r2=r1;

Only one object instance is created in heap memory, two object references are created in stack memory, and two object references point to an object instance.

d) Packing class

The basic types have corresponding wrapper classes: such as int corresponding to the integer class, double corresponding to the double class, and so on, the basic type definition is directly in the stack, if the wrapper class to create the object, just like the normal object. For example: int i=0;i is stored directly in the stack. Integer I (which is the object at this time) = new Integer (5), so that the I object data is stored in the heap, I's reference is stored in the stack, and the object is manipulated through references in the stack.

e) String

String is a special wrapper class data. Can be created in the following two ways:

String str = new String("abc");String str = "abc";

The first method of creation is the same as the creation of a normal object, and the second creates a method in which Java internally translates the statement into the following steps: (1) First define an object reference variable named str to the String class: String str; (2) Find in the stack whether there is a value of "ABC" Address, if not, open a store literal as an "ABC" address, then create a new String Class object O, and point the string value of O to the address, and note the referenced object o next to the address of the stack. If you already have an address with a value of "ABC", look for the object o, and return to the address of O. (3) Point Str to the address of the object o. It is important to note that the string values in the generic string class are directly stored values. But like string str = "abc"; In this case, the string value holds a reference to the data in the existing stack. To better illustrate this problem, we can verify it by following several code.

String str1="abc";String str2="abc";System.out.println(s1==s2);//true

Note that the Str1.equals (STR2) is not used here, as this will compare the values of two strings for equality. = = number, as described in the JDK, returns true only if two references point to the same object. And what we're looking at here is whether str1 and str2 all point to the same object. Let's look at the following code again.

String str1= new String("abc");String str2="abc";System.out.println(str1==str2);//false

Two references were created. Two objects were created.   Two references point to a different two objects, respectively. The above two code shows that as long as new () is used to create the object, it is created in the heap, and its string is stored separately, even if the data in the stack is the same, it is not shared with the data in the stack.

f) Array

When defining an array, int x[], or int []x;, when an array reference is created in the stack memory, the array is referenced by the reference (that is, the array name). X=new Int[3]; Allocates 3 space in heap memory to hold int data, the first address of the heap memory is placed in the stack memory, and each array element is initialized to 0.

g) Static variables

Static modified variables and methods, in effect, specify the "fixed position"-static storage of these variables and methods in memory, which can be understood as memory space shared by all instance objects. The static variable is somewhat similar to the concept of a global variable in C; static represents the sharing of memory, that is, every instance of it points to the same memory address. To get the static is to tell the JVM that it is static and that its references (with indirect references) point to the same location, where you change it, it doesn't become the same, you clean it up, it doesn't come back. When is the static variable and method initialized? For two different class properties, the static property is different from the instance property when it is initialized. The instance property is initialized when the instance is created, and the static property is initialized when the class is loaded, that is, when the class is first used, and is not initialized again for subsequent instance creation. We can often see examples like the following to illustrate this problem:

class Student{static int numberOfStudents=0;Student(){numberOfStudents++;}}

Each time a new student instance is created, the member numberofstudents is incremented continuously, and all student instances have access to the same numberofstudents variable, in effect an int The numberofstudents variable is stored in memory only in one place.

    1. Examples of memory management in Java

Multiple parts of a Java program (methods, variables, objects) reside in memory in the following two locations: Heap and Stack, now we only care about 3 kinds of things: instance variables, local variables and objects: instance variables and objects residing on the heap local variables reside on the stack let's look at a Java program, See how his parts are created and mapped to stacks and heaps:

public class Dog {Collar c;String name;//1. main()方法位于栈上public static void main(String[] args) {//2. 在栈上创建引用变量d,但Dog对象尚未存在Dog d;//3. 创建新的Dog对象,并将其赋予d引用变量d = new Dog();//4. 将引用变量的一个副本传递给go()方法d.go(d);}//5. 将go()方法置于栈上,并将dog参数作为局部变量void go(Dog dog){//6. 在堆上创建新的Collar对象,并将其赋予Dog的实例变量c =new Collar();}//7.将setName()添加到栈上,并将dogName参数作为其局部变量void setName(String dogName){//8. name的实例对象也引用String对象name=dogName;}//9. 程序执行完成后,setName()将会完成并从栈中清除,此时,局部变量dogName也会消失,尽管它所引用的String仍在堆上}
    1. Garbage collection mechanism:

(Question one: What is a garbage collection mechanism?) Garbage collection is a dynamic storage management technology that automatically frees objects that are no longer referenced by the program, and implements automatic resource recovery based on a specific garbage collection algorithm. When an object is no longer referenced, the memory reclaims the space it occupies so that space is used by later new objects to avoid a memory leak. (Question two: what are the characteristics of Java garbage collection?) The JAVA language does not allow programmers to directly control the use of memory space. The allocation and recycling of memory space is done automatically by the JRE in the background, especially for garbage collection (Garbagecollection, also known as garbage collection), which can only be monitored and controlled by a super-thread provided by the running environment. (Question three: When will the garbage collector run?) Typically, garbage collection occurs automatically when the CPU is idle or out of space, and programmers cannot precisely control the timing and order of garbage collection. (Question four: What objects meet the garbage collection criteria?) When no gain thread can access an object, the object is eligible for garbage collection. (Question five: How does the garbage collector work?) If the garbage collector finds that an object cannot be accessed by any live thread, he will consider the object to be eligible for deletion, add it to the recycle queue, but not destroy the object immediately, and when to destroy and free memory is unpredictable. Garbage collection cannot be enforced, but Java provides methods (such as the System.GC () method) that allow you to request that the JVM perform garbage collection instead of requiring that the virtual opportunity do its best to satisfy the request, but there is no guarantee that the JVM will remove all unused objects from memory. (Question six: Can a Java program run out of memory?) Can The garbage collection system attempts to remove objects from memory when they are not being used. However, if you keep too many live objects, the system may run out of memory. The garbage collector does not guarantee enough memory to ensure that available memory is managed as efficiently as possible. (Question seven: How do I show objects that conform to the garbage collection criteria?) ) (1) null reference: When the object does not have a reachable reference to him, he is eligible for garbage collection. In other words, if there is no reference to him, deleting the object's reference can achieve the purpose, so we can set the reference variable to NULL to meet the garbage collection criteria.

StringBuffer sb = new StringBuffer("hello");System.out.println(sb);sb=null;

(2) Re-assign a value to the reference variable: You can refer to another object by setting a reference variable to disassociate the reference variable from the reference to an object.

StringBuffer sb1 = new StringBuffer("hello");StringBuffer sb2 = new StringBuffer("goodbye");System.out.println(sb1);sb1=sb2;//此时"hello"符合回收条件  

(3) object created within the method: The local variable created is only present within the duration of the method's action. Once the method returns, objects created within this method are eligible for garbage collection. One notable exception is the return object of the method.

public static void main(String[] args) {Date d = getDate();System.out.println("d = " + d);}private static Date getDate() {Date d2 = new Date();StringBuffer now = new StringBuffer(d2.toString());System.out.println(now);return d2;}

(4) Quarantine reference: In this case, the object being reclaimed still has a reference, which is known as the isolated island. If there are two instances, they reference each other, and all other references to both objects are deleted, and no other thread can access either of the two objects. can also meet garbage collection conditions.

public class Island {Island i;public static void main(String[] args) {Island i2 = new Island();Island i3 = new Island();Island i4 = new Island();i2.i=i3;i3.i=i4;i4.i=i2;i2=null;i3=null;i4=null;}}

(Issue eight: Cleanup before garbage collection------Finalize () method) Java provides a mechanism that enables you to run some code before an object is just going to be garbage collected. This code is within a method named Finalize (), and all classes inherit this method from the Object class. Because the garbage collector cannot be guaranteed to delete an object. Therefore, the code placed in finalize () cannot be guaranteed to run. It is therefore recommended that you do not rewrite finalize ();

    1. Final question: Final makes the modified variable "unchanged", but because the nature of the object type variable is "reference", so that "invariant" also has two meanings: the reference itself is unchanged, and the reference point to the object does not change. The reference itself does not change:

As you can see, final is valid only for the referenced "value" (the memory address of the object it points to), forcing the reference to point only to the object that was initially pointed at, and changing its point to cause a compile-time error. Final is not responsible for the change in the object it points to. This is similar to the = = Operator: the = = operator is only responsible for the reference "value" equality, as to whether the address points to the object content is equal, the = = operator is no matter. In an example:

public class Name {private string Firstname;private string Lastname;public string Getfirstname () {return firstname;} public void Setfirstname (String firstname) {this.firstname = FirstName;} Public String Getlastname () {return LastName;} public void Setlastname (String lastname) {this.lastname = LastName;}} public class Name {private string Firstname;private string Lastname;public string Getfirstname () {return firstname;} public void Setfirstname (String firstname) {this.firstname = FirstName;} Public String Getlastname () {return LastName;}         public void Setlastname (String lastname) {this.lastname = LastName;}} Write the test method: public static void Main (string[] args) {final name name = new Name (); Name.setfirstname ("JIM"); Name.setlastname (" Green "); System.out.println (Name.getfirstname () + "" +name.getlastname ());} public static void Main (string[] args) {final name name = new name (); Name.setfirstname ("JIM"); Name.setlastname ("Green"); System.out.println (Name.getfirstname () + "" +name.getlastname ());}

Understanding the final question has a very important meaning. Many program vulnerabilities are based on this----final can only guarantee that a reference will always point to a fixed object, and that the state of that object is not guaranteed to be constant. In multi-threaded operations, an object is shared or modified by multiple threads, and a thread's unconscious modification of an object can cause another thread that uses this object to crash. One wrong solution is to declare it as final when the object is newly created, with the intention of making it "forever". In fact, it was futile. Final There is a notable point: look at the following sample programs first:

class Something {final int i;public void doSomething() {System.out.println("i = " + i);}}class Something {final int i;public void doSomething() {System.out.println("i = " + i);}}

For class variables, the Java virtual opportunity is automatically initialized. If the initial value is given, it is initialized to that initial value. If not given, it is initialized to the default initial value of the type variable. But for a class variable that is final decorated, the virtual machine does not give it an initial value, and must be given a definite constructor before the end of the constructor. Can be modified to "final int i = 0;".

    1. How to write a program more robust: 1. Release the reference of the useless object as soon as possible. A good idea is to use a temporary variable when the reference variable is automatically set to null after exiting the active domain, implying that the garbage collector collects the object to prevent a memory leak. For instances where pointers are still pointing, the JVM does not reclaim the resource because garbage collection uses the null object as garbage and improves the efficiency of the GC recycle mechanism; 2, the definition string should try to use string str= "Hello"; form, avoid using string str = new string ("Hello"); The form. Because you want to use the same content string, you don't have to new a string every time. For example, we want to initialize a String reference variable named S in the constructor, set it to the initial value, and should do this:
public class Demo {private String s;public Demo() {s = "Initial Value";}}public class Demo {private String s;...public Demo {s = "Initial Value";}...}

Rather than

s = new String("Initial Value");  

The latter invokes the constructor every time, generates new objects, performs poorly and has a large memory overhead, and makes no sense, because the string object is immutable, so for a string of the same content, just one string object to represent it. It also says that multiple calls to the above constructor create several objects whose String type property s all point to the same object.

3, our program is inevitably a lot of string processing, avoid using string, should use a lot of stringbuffer, because string is designed to be immutable (immutable) class, so all its objects are immutable objects, see the following code;

String s = "Hello";   s = s + " world!";  String s = "Hello";s = s + " world!";

In this code, s originally pointed to a String object, the content is "Hello", and then we have a + operation on S, then the object pointed to by S has changed it? The answer is no. At this point, S does not point to the original object, and point to another String object, the content is "Hello world!", the original object is still in memory, but s this reference variable no longer points to it. With the instructions above, it is easy to derive another conclusion that if you frequently make a variety of changes to the string, or if the changes are unpredictable, then using string to represent the strings can cause significant memory overhead. Because a string object cannot be changed after it is established, a string object is required for each different string. At this point, you should consider using the StringBuffer class, which allows you to modify instead of creating a new object for each different string. Also, the conversion of these two kinds of objects is very easy. 4, minimize the use of static variables, because the static variables are global, the GC will not be recycled; 5. Avoid creating and initializing a large number of objects in the constructor of the class to prevent unnecessary memory wasting when invoking the constructor of its own class, especially large objects, the JVM will suddenly need a lot of memory, which will inevitably trigger GC optimizes the system memory environment; The declared array space is displayed, and the number of requests is significant. The following are the time consuming to initialize different types of objects:

As you can see from table 1, creating a new object takes 980 units of time, is 980 times times the local assignment time, is 166 times times the method invocation time, and it takes more time to create a new array. 6, as far as possible in the appropriate scenario to use the object pool technology to improve system performance, reduce the cost, but pay attention to the size of the object pool should not be too large, timely elimination of invalid objects to free memory resources, comprehensive consideration of the application running environment memory resource limitations, to avoid overestimation of the running environment to provide the amount of memory resources. 7, large collection objects have large data volume of business objects, you can consider chunking to deal with, and then solve a piece of the strategy to release a piece. 8. Do not create objects in frequently invoked methods, especially when creating objects in loops. You can use Hashtable,vector to create a set of object containers and then fetch those objects from the container without having to discard them each time you new. 9, generally occurs in the opening of large files or with the database once took too much data, resulting in the state of the memory Error, it is likely to calculate the maximum amount of data, and set the required minimum and maximum memory space value. 10, minimize the use of the Finalize function, because finalize () will increase the workload of GC, and GC equivalent to the cost of the system's computing power. 11, do not use the hash table, a certain development experience of developers often use hash tables (hash table in the JDK is an implementation is HASHMAP) to cache some data, thereby increasing the speed of the system. For example, the use of HASHMAP cache some material information, personnel information and other basic information, which improves the system speed, but also increased the system's memory, especially when the cache of more data. In fact, we can use the concept of caching in the operating system to solve this problem, that is, to allocate a cache of a certain size cache container, according to a certain algorithm to eliminate the need to continue to cache the object, on the one hand, because of the object cache and improve the system's operational efficiency, It also reduces the memory footprint of the system because the cache container is not infinitely expanded. Now there are many open source cache implementation projects, such as Ehcache, Oscache, etc., these projects have implemented the FIFO, MRU and other common cache algorithm

Java Memory Management

Related Article

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.