How does object reference seriously affect the Garbage Collector? (1)

Source: Internet
Author: User

If you think that Java game developers are Formula One drivers in the Java programming world, you will understand why they place so much emphasis on program performance. Game developers face performance issues almost every day, often beyond the scope of general programmers. Where can we find these special developers? The Java game community is a good place to go. Although there may not be many server-side applications on this site, we can still benefit from this. Let's take a look at what these "bits are like gold" game developers face every day, we often get valuable experience from it. Let's start the game!

Object Leakage
Game programmers, like other programmers, also need to understand the nuances of the Java Runtime Environment, such as garbage collection. Garbage collection may be one of the more difficult concepts to understand, because it cannot always solve the problem of heap management in the Java Runtime Environment. There seems to be a lot of discussions like this. It starts or ends with "my question is about garbage collection ".

If you encounter an out-of-memory error. So you want to find the problem using the detection tool, but this is futile. You can easily think of another credible reason: this is a problem with Java Virtual Machine heap management, rather than your own program. However, as senior experts in the Java game community explained more than once, Java virtual machines do not have any proven object leakage issues. Practice has proved that the garbage collector can accurately determine which objects can be collected and reclaim their memory space to the Java Virtual Machine. Therefore, if you encounter an error of memory depletion, this may be entirely caused by your program, that is, your program contains "unintentional object retention) ".

Memory leakage and unintentional object retention
What is the difference between memory leakage and unintentional object retention? For programs written in Java, there is no difference. Both of them refer to some object references in your program, but you do not need to reference these objects. A typical example is to add some objects to a collection for later use, but you forget to delete these objects from the collection after use. Because the set can be expanded without limit and never become smaller, when you add too many objects to the Set (or many objects are referenced by elements in the set, the heap space will fill up and cause memory exhaustion errors. The garbage collector cannot collect the objects that you think are used up, because for the garbage collector, applications can still access these objects at any time through this collection, therefore, these objects cannot be treated as garbage.

For languages without garbage collection, such as C ++, memory leakage is different from unintentional object retention. C ++ programs, like Java programs, may produce unintentional object retention. However, there is a real memory leakage in the C ++ program, that is, the application cannot access some objects so that the memory used by these objects cannot be released and returned to the system. Fortunately, this memory leakage is impossible in Java programs. Therefore, we prefer to use "unintentional object retention" to indicate the memory issue that causes Java programmers to break their heads. In this way, we can be different from other programmers who use a language without garbage collection.

Tracked objects
So what should I do when an unconscious object is found to be retained? First, you need to determine which objects are unintentionally retained and find out which objects are referencing them. Then you must arrange where to release them. The easiest way is to use a detection tool that can generate snapshots for the heap to identify these objects, compare the number of objects in the heap snapshot, track these objects, and find the objects that reference these objects, then force the garbage collection. With such a detector, the subsequent work is relatively simple:

Wait until the system reaches a stable State. In this state, most newly generated objects are temporary and meet the collected conditions; this state is generally completed after all the initialization work of the program.
Force a garbage collection and create an object snapshot for the heap at this time.
Any operation that can generate objects that are unintentionally retained.
Force a garbage collection, and then take a second object snapshot of the objects in the System Heap.
Compare two snapshots to see which objects are referenced more than the first snapshot. Because you have forced garbage collection before the snapshot, the remaining objects should be the objects referenced by the application, by comparing two snapshots, we can accurately find the newly generated objects retained by the program.
Based on your understanding of the application and comparison of the two snapshots, you can determine which objects are unintentionally retained.
Trace the reference chains of these objects to find out which objects are being referenced and unintentionally retained until you find the root object, which is the root cause of the problem.

Explicitly assigning null (nulling) variables
When talking about the topic of garbage collection, there will always be an attractive discussion about whether explicit null variables help program performance. Null variables are simply null values that are explicitly assigned to this variable, and the reference of this variable loses its scope.


Listing 1. Local Scope

Public static String scopingExample (String string ){
StringBuffer sb = new StringBuffer ();
Sb. append ("hello"). append (string );
Sb. append (", nice to see you! ");
Return sb. toString ();
}

When this method is executed, the runtime stack retains a reference to the StringBuffer object, which is generated in the first line of the program. During the execution of this method, the reference of the object stored in the stack will prevent the object from being treated as garbage. When this method is executed, the variable sb loses its scope, and the corresponding runtime stack deletes the reference to the StringBuffer object. So there is no reference to the StringBuffer object, and now it can be used as garbage collection. Stack deletion references are equivalent to assigning a null value to the variable sb at the end of the method.

Error Scope
Since Java virtual machines can perform operations equivalent to null assignment, what is the use of explicitly assigning null variables? Explicit null variables are useless for variables in the correct scope. But let's take a look at another version of scopingExample. This time we will put the variable sb in an error scope.

Listing 2. Static Scope

Static StringBuffer sb = new StringBuffer ();
Public static String scopingExample (String string ){
Sb = new StringBuffer ();
Sb. append ("hello"). append (string );
Sb. append (", nice to see you! ");
Return sb. toString ();
}

Currently, sb is a static variable, so as long as its class is still loaded in the Java virtual machine, it will also exist. This method is executed once. A new StringBuffer will be created and referenced by the sb variable. In this case, the StringBuffer object previously referenced by the sb variable will die and become the garbage collection object. That is to say, the dead StringBuffer object is retained by the Program for a longer time than it actually needs to be retained-if it no longer calls the scopingExample method, It will be retained forever.

A problematic example
Even so, can explicit null variables improve performance? We will find it hard to believe that an object will have a greater or less significant impact on the performance of the program until I see an example provided by Sun engineers at Java Games, this example contains an unfortunate large object.

Listing 3. Objects still in static Scope

Private static Object bigObject;

Public static void test (int size ){
Long startTime = System. currentTimeMillis ();
Long numObjects = 0;
While (true ){
// BigObject = null; // explicit nulling
// SizableObject cocould simply be a large array, e.g. byte []
// In the JavaGaming discussion it was a BufferedImage
BigObject = new SizableObject (size );
Long endTime = System. currentTimeMillis ();
++ NumObjects;
// We print stats for every two seconds
If (endTime-startTime> = 2000 ){
System. out. println ("Objects created per 2 seconds =" + numObjects );
StartTime = endTime;
NumObjects = 0;
}
}
}

In this example, a simple loop is used to create a large object and assign it to the same variable. The number of created objects is reported every two seconds. Current Java

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.