I. General
The general topic is suitable for most Java applications.
1.1 create a class instance without the New Keyword
When you create an instance with the New Keyword, all constructors in the constructor chain are automatically called. But if an object implements the cloneable interface, we can call its clone () method. The clone () method does not call any class constructor.
When using design pattern, it is very easy to use the clone () method to create a new object instance if you create an object in factory mode. For example, the following is a typical Implementation of the factory mode:
Public static credit getnewcredit (){
Return new credit ();
}
The improved code uses the clone () method as follows:
Private Static credit basecredit = new credit ();
Public static credit getnewcredit (){
Return (credit) basecredit. Clone ();
}
The above idea is also useful for Array Processing.
1.2 use non-blocking I/O
Earlier JDK versions do not support non-blocking I/O
API. To avoid I/O congestion, some applications use the method of creating a large number of threads (in good cases, a buffer pool is used ). This technology can be seen in many applications that must support concurrent I/O streams.
To, such as web servers, quotations, and auction applications. However, creating a Java thread requires considerable overhead.
JDK 1.4 introduces a non-blocking I/O Library (Java. NiO ). If an application requires JDK of an earlier version, there is a software package that supports non-blocking I/O.
See adjust Java I/O performance on Sun China website.
1.3 usage exceptions with caution
Exceptions are detrimental to performance. To throw an exception, you must first create a new object. The constructor of the throwable interface calls the local code named fillinstacktrace ().
(Native) method. The fillinstacktrace () method checks the stack and collects Call trace information. As long as an exception is thrown, the VM must adjust the call stack.
A new object is created.
Exceptions can only be used for error handling and should not be used to control program processes.
1.4 do not reinitialize the variable
By default, when you call a class constructor,
Java initializes the variable to a definite value: all objects are set to null, integer variables (byte, short, Int, long) are set to 0, float, and
Set the double variable to 0.0 and the logical value to false. This is especially important when a class is derived from another class, because the function chain is constructed when an object is created using the new keyword.
All constructors in are automatically called.
1.5 specify the final modifier of the class as much as possible
Classes with final modifiers cannot be derived. There are many examples of final applications in the Java core API, such as Java. Lang. String. Specifying final for the string class prevents people from overwriting the length () method.
In addition, if you specify a class as final, all the methods of this class are final. The Java compiler will look for opportunities to inline (Inline) All final methods (this is related to the specific compiler implementation ). This can increase the performance by an average of 50%.
1.6 use local variables whenever possible
The parameters passed during method calling and the temporary variables created in the call are saved in the stack, which is faster. Other variables, such as static variables and instance variables, are created in heap, which is slow. In addition, local variables may be further optimized depending on the specific compiler/JVM. See use stack variables whenever possible.
1.7 multiplication and division
Consider the following code:
For (val = 0; Val <100000; Val + = 5) {alterx = Val * 8; myresult = Val * 2 ;}
Replacing multiplication with shift operations can greatly improve performance. The modified code is as follows:
For (val = 0; Val <100000; Val + = 5) {alterx = Val <3; myresult = Val <1 ;}
The modified code does not multiply by 8. Instead, it uses the equivalent three-bit left shift operation, and one-bit left shift operation is equivalent to multiplying 2. Correspondingly, the one-bit operation on the right is equivalent to dividing by 2. It is worth mentioning that, although the shift operation is fast, it may make the code more difficult to understand, so it is best to add some comments.
Ii. J2EE
The performance improvement techniques described earlier are suitable for most Java applications. The questions to be discussed later are suitable for JSP, EJB, or JDBC applications.
2.1 use a buffer flag
Some application servers have added the JSP-oriented buffer tag function. For example, the WebLogic Server of BEA supports this function from version 6.0.
The symphony project also supports this function. The JSP buffer tag can buffer both page fragments and the whole page. When the JSP page is executed, if the target segment is already in the buffer
The code that generates the snippet does not need to be executed. Page-level buffer captures requests to a specified URL and caches the entire result page. This feature is extremely useful for shopping baskets, directories, and portals. Pair
In such applications, page-level buffering can save the results of page execution for subsequent requests.
For pages with complex code logic, the performance improvement by using the buffer tag is obvious; otherwise, the performance may be slightly inferior.
See improving the performance and stability of JSP applications with buffer technology.
2.2 always access the Entity Bean through the session bean
Direct access to the Entity Bean is not conducive to performance. When the client program remotely accesses the object bean, each get method is a remote call. The Session Bean accessing the object bean is local. It organizes all the data into a structure and returns its value.
The access to the Entity Bean encapsulated by the session bean can improve the transaction management, because the Session Bean will be submitted only when it reaches the transaction boundary. Each direct call to the get method generates a transaction, and the container will execute a "load-read" operation after each Entity Bean transaction.
In some cases, using the Entity Bean will lead to poor program performance. If the only purpose of the entity bean is to extract and update data, you can use JDBC to access the database within the session bean to achieve better performance.
2.3 select an appropriate reference mechanism
In a typical JSP application system, the page header and footer are often extracted, and the page header and footer are introduced as needed. Currently, there are two main methods to introduce external resources in JSP pages: include commands and include actions.
Include command: for example, <% @ include file = "copyright.html"
%>. This command introduces specified resources during compilation. Before compilation, the page with the include command and the specified resource are merged into a file. The referenced external resources are determined during compilation,
It is more efficient than determining resources during running.
Include action: for example, <JSP: Include page = "Copyright. jsp"
/>. This action introduces the result generated after the specified page is executed. Because it is completed at runtime, the control of output results is more flexible. However, only when the referenced content changes frequently or
The include action is cost-effective only when the referenced page cannot be determined before the page request appears.
2.4 set the read-only attribute in the deployment descriptor
The deployment descriptor of the Entity Bean allows you to set all get methods to "read-only ". When a transaction unit only includes read operations, setting the read-only attribute improves performance because the container does not have to perform storage operations.
2.5 Buffer access to EJB home
EJB
The home interface is obtained through the JNDI name search. This operation requires considerable overhead. It is best to put the JNDI search in the init () method of servlet. If the application is frequently used
It is recommended to create an ejbhomecache class when EJB access occurs. The ejbhomecache class is generally implemented as Singleton.
2.6 implement Local interface for EJB
The Local interface is newly added to the EJB 2.0 specification, which allows the bean to avoid the overhead of remote calls. Consider the following code.
Paybeanhome home = (paybeanhome)
Javax. RMI. portableremoteobject. Narrow
(CTX. Lookup ("paybeanhome"), paybeanhome. Class );
Paybean bean = (paybean)
Javax. RMI. portableremoteobject. Narrow
(Home. Create (), paybean. Class );
The first statement indicates that we are looking for the home interface of bean. This query is performed through JNDI, which is an Rmi call. Then, we locate the remote object and return the proxy reference, which is also
RMI call. The second statement demonstrates how to create an instance. It involves the stub program that creates an IIOP request and transmits the request over the network. It is also an Rmi call.
To implement the local interface, we must make the following changes:
Methods cannot throw a java. RMI. RemoteException, including exceptions derived from RemoteException, such
Transactionrequiredexception, transactionrolledbackexception, and
Nosuchobjectexception. EJB provides equivalent local exceptions, such as transactionrequiredlocalexception,
Transactionrolledbacklocalexception and nosuchobjectlocalexception.
All data and return values are passed through reference instead of values.
The Local interface must be used on the machine where the EJB is deployed. In short, the customer program and the components that provide services must run on the same JVM.
If bean implements a local interface, its reference cannot be serialized.
For more information, see use local references to improve EJB access efficiency.
2.7 generate a primary key
There are many ways to generate a primary key in EJB. The following describes several common methods and their features.
Use the database's built-in identity mechanism (SQL Server's identity or Oracle's sequence ). The disadvantage of this method is that EJB has poor portability.
The Entity Bean automatically calculates the primary key value (for example, incremental operations ). Its disadvantage is that transactions must be serializable and slow.
Use NTP and other clock services. This requires that you have local code for a specific platform to fix the bean to a specific OS. In addition, it also leads to the possibility that two primary keys are generated within the same millisecond on a multi-CPU server.
Use Microsoft's idea to create a guid in bean. However, if you do not turn to JNI, Java cannot determine the MAC address of the NIC; if you use JNI, the program depends on a specific OS.
There are several other methods, but these methods also have their own limitations. There seems to be only one ideal answer: combining RMI and JNDI. Bind the remote RMI object to the JNDI tree through RMI registration. The customer program searches through JNDI. The following is an example:
Public class keygenerator extends unicastremoteobject implements remote {
Private Static long keyValue = system. currenttimemillis ();
Public static synchronized long getkey () throws RemoteException {return keyValue ++ ;}
2.8 clear unnecessary sessions in time
To clear sessions that are no longer active, many application servers have the default session timeout time, usually 30 minutes. When the application server needs to save more sessions, if the memory capacity is insufficient, the operating system will
When the data is transferred to the disk by memory, the application server may also use the most recently
Used) the algorithm dumps some inactive sessions to the disk, and may even throw an "out-of-memory" exception. In large-scale systems, serialized sessions are expensive. When the session is no longer needed, it should be timely
Call httpsession. invalidate () to clear the session. The httpsession. invalidate () method can be called on the exit page of the application.
.
2.9 close useless sessions on the JSP page
For pages that do not need to track session Status, disabling automatically created sessions can save some resources. Use the following page command:
<% @ Page session = "false" %>
2.10 Servlet and memory usage
Many developers store a large amount of information in user sessions at will. In some cases, objects stored in sessions are not recycled in a timely manner by the garbage collection mechanism. In terms of performance, the typical symptom is that the user feels the system week
But it cannot be attributed to any specific component. If you monitor the heap space of the JVM, the memory usage may fluctuate abnormally.
There are two main ways to solve such memory problems. The first method is to implement the httpsessionbindinglistener interface in all beans with the function scope of the session. In this way, the bean resources can be explicitly released as long as the valueunbound () method is implemented.
Another method is to invalidate the session as soon as possible. Most application servers have the option of setting the session expiration time. In addition, sessions can also be called programmatically.
Setmaxinactiveinterval () method, which is used to set the maximum interval of customer requests allowed by the servlet container before the session is voided, in seconds.
2.11 HTTP keep-alive
The keep-alive function keeps the client-to-server connection valid. When a subsequent request is sent to the server, the keep-alive function avoids or reestablishes a connection. Market
Most Web servers, including iPlanet, IIS, and Apache, Support HTTP
Keep-alive. This feature is usually useful for websites that provide static content. However, for websites with heavy load, there is another problem: although you keep the connected
But it also affects performance because resources that can be released are still occupied during the pause process. When the Web server and Application Server run on the same machine, keep-
The impact of the alive function on resource utilization is particularly prominent.
2.12 JDBC and Unicode
You must have understood some measures to improve the performance when using JDBC, for example, using the connection pool, correctly selecting stored procedures and directly executing SQL statements, deleting redundant columns from the result set, and pre-compiling SQL statements.
In addition to these obvious options, another good choice for improving performance may be to save all the character data as Unicode (code page 13488 ). Java uses Unicode
To process all the data. Therefore, the database driver does not have to execute the conversion process. But remember: if this method is used, the database will become larger, because each UNICODE character requires 2 bytes.
Storage space. In addition, if other non-Unicode programs access the database, performance problems still occur, because the database driver must still execute the conversion process.
2.13 JDBC and I/O
If an application needs to access a large dataset, consider using block extraction. By default, JDBC extracts 32 rows of data each time. For example, suppose we want to traverse
For a 5000-row record set, JDBC must call the database 157 times to extract all data. If the block size is changed to 512, the number of database calls will be reduced to 10.
In some cases, this technology is ineffective. For example, if you use a scrollable record set or specify for update in the query, the block operation method is no longer valid.
2.14 Memory Database
Many applications need to store a considerable amount of data in session objects in units of users, typical applications such as shopping baskets and directories. Because this type of data can be organized in the form of rows/columns, many applications have created
A large vector or hashmap. Saving this type of data in a session greatly limits the scalability of the application, because the memory occupied by the server must at least reach the memory occupied by each session multiplied by and
The maximum number of sending users. This not only makes the server expensive, but also increases the time interval for garbage collection to an intolerable level.
Some people transfer the shopping basket/directory function to the number
The database layer improves scalability to some extent. However, putting this feature on the database layer also has problems, and the root cause of the problem is related to the architecture of most relational database systems. For relational databases
One of the important principles of running is to ensure that all write operations are stable and reliable. Therefore, all performance problems are related to the ability of physically writing data to a disk. Relational databases are designed to reduce I/O operations.
This is not for read operations, but the main way to achieve this goal is to execute a complex set of algorithms that implement the buffer mechanism. This is the main reason why the performance bottleneck of No. 1 database layer is always the CPU.
A solution to replace traditional relational databases is to use a database running in the memory (in-memory
Database), such as TimesTen. The starting point of the memory database is to allow temporary data writing, but the data does not need to be permanently saved to the disk, and all operations are performed in the memory. This
Example: memory databases do not need complex algorithms to reduce I/O operations, and can adopt a simple locking mechanism, so the speed is very fast.
Iii. Gui
This section is suitable for graphical user interface applications (Applet and common applications) and uses AWT or swing.
3.1 Use jar to compress class files
Java file (JAR file) is a file compressed according to the javajan standard. It is the main method and recommended method for publishing the javajan component. Jar files help reduce file bodies
Product to shorten the download time. For example, it helps the applet increase the startup speed. A jar file can contain one or more related beans and support files, such as bitwise, sound, and HTML.
And other resources.
To specify the JAR file in the HTML/JSP file, you only need to add the archive = "name. Jar" declaration to the applet tag.
See "using file files to increase the loading speed of Applet".
3.2 prompt applet Loading Process
Have you ever seen a website that uses an applet and noticed that there is a placeholder in the place where the applet should be run? What happens when the applet is downloaded for a long time? The biggest possibility is that the user turns around and leaves. In this case, displaying the information that an applet is downloading will undoubtedly help to encourage users to continue waiting.
Let's take a look at a specific implementation method. First, create a small applet, which is responsible for downloading the official Applet in the background:
Import java. Applet. Applet;
Import java. Applet. appletstub;
Import java. AWT. label;
Import java. AWT. graphics;
Import java. AWT. gridlayout;
Public class preloader extends applet implements runnable, appletstub {
String largeappletname;
Label label;
Public void Init (){
// The formal applet to be loaded
Largeappletname = getparameter ("applet ");
// "Please wait" prompt
Label = new label ("Please wait..." + largeappletname );
Add (Label );
}
Public void run (){
Try {
// Obtain the class of the applet to be loaded
Class largeappletclass = Class. forname (largeappletname );
// Create the instance for which the applet is to be loaded
Applet largeapplet = (applet) largeappletclass. newinstance ();
// Set the stub program of the Applet
Largeapplet. setstub (this );
// Cancel the "Please wait" Message
Remove (Label );
// Set the Layout
Setlayout (New gridlayout (1, 0 ));
Add (largeapplet );
// Display the official Applet
Largeapplet. INIT ();
Largeapplet. Start ();
}
Catch (exception ex ){
// Display the error message
Label. settext ("the specified applet cannot be loaded ");
}
// Refresh the screen
Validate ();
}
Public void appletresize (INT width, int height ){
// Transfer the appletresize call from the stub program to the Applet
Resize (width, height );
}
}
The compiled code is less than 2 kb, And the download speed is fast. There are several points worth noting in the code. First, preloader implements the appletstub interface. Generally, the Applet
Determine your own codebase. In this example, we must call setstub () to tell the applet where to extract this information. Another thing worth noting is that,
The appletstub Interface contains many methods that are the same as the Applet Class, except for the appletresize () method. Here we use the appletresize () method
The call is passed to the resize () method.
3.3 pre-mount it before drawing the image
The imageobserver interface can be used to receive prompt information about image loading. The imageobserver interface has only one imageupdate () method. You can use a repaint () operation to draw images on the screen. An example is provided below.
Public Boolean imageupdate (image IMG, int flags, int X, int y, int W, int h ){
If (flags & allbits )! = 0 {
Repaint ();
}
Else if (flags & (error | abort ))! = 0 ){
Error = true;
// The file is not found. Consider displaying a placeholder
Repaint ();
}
Return (flags & (allbits | error | abort) = 0;
}
The imageupdate () method is called When graphical information is available. If further updates are required, the method returns true. If required information is obtained, the method returns false.
3.4 overwrite the update Method
The default action of the update () method is to clear the screen and then call the paint () method. If you use the default Update () method, applications that frequently use graphs may flash. To avoid the screen cleanup operation before the paint () call, override the update () method as follows:
Public void Update (Graphics g ){
Paint (g );
}
The ideal solution is to overwrite Update () and only redraw the area on the screen that has changed, as shown below:
Public void Update (Graphics g ){
G. cliprect (X, Y, W, H );
Paint (g );
}
3.5 delayed re-painting
For graphic user interface applications, the main reason for poor performance can often be attributed to the inefficiency of the screen. When you change the window size or scroll a window, this is usually obvious.
Observed. Operations such as changing the window size or scrolling the screen cause a large number of screen re-painting events to be generated quickly, or even exceed the execution speed of the relevant code. The best way to deal with this problem is to ignore all "late"
.
It is recommended to introduce a time difference of several milliseconds here, that is, if we receive another re-painting event immediately, we can stop processing the current event and then process the last re-painting event received; otherwise, we continue the current re-painting process.
If an event needs to start a time-consuming task, separating a working thread is a good way to handle it. Otherwise, some parts may be frozen because only one event can be processed at a time. The following provides a simple example of event processing, but after expansion, it can be used to control the working thread.
Public static void runonce (string ID, final long milliseconds ){
Synchronized (e_queue) {// e_queue: a collection of all events
If (! E_queue.containskey (ID )){
E_queue.put (token, new lastone ());
}
}
Final lastone = (lastone) e_queue.get (token );
Final long time = system. currenttimemillis (); // obtain the current time
Lastone. Time = time;
(New thread () {public void run (){
If (milliseconds> 0 ){
Try {thread. Sleep (milliseconds);} // pause the thread
Catch (exception ex ){}
}
Synchronized (lastone. Running) {// wait until the last event ends
If (lastone. Time! = Time) // only process the last event
Return;
}
}). Start ();
}
Private Static hashtable e_queue = new hashtable ();
Private Static class lastone {
Public long time = 0;
Public object running = new object ();
}
3.6 use dual-Buffer
The entire image is displayed immediately after the drawing is completed in the buffer area outside the screen. Because there are two buffers, the program can switch back and forth. In this way, we can use a low-priority thread to draw pictures, so that the program can use idle CPU time to execute other tasks. The following pseudocode snippets demonstrate this technology.
Graphics mygraphics;
Image myoffscreenimage = createimage (SIZE (). Width, size (). Height );
Graphics offscreengraphics = myoffscreenimage. getgraphics ();
Offscreengraphics. drawimage (IMG, 50, 50, this );
Mygraphics. drawimage (myoffscreenimage, 0, 0, this );
3.7 Use bufferedimage
Java JDK
1.2 A soft display device is used to make the text look similar on different platforms. To implement this function, Java must directly process the pixels that constitute the text. Because this technology requires a large amount of input in the memory
The row-bit replication operation, the early JDK used this technology in poor performance. The java standard proposed to solve this problem implements a new graphic type, namely bufferedimage.
The image described by the bufferedimage subclass has an accessible graphic data buffer. A bufferedimage contains a colormodel and a set of Raster Graphic Data. This class uses RGB (red, green, and blue) color models, but it can also process grayscale images. Its constructor is very simple, as shown below:
Public bufferedimage (INT width, int height, int imagetype)
Imagetype allows us to specify the types of images to buffer, such as 5-bit RGB, 8-bit RGB, and grayscale.
3.8 Use volatileimage
Many hardware platforms and their operating systems provide basic hardware acceleration support. For example, hardware acceleration generally provides the rectangle filling function, which is more efficient than using the CPU to complete the same task. By
Hardware acceleration separates a part of work and allows multiple workflows to run concurrently. This reduces the pressure on CPU and system bus and enables applications to run faster. Using volatileimage
To create a hardware-accelerated image and manage its content. Because it directly utilizes the capabilities of the lower-layer platform, the performance improvement mainly depends on the graphic adapter used by the system. Volatileimage
Content may be lost at any time, that is, it is "unstable )". Therefore, before using a graphic, it is best to check whether its content is lost. Volatileimage has two
Methods to check whether the content is lost:
Public abstract int validate (graphicsconfiguration GC );
Public Abstract Boolean contentslost ();
The Validate () method should be called each time the content is copied from the volatileimage object or written to the volatileimage object. The contentslost () method tells us whether the image content is lost since the last validate () call.
Although volatileimage is an abstract class, do not derive a subclass from it. Volatileimage should pass
Component. createvolatileimage () or
Graphicsconfiguration. createcompatiblevolatileimage () method.
3.9 Use Window blitting
During the scrolling operation, all visible content must be repainted, resulting in a large amount of unnecessary re-painting. Graphics subsystems of Many operating systems, including Win32
GDI, MacOS, and X/windows all support the window blitting technology. Window
Blitting technology directly moves the image to a new position in the screen buffer and only re-draws the new area. To use windows in a swing Application
The blitting technology is configured as follows:
Setscrollmode (INT mode );
In most applications, this technology can improve the rolling speed. In only one case, window blitting may result in lower performance, that is, the application performs rolling operations in the background. If the user is rolling an application, it is always on the frontend without worrying about any negative impact.