Always Use a Finally Clause In Each Method to Cleanup
In Java, it is impossible to leave the try
or catch
blocks (even with a throw
or return
statement) without executing the finally block. If for any reason the instance variables cannot be cleaned, throw a catch-all exception that should cause the caller to discard its object reference to this now corrupt object.
If, for any reason the static variables cannot be cleaned, throw an InternalError
or equivalent that will ultimately result in restarting the now corrupt JVM.
Discard Objects That Throw Catch-All Exceptions
In many cases, these exceptions indicate that the internal state of the invoked object is corrupt, and that further invocations will also fail. Keep the object reference only if careful scrutiny of the exception shows it is benign, and further invocations on this object are likely to succeed.
Adopt a guilty unless proven innocent approach. For example, a SQLException
thrown from an Oracle JDBC invocation could represent one of thousands of error conditions in the JDBC driver, the network, or the database server. Some of these errors (for example, subclass SQLWarning
) are benign.
Some SQLExceptions
(for example, "ORA-3113: end of file on communication channel") definitely leave the JDBC object useless. Most SQLExceptions
do not clearly specify what state the JDBC object is left in.
The best approach is to enumerate the benign error codes that could occur frequently in your application and can definitely be retried, such as a unique key violation for user-supplied input data. If any other error code is found, discard the potentially corrupt object that threw the exception.
Discard all object references to the (potentially) corrupt object. Be sure to remove the corrupt object from all pools in order to prevent pools from being poisoned by corrupt objects. Do not invoke the corrupt object again - instantiate a brandnew object instead.
When you are sure that the corrupt objects have been discarded and that the catching object is not corrupt, throw a non catch-all exception so that the caller does not discard this object
Design Transactions Usage Correctly
Transactions should not span client requests because this can tie up shared resources indefinitely.
Requests generally should not span more than one transaction, because a failure in mid-request could leave some transactions committed and others rolled back. If this requires application-level compensation to recover, then availability or data integrity may be compromised.
Transactions generally should not span more than one database, because distributed transactions lock shared resources longer, and failure recovery may require simultaneous availability and coordination of multiple databases.
Applications that require a single client request (for example, a confirm checkout request in a shopping cart application) to ultimately affect several databases (for example, credit card, fulfillment, shopping cart, and customer history databases) should perform the first step with one database, and in the same transaction queue a message in the first database addressed to the second database.
The second database will perform the second step and queue the third step, and so on. This queued transaction chain will eventually complete automatically, or an administrator will see an undeliverable message and will have to manually compensate.
Put Business Logic In the Right Place
In general, you should not implement business logic in your client program. Instead, put validation and defaulting logic in your entity objects, and put client-callable methods in application modules, view objects, and view rows.
Working with application module methods allows the client program to encapsulate task-level custom code in a place that allows data-intensive operations to be done completely in the middle-tier without burdening the client.
Working with view object methods allows the client program to access the entire row collection for cross-row calculations and operations.
Working with view row methods allows the client program to operate on individual rows of data. There are three types of custom view row methods you may want to create:
- Accessor methods: The
oracle.jbo.Row
interface (which view rows implement) contains the methods getAttribute()
and setAttribute()
, but these methods are not typesafe. You can automatically generate custom typesafe accessors when you generate a custom view row class.
- Delegators to entity methods: By design, clients cannot directly access entity objects. If you want to expose an entity method to the client tier, you should create a delegator method in a view row.
- Entity-independent calculations: This is useful if the calculation uses attributes derived from multiple entity objects or from no entity objects.
Avoid Common Errors That Can Result In Memory Leaks
In Java, memory bugs often appear as performance problems, because memory leaks usually cause performance degradation. Because Java manages the memory automatically, developers do not control when and how garbage is collected. To avoid memory leaks, check your applications to make sure they:
- Release JDBC
ResultSet,
Statement
, or connection.
- Release failures here are usually in error conditions. Use a
finally
block to make sure these objects are released appropriately.
- Release instance or resource objects that are stored in static tables.
Perform clean up on serially reusable objects.
An example is appending error messages to a Vector
defined in a serially reusable object. The application never cleaned the Vector
before it was given to the next user. As the object was reused over and over again, error messages accumulated, causing a memory leak that was difficult to track down.
Avoid Creating Objects or Performing Operations That May Not Be Used
This mistake occurs most commonly in tracing or logging code that has a flag to turn the operation on or off during runtime.
Some of this code goes to great lengths creating and formatting output without checking the flag first, creating many objects that are never used when the flag is off. This mistake can be quite expensive, because tracing and logging usually involves many String
objects and operations to translate the message or even access to the database to retrieve the full text of the message.
Large numbers of debug or trace statements in the code make matters worse.
Replace Hashtable and Vector With Hashmap, ArrayList, or LinkedList If Possible
The Hashtable
and Vector
classes in Java are very powerful, because they provide rich functions. Unfortunately, they can also be easily misused. Since these classes are heavily synchronized even for read operations, they can present some challenging problems in performance tuning. Hence, the recommendations are:
- Use an Array Instead of an ArrayList If the Size Can Be Fixed
- Use an ArrayList or LinkedList To Hold a List of Objects In a Particular Sequence
- Use HashMap or TreeMap To Hold Associated Pairs of Objects
- Replace Hashtable, Vector, and Stack
- Avoid Using String As the Hash Key (If Using JDK Prior to 1.2.2)
Reuse Objects Instead of Creating New Ones If Possible
Object creation is an expensive operation in Java, with impact on both performance and memory consumption. The cost varies depending on the amount of initialization that needs to be performed when the object is to be created. Here are ways to minimize excess object creation and garbage collection overhead:
- Use a Pool to Share Resource Objects
- Use Lazy Initialization to Defer Creating the Object Until You Need It.
Use Stringbuffer Instead of String Concatenation
The String class is the most commonly used class in Java. Especially in Web applications, it is used extensively to generate and format HTML content.
String is designed to be immutable; in order to modify a String, you have to create a new String object.
Therefore, string concatenation can result in creating many intermediate String objects before the final String can be constructed. StringBuffer is the mutable companion class of String; it allows you to modify the String. Therefore, StringBuffer is generally more efficient than String when concatenation is needed.
This section also features the following practices:
- Use StringBuffer Instead of String Concatenation If You Repeatedly Append to a String In Multiple Statements
- Use Either String or StringBuffer If the Concatenation Is Within One Statement
- Use StringBuffer Instead of String Concatenation If You Know the Size of the String
Just providing points such way does not make any sense...
ReplyDeleteToday will explain all dont worry rishi
ReplyDeleteToday will explain all dont worry rishi
ReplyDelete