Java Performance Tuning of 55 details (Collector's Edition)

In Java programs, largely because of performance problems is not the Java language, but the program itself. Develop good coding practice is very important, can significantly improve the performance of the program.

1, as far as possible in the case of a suitable embodiment with a single

Singleton can reduce the burden of load, reduce the time to load and improve the efficiency of the load, but not all places are suitable for a single case, in simple terms, a single case mainly applies to the following three aspects:

First, control the use of resources by thread synchronization to control concurrent access to resources;

Second, control generates instance, in order to save resource;

Third, control data sharing, under conditions not directly related to the establishment, so that communication between multiple unrelated processes or threads.

2, try to avoid using static random variable

When an object is defined as a static variable is referenced, then the GC does not reclaim the object is usually occupied by memory, such as

At this static variable b life cycle synchronized with the Class A, Class A if not uninstall, then b objects of permanent memory, until the program is terminated.

3, try to avoid too much too often to create Java objects

Try to avoid frequent method calls, circulating new objects, due to the system not only takes time to create objects, but also to spend time on these objects for garbage collection and disposal, within the range that we can control, maximize reuse of objects , the best use an array of basic data types or objects instead.

4, try to use the final modifier

With the final modifier class is not derived. In the core JAVA API, there are many examples of the final application, e.g. java, lang, String, prevents the user specified final covering length () method of class String. Further, if a class is final, then all such methods are final. java compiler will look for opportunities to inline (inline) all of the final method (which the compiler and the specific implementation-dependent), a move that can improve the performance by an average of 50%.

Such as: let within the instance variable access getter / setter methods become "final:

Simple getter / setter methods should be set to the final, which will tell the compiler that this method will not be overloaded, it can become "inlined", example:

5, to make use of local variables

Delivery method call parameters and temporary variables created in the call are stored in the stack (Stack), the faster; other variables, such as static variables, instance variables are created in the heap (Heap), slow .

6, try to deal with both the packaging and the type of basic types of use of premises

Although the basic types and the type of packaging during use can be interchangeable, but they both memory area is generated completely different basic types of data processing are generated and processed in the stack, a package type object in the heap generating instance. In the collection class object has an object type of process suitable for packaging need, other processes advocate the use of basic types.

7, the synchronized caution, a method to minimize synchronize

All know, is synchronized to a lot of overhead expense, and may even cause a deadlock, so try to avoid unnecessary synchronization control. When synchronize method is called, it will direct the current object lock, other threads can not call other methods of the current object before executing the method. Therefore, to minimize Synchronize method, and the method should be used instead of the sync block synchronization.

9, try not to use finalize method

In fact, the clean-up resources in finalize method is done very bad choice, GC due to the large amount of work, especially when recycled Young generation of memory, the Metropolitan cause the application to be suspended, so again choose to use finalize methods of resource clean-up will lead to a greater burden on GC, process efficiency worse.

10, to make use of the basic data types in place of object

Above this way will create a "hello" string, and JVM character string buffer pool will be cached;

At this time, in addition to the program to create a string, String str underlying objects referenced further comprises a char [] array, the char [] array are sequentially stored for h, e, l, l, o

11, multi-threading thread-safe did not occur under the premise should use HashMap, ArrayList

HashTable, Vector, etc. using the synchronous mechanism, reducing the performance.

12, try to create reasonable HashMap

When you want to create a relatively large hashMap, take advantage of this constructor

Avoid HashMap conducted several hash reconstruction, expansion is a very performance-consuming thing, in default of initialCapacity only 16, but loadFactor 0.75, how much capacity, you'd better be able to accurately estimate what you need the best size, same Hashtable, Vectors is the same reason.

13, to minimize duplication of the calculation variables

Such as:

It should read:

And in the loop should avoid the use of complex expressions, in a loop, the loop condition will be repeated computing faster, without the use of complex expressions, the value of the same cycling conditions, the program will run.

14, try to avoid unnecessary creation

Such as:

It should read:

15, as far as possible the release of resources in the finally block

Used in the program to resources should be released, to avoid resource leaks, which is best done in a finally block. Regardless of the outcome of program execution, finally block will always be performed to ensure proper shutdown of resources.

16, instead of shifting to make use of 'a / b' operation

"/" Is a high cost of operation, shift operation will be faster and more efficient

Such as:

It should read:

However, note that using a shift should add comments, because the shift operation is not intuitive and more difficult to understand.

17, instead of shifting to make use of 'a * b' operation

Likewise, for the '*' operator, using the operation of the shift will be faster and more efficient

Such as:

It should read:

18, as far as possible to determine the capacity of StringBuffer

StringBuffer constructor creates a default size (usually 16) of an array of characters. In use, if you exceed this size, it will re-allocate memory, creating a larger array and copy over the original array, then discard the old array. In most cases, you can specify when you create StringBuffer size, thus avoiding the automatic increase in capacity is not enough time to improve performance.

Such as:

19, as early as possible the release of useless object references

Most of the time, the local method reference object variables referenced with the end of the method will become garbage, therefore, most of the time without having to program locally, reference variables explicitly set to null.

E.g:

Java code

Above this there is no need, as the method of implementation of the completion test (), the program obj reference variable scoping is over. But if it is changed to the following:

Java code

This time it is necessary to assign obj is null, we can release the reference to the Object object as soon as possible.

20, try to avoid using two-dimensional array

二维数据占用的内存空间比一维数组多得多,大概10倍以上。

21、尽量避免使用split

除非是必须的,否则应该避免使用split,split由于支持正则表达式,所以效率比较低,如果是频繁的几十,几百万的调用将会耗费大量资源,如果确实需要频繁的调用split,可以考虑使用apache的StringUtils.split(string,char),频繁split的可以缓存结果。

22、ArrayList & LinkedList

一个是线性表,一个是链表,一句话,随机查询尽量使用ArrayList,ArrayList优于LinkedList,LinkedList还要移动指针,添加删除的操作LinkedList优于ArrayList,ArrayList还要移动数据,不过这是理论性分析,事实未必如此,重要的是理解好2者得数据结构,对症下药。

23、尽量使用System.arraycopy ()代替通过来循环复制数组

System.arraycopy() 要比通过循环来复制数组快的多。

24、尽量缓存经常使用的对象

尽可能将经常使用的对象进行缓存,可以使用数组,或HashMap的容器来进行缓存,但这种方式可能导致系统占用过多的缓存,性能下降,推荐可以使用一些第三方的开源工具,如EhCache,Oscache进行缓存,他们基本都实现了FIFO/FLU等缓存算法。

25、尽量避免非常大的内存分配

有时候问题不是由当时的堆状态造成的,而是因为分配失败造成的。分配的内存块都必须是连续的,而随着堆越来越满,找到较大的连续块越来越困难。

26、慎用异常

当创建一个异常时,需要收集一个栈跟踪(stack track),这个栈跟踪用于描述异常是在何处创建的。构建这些栈跟踪时需要为运行时栈做一份快照,正是这一部分开销很大。当需要创建一个 Exception 时,JVM 不得不说:先别动,我想就您现在的样子存一份快照,所以暂时停止入栈和出栈操作。栈跟踪不只包含运行时栈中的一两个元素,而是包含这个栈中的每一个元素。

如果您创建一个 Exception ,就得付出代价,好在捕获异常开销不大,因此可以使用 try-catch 将核心内容包起来。从技术上讲,你甚至可以随意地抛出异常,而不用花费很大的代价。招致性能损失的并不是 throw 操作——尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。真正要花代价的是创建异常,幸运的是,好的编程习惯已教会我们,不应该不管三七二十一就抛出异常。异常是为异常的情况而设计的,使用时也应该牢记这一原则。

27、尽量重用对象

特别是String对象的使用中,出现字符串连接情况时应使用StringBuffer代替,由于系统不仅要花时间生成对象,以后可能还需要花时间对这些对象进行垃圾回收和处理。因此生成过多的对象将会给程序的性能带来很大的影响。

28、不要重复初始化变量

默认情况下,调用类的构造函数时,java会把变量初始化成确定的值,所有的对象被设置成null,整数变量设置成0,float和double变量设置成0.0,逻辑值设置成false。当一个类从另一个类派生时,这一点尤其应该注意,因为用new关键字创建一个对象时,构造函数链中的所有构造函数都会被自动调用。

这里有个注意,给成员变量设置初始值但需要调用其他方法的时候,最好放在一个方法。比如initXXX()中,因为直接调用某方法赋值可能会因为类尚未初始化而抛空指针异常,如:public int state = this.getState()。

29、在java+Oracle的应用系统开发中,java中内嵌的SQL语言应尽量使用大写形式,以减少Oracle解析器的解析负担。

30、在java编程过程中,进行数据库连接,I/O流操作,在使用完毕后,及时关闭以释放资源。因为对这些大对象的操作会造成系统大的开销。

31、保证过期的对象的及时回收具有重要意义

过分的创建对象会消耗系统的大量内存,严重时,会导致内存泄漏,因此,保证过期的对象的及时回收具有重要意义。JVM的GC并非十分智能,因此建议在对象使用完毕后,手动设置成null。

32、在使用同步机制时,应尽量使用方法同步代替代码块同步。

33、不要在循环中使用Try/Catch语句,应把Try/Catch放在循环最外层

Error是获取系统错误的类,或者说是虚拟机错误的类。不是所有的错误Exception都能获取到的,虚拟机报错Exception就获取不到,必须用Error获取。

34、通过StringBuffer的构造函数来设定它的初始化容量,可以明显提升性能

StringBuffer的默认容量为16,当StringBuffer的容量达到最大容量时,它会将自身容量增加到当前的2倍+2,也就是2*n+2。无论何时,只要StringBuffer到达它的最大容量,它就不得不创建一个新的对象数组,然后复制旧的对象数组,这会浪费很多时间。所以给StringBuffer设置一个合理的初始化容量值,是很有必要的!

35、合理使用java.util.Vector

Vector与StringBuffer类似,每次扩展容量时,所有现有元素都要赋值到新的存储空间中。Vector的默认存储能力为10个元素,扩容加倍。

vector.add(index,obj) 这个方法可以将元素obj插入到index位置,但index以及之后的元素依次都要向下移动一个位置(将其索引加 1)。 除非必要,否则对性能不利。同样规则适用于remove(int index)方法,移除此向量中指定位置的元素。将所有后续元素左移(将其索引减 1)。返回此向量中移除的元素。所以删除vector最后一个元素要比删除第1个元素开销低很多。删除所有元素最好用removeAllElements()方法。

如果要删除vector里的一个元素可以使用 vector.remove(obj);而不必自己检索元素位置,再删除,如:

int index = indexOf(obj);

vector.remove(index)。

38、不用new关键字创建对象的实例

用new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用它的clone()方法。clone()方法不会调用任何类构造函数。

下面是Factory模式的一个典型实现:

改进后的代码使用clone()方法:

39、不要将数组声明为:public static final

40、HaspMap的遍历

利用散列值取出相应的Entry做比较得到结果,取得entry的值之后直接取key和value。

41、array(数组)和ArrayList的使用

array 数组效率最高,但容量固定,无法动态改变,ArrayList容量可以动态增长,但牺牲了效率。

42、单线程应尽量使用 HashMap, ArrayList

除非必要,否则不推荐使用HashTable,Vector,它们使用了同步机制,而降低了性能。

43、StringBuffer,StringBuilder的区别在于

java.lang.StringBuffer 线程安全的可变字符序列。一个类似于String的字符串缓冲区,但不能修改。StringBuilder与该类相比,通常应该优先使用StringBuilder类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。

为了获得更好的性能,在构造StringBuffer或StringBuilder时应尽量指定她的容量。当然如果不超过16个字符时就不用了。 相同情况下,使用StringBuilder比使用StringBuffer仅能获得10%~15%的性能提升,但却要冒多线程不安全的风险。综合考虑还是建议使用StringBuffer。

44、尽量使用基本数据类型代替对象。

45、使用具体类比使用接口效率高,但结构弹性降低了,但现代IDE都可以解决这个问题。

46、考虑使用静态方法

如果你没有必要去访问对象的外部,那么就使你的方法成为静态方法。它会被更快地调用,因为它不需要一个虚拟函数导向表。这同时也是一个很好的实践,因为它告诉你如何区分方法的性质,调用这个方法不会改变对象的状态。

47、应尽可能避免使用内在的GET,SET方法。

48、避免枚举,浮点数的使用。

以下举几个实用优化的例子:

49、避免在循环条件中使用复杂表达式

在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。例子:

更正:

50、为'Vectors' 和 'Hashtables'定义初始大小

JVM为Vector扩充大小的时候需要重新创建一个更大的数组,将原原先数组中的内容复制过来,最后,原先的数组再被回收。可见Vector容量的扩大是一个颇费时间的事。

通常,默认的10个元素大小是不够的。你最好能准确的估计你所需要的最佳大小。例子:

更正:

自己设定初始大小。

51、在finally块中关闭Stream

程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。

52、使用'System.arraycopy ()'代替通过来循环复制数组

例子:

更正:

53、让访问实例内变量的getter/setter方法变成”final”

简单的getter/setter方法应该被置成final,这会告诉编译器,这个方法不会被重载,所以,可以变成”inlined”,例子:

更正:

54、对于常量字符串,用'String' 代替 'StringBuffer'

常量字符串并不需要动态改变长度。

例子:

更正:把StringBuffer换成String,如果确定这个String不会再变的话,这将会减少运行开销提高性能。

55、在字符串相加的时候,使用 ' ' 代替 " ",如果该字符串只有一个字符的话

例子:

更正:

将一个字符的字符串替换成' '

以上仅是Java方面编程时的性能优化,性能优化大部分都是在时间、效率、代码结构层次等方面的权衡,各有利弊,不要把上面内容当成教条,或许有些对我们实际工作适用,有些不适用,还望根据实际工作场景进行取舍,活学活用,变通为宜。

来源:https://yq.aliyun.com/articles/662001   、  微信公众号 :jave后端技术  必会的55个Java性能优化细节!一网打尽! 

Guess you like

Origin www.cnblogs.com/Small-sunshine/p/10962423.html