GC-oriented Java programming

Source: Internet
Author: User

Transfer from http://hellojava.info/?p=341 Hellojava public account website

GC-oriented Java programmingLeave a reply

This is an internal colleague (Mu Jian) wrote the article, there is a special Java performance optimization of the company, and it is mainly concerned about the use of Java memory optimization, focusing on the choice of data structure, the optimization effect is very obvious, So the difference between a good Java programmer and an ordinary Java programmer is quite large.

Java programmers typically do not need to consider memory issues during coding, and the JVM's highly optimized GC mechanism is most likely to handle heap cleanup issues well. So many Java programmers think, I just need to care about when to create objects, and to recycle objects, to the GC to do it! It has even been said that if memory problems are frequently considered during programming, it is a degradation that should be given to the compiler and given to the virtual machine for resolution.

In fact, there is not much problem, indeed, most of the scenes concerned about the memory, GC problems, appear a little "worrying", Gao said:

> Premature optimization is the source of all evils.

But on the other hand, what is "premature optimization"? **

> If We could do things right to the first time, why not?

In fact **JVM's memory model * * ([JMM]) is supposed to be the basic knowledge of Java programmers, after dealing with a number of JVM online memory problems will be clearly felt, * * A lot of system problems, are memory problems * *.

Students interested in the structure of the JVM memory can look at [Analysis of Java Virtual machine structure and mechanism] (http://blog.hesey.net/2011/04/introduction-to-java-virtual-machine.html) This article, this article will not repeat, this article is not concerned about the specific GC algorithm, related articles voluminous, ready to check.

Also, do not expect GC-optimized techniques that can multiply application performance, especially for I/O intensive applications or optimizations that actually fall on YOUNGGC, and may only help you reduce the frequency of YOUNGGC.

But I think that the value of a good programmer is not in the skills of the Dragon Slayer, but in the details, as I said before, if we can do it right at once and do it well, as much as possible in the scope of the permissible, why not do it?

# # # One, the basic hypothesis of GC generational # # #

Most GC algorithms use heap memory for generational (Generation) processing, but why divide, and why not memory partitioning, fragmentation, and the use of time-and age-oriented "generations" to represent different areas of memory?

The basic assumptions of GC generational * * are:

> The life cycle of most objects is very short and survival time is short.

And these short-lived objects are exactly what GC algorithms need to focus on first. So in most GC, YOUNGGC (also known as MINORGC) accounts for the vast majority of applications that are not heavily loaded and may run for months without FULLGC.

Based on this premise, in the coding process, we should * * as much as possible to shorten the life cycle of the object * *. In the past, allocating objects was a relatively heavy operation, so some programmers would minimize the number of new objects, try to reduce the allocation overhead of the heap, and reduce memory fragmentation.

However, the creation of short-lived objects is better than we thought in the JVM, so don't be stingy with the new keyword and go boldly to new.

Of course the premise is not to do meaningless creation, the higher the rate of object creation, then the faster the GC will be triggered.

Conclusion:

> Allocate small objects for cost sharing small, not stingy to create.

> GC likes this small and short-lived object most.

> makes the object's life cycle as short as possible, such as in the method body, so that it can be recycled as soon as possible in YOUNGGC, not promoted (romote) to old Generation.

# # # Two, optimization of object allocation # # #

Based on the majority of objects are small and short-lived, and there is no multi-threaded data competition. The allocation of these small objects will take precedence over the allocation of the thread-private **tlab**, the objects created in Tlab, the absence of locks, or even the cost of CAs.

The space occupied by Tlab is in Eden Generation.

When the object is larger, the Tlab space is not enough to put down, and the JVM thinks that the current thread is taking up tlab remaining space is sufficient, it will be allocated directly on the Eden generation, there is concurrent competition, so there will be the cost of CAs, but it is OK.

When the object is large enough to Eden generation, the JVM can only attempt to go to the old generation assignment, which needs to be avoided as soon as it is allocated in the older generation, the object can only be Generation GC or FULLGC is recycled.

# # # Three, the benefits of immutable Objects # # #

The GC algorithm usually needs to scan the surviving objects from the root node, scanning all surviving object references, and building an object graph.

The optimization of the GC by immutable objects is mainly embodied in the old generation.

As you can imagine, if an old generation object refers to the object of young generation, this must be taken into account in each YOUNGGC process.

In order to improve the performance of the YOUNGGC, the Hotspot JVM avoids scanning object references in old generation each time YOUNGGC, using the * * Card Table * * method.

Simply put, when an object in an old generation creates a new reference relationship to an object in young generation or releases a reference, it is marked dirty (dirty) on the token in the card table, and YOUNGGC, You just need to scan these dirty items.

A mutable object's reference relationship to other objects may change frequently, and it is possible to hold more and more references, especially containers, during the run. These will cause the corresponding card table entries to be frequently marked as dirty.

The reference relationships of immutable objects are very stable, and they are not swept to their corresponding items when the card table is scanned.

Note that immutable objects here do not refer only to the immutable ' final ' object itself, but to the real **immutable objects**.

# # # Four, quote null legend # # #

Many of the earlier Java data mentioned that placing a variable in the method body as null optimizes the performance of the GC, similar to the following code:

"' Java
List List = new ArrayList ();
Some code
list = null; Help GC
"'

In fact, this approach does little to help the GC, and sometimes it can lead to code clutter.

I remember a few years ago @rednaxelafx discussed this issue in detail in the HLL VM Group, which I did not find, the conclusion is basically:

> In a very large method body, to a larger object, its reference to null, to some extent can help the GC.

> In most cases, this behavior does not have any benefit.

So, let's just give up this "optimization" method earlier.

The GC is smarter than we thought.

# # # Five, manual file of GC # # #

The following two artifice are available on many Java materials:

> ' Thread.yield () ' yields CPU resources to other threads.

> Triggers gc via ' SYSTEM.GC ' ().

In fact, the JVM never guarantees these two things, and ' System.GC ' () in the JVM startup parameters, if explicit GC is allowed, it will trigger fullgc**, which is almost equivalent to suicide in response to sensitive applications.

So, let's keep in mind two points:

> Never use ' Thread.yield () '.

> Never use ' System.GC ' (). Unless you really need to recycle native Memory.

2nd there is an exception to the native memory if you are in the following scenario:

– Use of NiO or NIO framework (Mina/netty)

– Allocation of byte buffers using Directbytebuffer

– Using Mappedbytebuffer for memory mapping

Since **native memory can only be recycled through FULLGC (or CMS GC), it is not easy to call ' System.GC ' () and cherish it unless you know it is really necessary.

In addition, to prevent ' System.GC ' calls in some frameworks (such as the NIO Framework, Java RMI), it is recommended to add '-XX:+DISABLEEXPLICITGC ' to the startup parameters to disable the explicit GC.

This parameter has a huge pit, if you disable the ' System.GC ' (), then the above 3 scenarios of memory can not be recycled, may cause oom, if you use a CMS GC, then you can use this parameter instead: '-xx:+ Explicitgcinvokesconcurrent '.

For ' System.GC ' (), refer to a few articles @bluedavy:

–[CMS GC will not reclaim direct Bytebuffer's memory]

–[said I made a mistake on the Java startup parameters]

–[java.lang.outofmemoryerror:map failed]

# # # Six, specify container initialization size # # #

One of the features of the Java container is the ability to dynamically expand, so usually we do not think about the initial size of the setting, not enough will be automatically expanded chant anyway.

But expansion does not mean there is no cost, even a high price.

For example, some array-based data structures, such as ' StringBuilder ', ' stringbuffer ', ' ArrayList ', ' HashMap ', and so on, need to be arraycopy in terms of capacity expansion, for a growing structure, after several expansions , there will be a lot of useless old arrays, and the pressure to reclaim these arrays will all be added to the GC.

The constructors of these containers usually have a parameter that can specify size, which is recommended if the container can be estimated for some size.

However, because the expansion of the container is not to wait until the container is full, but there is a certain proportion, such as the ' HashMap ' expansion threshold and load factor (loadfactor) correlation.

The Google Guava Framework provides a very handy tool for the initial capacity of a container, such as:

"' Java
Lists.newarraylistwithcapacity (initialarraysize);

Lists.newarraylistwithexpectedsize (estimatedsize);

Sets.newhashsetwithexpectedsize (expectedsize);

Maps.newhashmapwithexpectedsize (expectedsize);
"'

So we just pass in the estimated size, the capacity of the calculation will be given to guava to do it.

Counter Example:

> If a default parameterless constructor is used to create a ArrayList that continuously increases the element until oom, this process will result in:
>– multiple array expansions, reassigning larger space arrays
>– Multiple array copies
>– Memory Fragmentation

# # # Seven, Object Pool # # #

In order to reduce object allocation overhead and improve performance, it may be possible for someone to cache the collection of objects as a means of reuse by using the object pooling method.

However, objects in the object pool will be promoted to old Generation because they survive for long periods of time, and therefore cannot be reclaimed by YOUNGGC.

And usually ... There's no effect.

For the object itself:

> If the object is small, the overhead of allocating it is small, and the object pool only increases the complexity of the code.

> If the object is larger, the pressure on the GC will be greater after the promotion to old generation.

From a thread-safe point of view, usually the pool will be accessed concurrently, then you need to deal with the problem of synchronization, this is a big pit, and * * The cost of synchronization, not necessarily more than you re-create an object small * *.

The only appropriate scenario for object pooling is that the cache reuse makes sense when the creation of each object in the pool is expensive * *, for example, each time new creates a connection or relies on RPC.

For example:

>– thread Pool
>– Database Connection Pool
>–TCP Connection Pool

Even if you really need to implement an object pool, use a mature open source framework, such as Apache Commons pool.

Also, use the JDK's threadpoolexecutor as the thread pool, and don't reinvent the wheel unless you read the AQS source and think you can write better than Doug Lea.

# # # Eight, Object scope # # #

Minimize the scope of the object, that is, the life cycle.

> If a local variable can be declared within a method, do not declare it as an instance variable.

> If your object is singleton or unchanging, declare the static variable as little as possible.

# # # Nine, all kinds of quotes # #

' Java.lang.ref.Reference ' has several subclasses that are used to process and GC-related references. There are several simple reference types for the JVM:

–strong Reference, the most common reference
–weak Reference, which is recycled by GC when there is no strong reference to it
–soft Reference can only be recycled by GC when approaching Oom.
–phantom Reference, primarily used to identify the timing of an object being GC, is typically used to do some cleanup work

When you need to implement a cache, consider taking precedence over ' weakhashmap ' instead of ' HashMap ', and of course, the better option is to use the framework, such as guava Cache.

Finally, again, these may not be able to improve the performance of the code, but familiarity with these methods is intended to help us write better code, and to work with the GC.

——————————————-
For writing GC-friendly or better-written versions of memory efficient Java applications, my advice is:
1. From our application point of view, the main waste of memory allocation is focused on the self-growth data structure, so in the use of self-growth data structure, to set reasonable initialization size, interested students can check the JRockit stringmaker, this is an optimization of the typical case;

2. Data structure selection, different data structure on the memory of the difference is very large, this can go to Google a ppt (Building memory-efficient Java applications), there is a javaone 2013 The above memory efficient Java PPT also suggest you look;

3. There are a lot of tricks, such as avoiding the memory waste caused by autobox as much as possible, such as the new object caused by Int–>integer, which is interested in finding a case code for auto Box/unbox in JavaOne 2010.

Finally recommend the next colleague's blog, there are many materials:
Http://hesey.net

=============================
The graph is derived from the content of the PPT recommended above.
Welcome to follow the public number: hellojavacases

About this number:
Share Java troubleshooting cases, Java Industry dynamics and new technologies, Java's little knowledge Point test, and talk to you about Java issues or scenarios, where only Java details are shared, without great principles, big architectures, and big frameworks.

The information posted on the public number is stored on the http://hellojava.info.

This entry is posted in Java and tagged Memory efficient on 2014-05-07.post navigation ← Ali version of the JVM under high pressure performance is not good Java applications → Leave a Reply Welcome to the public number recent POSTS
    • Is the Ops tool really easy to do?
    • Build high-availability systems
    • Borg papers
    • Is it really so low to add the machine and cut the flow?
    • Java issues I'm concerned about (Cont.)
Recent COMMENTS
    • Becile on plus machine, cutting flow is it really that low?
    • Tim on talk about OSGi
    • Google Borg paper reading notes | Travel @kryptosxon Borg Papers
    • Shiwentao on recently encountered three case
    • Lonny on the Java issue I'm concerned about
ARCHIVES
    • July 2015
    • June 2015
    • May 2015
    • April 2015
    • March 2015
    • January 2015
    • November 2014
    • October 2014
    • September 2014
    • August 2014
    • July 2014
    • June 2014
    • May 2014
    • April 2014
    • March 2014
    • February 2014
    • January 2014
    • December 2013
    • November 2013
    • October 2013
    • September 2013
    • August 2013
    • July 2013
    • June 2013
    • May 2013
    • April 2013
    • March 2013
CATEGORIES
    • Java
    • Architecture
TAGS-XSS Backlog Blktrace CMS gccms GC fragment Codecache CPU consumption Debugfs direct Buffer Memory Direct Bytebuffer DTD File.encodingh Ashmap.get http 499 Infinite loopinstanceklass iotop iowait high Javajava Auto box/unbox JavaOne java thread java default encoding Jmap Kernel.pi D_max langlc_ctypemaxdirectmemorysize maxinlinesize netty New native thread OOM outofmemoryraid card write policy String.intern String Poolstringtablesize sun.misc.Unsafe tomcatulimit-u WriteBack writethrough Auto Boxing Misuse HashMap timeout proudly powered by WordPress

GC-oriented Java programming

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.