Explain the common optimization schemes of Java code in detail

  • 2021-07-18 07:51:45
  • OfStack

First of all, good coding specifications are very important. In java program, most of the problems such as access speed and resource shortage are caused by irregular code.

Use scenarios of singletons

Singleton pattern has many advantages in reducing resource consumption and improving access speed, but not all scenarios are suitable for singleton.

Simply put, singletons are mainly applicable to the following three aspects:

In multithreaded scenario, the concurrent access of resources is controlled by thread synchronization. Multithreaded scenario, controlling data sharing, allowing communication between multiple unrelated processes or threads (controlled by accessing the same resource). Control the generation of instances, and only instantiate a single instance once to save resources;

Do not use static variables at will

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

Examples are as follows:


public class A {
  private static B b = new B();
}

The lifecycle of the static variable b is synchronized with that of the A class, that is, if the A class is not unloaded, the b object resides in memory until the program terminates.

Use Considerations for Creating Java Objects

According to the business usage scenario, try to avoid new objects in the loop.

This is because the system takes time to create objects, and it also takes time to manage and garbage collect those objects. Therefore, within the scope of control, we should try our best to reuse objects to the maximum extent, and it is best to replace objects with basic data types or arrays.

Considerations for using final modifiers

The class of the final modifier is non-derivable, that is, cannot be inherited. In the java core code, there are many classes modified by final, such as java. lang. String classes.

If a class is final, all methods of the class are final. The java compiler looks for opportunities to inline (inline) all final methods, depending on the specific compiler implementation. Doing so can improve the performance by 50% on average.

Examples are as follows:


class A {
  public void setSize (int size) {
    this.size = size;
  }
  private int size;
}
// setSize  Method becomes  final  Better performance 
class A {
  final public void setSize (int size) {
    this.size = size;
  }
  private int size;
}

Make the getter/setter method accessing the instance variable final: The simple getter/setter method should be set to final, which tells the compiler that this method will not be overloaded and can be changed to "inlined".

Specification for the use of local variables

The parameters passed when calling the method and the temporary variables created during the call are stored in the stack (Stack), which is fast; Other variables, such as static variables, instance variables, etc., are created in the heap (Heap), which is slower.

Handle the use places of packaging types and basic types well

Basic types: byte, short, int, long, float, double, char, boolean
Corresponding packaging types: Byte, Short, Int, Long, Float, Double, Character, Boolean

Base types and wrapper types can be converted to each other in use, but the memory areas they produce are completely different. The generation and processing of basic types are handled in the stack, the wrapper type is a reference type, and its object is to generate instances in the heap.

In the case of collection class objects, wrapper types are appropriate for processing with object needs, and primitive types are recommended for processing in other cases.

Use basic data types instead of objects

Examples are as follows:


String s1 = "hello";

This creates an "hello" string, and the character cache pool of JVM caches this string.


String s2 = new String("hello");

In this way, in addition to creating strings, the underlying String object referenced by s2 contains an char [] array, in which h, e, l, l and o are stored in turn.

Usage specification of synchronized

Synchronization requires a lot of system overhead, and may even cause deadlock. So try to avoid unnecessary synchronization control.

When the synchronize method is called, it directly locks the current object, and other threads cannot call other methods of the current object until the method is executed. A more flexible usage is to use code block synchronization instead of synchronization in methods.

Usage specification of finalize

Do not put resource cleanup in the finalize method, which is also rarely used.

Due to the heavy workload of GC, especially when reclaiming Young generation memory, the application will be suspended. If we choose to use finalize method to clean up resources, it will increase the burden of GC and deteriorate the program running efficiency.

Thread synchronization is not required, and HashMap and ArrayList should be used as much as possible

HashTable, Vector, etc. use synchronization mechanisms, resulting in a reduction.

Usage specification of HashMap

When you create a larger hashMap, you should use a constructor with parameters to create the object.

Examples are as follows:


public HashMap(int initialCapacity, float loadFactor);

hash expansion is a very performance-intensive thing. The default constructor creates an object with an initialCapacity of only 16 and an loadFactor of 0.75. It is best to accurately estimate the optimal size required. The same is true for Hashtable and Vectors.

Reduce repeated calculation of variables


for (int i = 0; i < list.size(); i++) {...}
//  Should read 
for (int i=0, l=list.size(); i < l; i++) {...}

Avoid creating objects unnecessarily


A a = new A();
if (i == 1) {
  list.add(a);
}
//  Should read 
if (i == 1) {
  A a = new A();
  list.add(a);
}

Usage specification of finally

In try-catch, used resources should be released to avoid resource leakage, which is best done in finally block. The code in finally will always execute regardless of whether the program executes abnormally, which can ensure the correct shutdown of resources.

Usage specification of StringBuffer

The parameterless constructor of StringBuffer creates an array of characters with a default of 16. In the process of using, if the array length exceeds 16, the memory should be reallocated, an array with larger capacity should be created, the original array should be copied, and the old array should be discarded.

In most cases, you can specify the size when you create the StringBuffer, avoiding automatic growth when the capacity is insufficient to improve performance.


StringBuffer sb= new StringBuffer(int capacity);

Explicitly freeing space allows gc to recycle objects

In most cases, objects referenced by local reference variables inside a method become garbage and are collected as the method ends. Therefore, there is no need to explicitly set the local reference variable to null in the program.

Examples are as follows:


void gcTest1() {
  Object obj = new Object();
   ... 
  obj = null;
}

As the execution of the method gcTest1 () completes, the scope of the local reference variable obj in the program ends, and there is no need to execute obj = null.

For example:


void gcTest2(){
  Object obj = new Object();
   ... 
  obj = null;
  // Time-consuming and memory-consuming operations 
   ... 
}

At this point, you need to free the space that is no longer used as early as possible, and execute obj = null to explicitly free the local reference variable obj.

Specification for the use of 2-dimensional arrays

2D data takes up about 10 times more memory space than 1D arrays.

split usage scenarios

Try to avoid using split. split uses regular expressions, which is inefficient. If it is called frequently, it will consume a lot of resources.

If you really need to call split frequently, it is better to use StringUtils. split (string, char) of apache to cache the results.

Usage specification of ArrayList and LinkedList

For linear and linked lists, the random query operation ArrayList is better than LinkedList, and LinkedList requires moving the pointer. The operation LinkedList to add deletion is better than ArrayList, and ArrayList requires moving data.

System. arraycopy () usage specification

Try to copy arrays using System. arraycopy (), which is much faster than copying arrays through loops.

Cache object

When caching frequently used objects, you can use arrays or containers such as HashMap to cache them. This approach requires self-management of these containers, which can lead to excessive cache use and performance degradation.

You can also use some third-party open source tools, such as EhCache and Oscache, which basically implement caching algorithms such as FIFO/FLU.

Try to avoid very large memory allocation

Some problems are not caused by insufficient heap memory, but by memory allocation failure. (gc defragments memory)

If all allocated blocks of memory must be contiguous, finding larger contiguous blocks becomes more and more difficult as the heap becomes full.

try/catch usage scenarios

Do not use the try/catch statement in the loop, but place try/catch on the outermost layer of the loop.


Related articles: