Today I’m going to share a dozen details of Java performance optimization.

In JAVA programs, most of the performance problems are not caused by the JAVA language, but by the program itself. Developing good coding habits is important and can significantly improve application performance.

1. Try to use singletons when appropriate

Using singletons can reduce the load burden, shorten the load time, and improve the load efficiency. However, it is not applicable to all places. Simply speaking, singletons are mainly applicable to the following three aspects:

1) Control the use of resources and control the concurrent access of resources through thread synchronization;

2) Control the generation of instances to achieve the purpose of saving resources;

3) Control data sharing to realize communication between multiple unrelated processes or threads without establishing direct correlation.

2. Avoid arbitrary use of static variables

When an object is defined as a static variable, GC usually does not reclaim the memory occupied by the object, as in:

At this point, the lifetime of the static variable B is synchronized with that of class A. If class A is not unloaded, the b object is resident in memory until the program terminates.

3. Try to avoid creating Java objects too often

Try to avoid in the method called often, cycle of the new object, because the system not only takes time to create the object, but also to spend time to garbage collection and processing of these objects, in we can control the range, maximum reuse objects, best can use object or array to replace basic data type.

4. Use final modifiers whenever possible

Classes with the final modifier are not derivable. In the JAVA core API, there are many examples of using final, ** such as JAVA, lang, and String. Specifying final for the String class prevents the user from overwriting the Length () method. ** Also, if a class is final, all methods of that class are final. The Java compiler looks for opportunities to inline all final methods (depending on the specific compiler implementation), which can improve performance by an average of 50%.

For example, making getters/setters that access variables in an instance “final” : simple getters/setters should be made final. This tells the compiler that this method is not loaded, so it can be changed to “inlined”.

5. Use local variables whenever possible

Parameters passed when calling a method and temporary variables created during the call are stored in the Stack, which is faster. Other variables, such as static variables, instance variables, etc., are created in the Heap and are slower.

6. Try to deal with the use of both the packaging type and the basic type

Although wrapper types and primitive types are interchangeable in use, the memory areas they generate are completely different. Primitive types are generated and processed in the stack, while wrapper types are objects and instances are generated in the heap. In the case of collection-class objects, processing that has object aspects needs applies to wrapper types, while other processing advocates primitive types.

Use synchronized sparingly, minimizing the use of synchronize

It is well known that synchronization is expensive and can even cause deadlocks, so try to avoid unnecessary synchronization control. When the synchronize method is called, it locks the current object so that no other thread can call any other methods on the current object until the method completes execution. Therefore, the synchronize method is kept to a minimum and method synchronization should be used instead of code block synchronization whenever possible.

8. Try not to use finalize methods

As a matter of fact, it is not a good choice to finalize the resource cleaning in Finalize method. Because of the heavy workload of GC, especially when the Young generation memory is recycled, the application program will be paused. Therefore, to finalize the resource cleaning in Finalize method will lead to a heavier burden of GC and a worse running efficiency of the program.

9. Use primitive data types instead of objects whenever possible

For example: String STR = “hello”; This creates a “hello” string, which is cached by the JVM’s character cache pool.

While: String STR = newString(” hello “); In addition to creating strings, the String referenced by STR also contains an array of char[], which holds h, E, L, L, and O.

10. Create a HashMap as reasonably as possible

Make full use of this constructor when creating a large hashMap:

public HashMap(int initialCapacity, float loadFactor);
Copy the code

By default, initialCapacity is only 16, and loadFactor is 0.75. You’d better be able to accurately estimate the optimal size you need. Vectors do the same thing.

11. Try to free resources in finally blocks

Resources used ina program should be released to avoid resource leaks, preferably ina finally block. Regardless of the result of program execution, the finally block is always executed to ensure that the resource is closed properly.

12. Try to determine the size of the StringBuffer

The constructor of a StringBuffer creates an array of characters of a default size (usually 16). In use, if this size is exceeded, memory is reallocated, a larger array is created, the original array is copied over, and the old array is discarded. In most cases, you can specify the size when creating a StringBuffer so that it doesn’t automatically grow when capacity is low, which improves performance.