Monday, October 29, 2007

Google Tip: Use a Colon

Search engines have gotten so good and useful syntax for more specific results. here are top three most useful Google search modifiers that use a colon:


site:URL and search term. As in, site:www.pcmag.com "wireless router." Insiders point out that this modifier is even stronger if you drop the www. You can also drop the domain name entirely and search, for example, only .gov sites.


define:word. This brings up definitions, related phrases, and offers to translate the word.


filetype:file extension and search term. It may be obvious, but this lets you search for files with a certain extension, such as PPT for a PowerPoint presentation on your topic.

Wednesday, October 24, 2007

Insufficient memory problem with StringBuffer

Using string buffer without selecting the proper construction can lead to memory leak.

Lets have a look of the constructor of string buffer

Constructs a string buffer with no characters in it and an initial capacity of 16 characters.

public StringBuffer() {
super(16);
}

Suppose you are creating objects of type StringBuffer in a loop, no of objects may change depnding upon the input. Every time it will create object to store at least 16 characters, you may not need all the 16, in that case remaining space will be unused and cannout be allocated for other purpose.

At some point these unused memory location may lead to Out of memory problem.

Instead of that we can use another constructor

Constructs a string buffer with no characters in it and the specified initial capacity.

public StringBuffer(int capacity) {
super(capacity);
}

Java Class Loaders

Class loaders have always been the key component of the Java, loading classes into the JVM at runtime. Class loaders fetch classes into the JVM, so they constitute the first line of defense in the JVM Sandbox, filtering malicious code, guarding trusted libraries, and setting up protection domains.

Further, the J2EE architecture makes uses of the class loaders to the fullest. Almost every component of J2EE is the dynamically loaded by the application server.

In a JVM, each and every class is loaded by some instance of a java.lang.ClassLoader. The ClassLoader class is located in the java.lang package and developers are free to subclass it to add their own functionality to class loading.



JVM creates an instance of java.lang.Class for every data type loaded into memory. The instance of this java.lang.Class is also stored on heap like any other object. Every object in Java contains a reference to this Class object of its data type. The getClass() method can be used to obtain the associated Class object. The getClass() method is inherited from the java.lang.Object hence available in every class.

Lets see an example of Dynamic class loading

public class DynamicLoader
{
public static void main(String[] args) throws Exception
{
Class toRun = Class.forName(args[0]);
String[] newArgs = scrubArgs(args);
Method mainMethod = findMain(toRun);
mainMethod.invoke(null, new Object[] { newArgs });
}
private static String[] scrubArgs(String[] args)
{
String[] toReturn = new String[args.length-1];
for (int i=1; i<args.length; i++)
{
toReturn[i-1] = args[i].toLowerCase();
}
return toReturn;
}
private static Method findMain(Class clazz) throws Exception
{
Method[] methods = clazz.getMethods();
for (int i=0; i<methods.length; i++)
{
if (methods[i].getName().equals("main"))
return methods[i];
}
return null;
}
}

public class Echo
{
public static void main (String args[])
{
for (int i=0; i<args.length; i++)
{
System.out.println("Echo arg"+i+" = "+args[i]);
}
}
}

Running DynamicLoader

>java DynamicLoader ECHO One Two Three

And the output is

Echo arg0 = One

Echo arg1 = Two

Echo arg2 = Three

As you can see, DynamicLoader created an instance of the Echo class, and called its main method, all without having any direct reference to Echo itself. In O-O parlance, this means that DynamicLoader is completely decoupled from Echo; there are no explicit dependencies between these two classes.


Class.forName(). In most of these systems, the code to do the run-time loading comes through the method forName on the class java.lang.Class; its use is demonstrated in the DynamicLoader code, above. Class.forName attempts to load the class whose name is given in its only argument, and returns the Class instance representing that class. In the event that the Class could not be found, resolved, verified, or loaded, Class.forName throws one of several different Exceptions.



CLASS LOADER


Now that we know java.lang.Class, it’s easy to comprehend the class loader of Java, which is a type of java.lang.Classloader (or its sub types).
The purpose of a class loader is to load the byte codes in ".class" file, and build the java.lang.Class object corresponding to the loaded type on JVM heap memory.


The java.lang.Class object is used to create objects requested by the programs.








Java has hierarchy of class loaders linked in a chain of parent-child relationship. Every class loader in Java, except the bootstrap class loader, has a parent class loader. At top of the parent-child chain is the bootstrap class loader.


Most java programs have at least 3 class loaders active behind the scenes. They are as follows










Bootstrap or Primordial Class loader: Class loader is responsible for loading only the core Java API (e.g. classes files from rt.jar). Since the core classes are required to bootstrap any Java program the class loader is called bootstrap class loader. This is root of all the class loader hierarchy in a java application.

Extension Class loader: Class loader responsible for loading classes from the Java extension directory (i.e. classes or jars in jre/lib/ext of the java installation directory). This class loader is responsible for loading the "installed extensions". Bootstrap class loader is the parent of this class loader.

System class loader or Application class loader: Class loader responsible for loading classes from the java class path (i.e. class directories or jars present in CLASSPATH environment variable of the Operating System). Extension class loader is the parent of this class loader. This class loader is by default the parent of all the custom/user defined class loaders in a java application.


The class loader subsystem involves many other parts of the Java virtual machine and several classes from the java.lang library. For example, user-defined class loaders are regular Java objects whose class descends from java.lang.ClassLoader. The methods of class ClassLoader allow Java applications to access the virtual machine's class loading machinery. Also, for every type a Java virtual machine loads, it creates an instance of class java.lang.Class to represent that type. Like all objects, user-defined class loaders and instances of class Class reside on the heap. Data for loaded types resides in the method area.

This use of dynamic runtime loading is the heart of Java Application Servers like the Java2 Enterprise Edition reference implementation, Enterprise JavaBeans, and the Servlet Specification. In each one of these architectures, at the time the application server is compiled, it knows nothing about the code that will be attached to it.

Instead, it simply asks the user for a classname to load, loads the class, creates an instance of the class, and starts making method calls on that instance. (It does so either through Reflection, or by requiring that clients implement a particular interface or class, like GenericServlet in the Servlet spec, or EJBObject in the EJB spec.)


The class loader subsystem is responsible for more than just locating and importing the binary data for classes. It must also verify the correctness of imported classes, allocate and initialize memory for class variables, and assist in the resolution of symbolic references. These activities are performed in a strict order:
1.Loading: finding and importing the binary data for a type
2.Linking: performing verification, preparation, and (optionally) resolution
a. Verification: ensuring the correctness of the imported type
b. Preparation: allocating memory for class variables and
initializing the memory to default values
c. Resolution: transforming symbolic references from the type into direct
references.
3.Initialization: invoking Java code that initializes class variables to their
proper starting values.



Wednesday, October 17, 2007

Custom String Values for Enum

The default string value for java enum is its face value, or the element name. However, you can customize the string value by overriding toString() method. For example,
public enum MyType {
ONE {
public String toString() {
return "this is one";
}
},

TWO {
public String toString() {
return "this is two";
}
}
}
Running the following test code will produce this:

public class EnumTest {
public static void main(String[] args) {
System.out.println(MyType.ONE);
System.out.println(MyType.TWO);
}
}
-------------
this is one
this is two

Another interesting fact is, once you override toString() method, you in effect turn each element into an anonymous inner class. So after compiling the above enum class, you will see a long list of class files:
MyType.class
MyType$1.class
MyType$2.class

Java Enum and Its Superclass

All java enum implicitly extend from java.lang.Enum. Since java doesn't allow multiple inheritance, enum types can't have superclass. They can't even extend from java.lang.Enum, nor java.lang.Object. It also means enum A can't inherit or extend enum B.

For example, the following is an invalid enum declaration:


public enum MyNumENUM extends Object {
ONE, TWO
}

Compiler error:
MyNumENUM.java:3: '{' expectedpublic enum MyNumENUM extends Object { MyNumENUM.java:6: expected
2 errors

The correct form should be:

public enum MyNumENUM {
ONE, TWO
}




Faster Deep Copies of Java Objects ( Shallow Copy and Deep Copy )

Faster Deep Copies of Java Objects

The java.lang.Object root superclass defines a clone() method that will, assuming the subclass implements the java.lang.Cloneable interface, return a copy of the object. While Java classes are free to override this method to do more complex kinds of cloning, the default behavior of clone() is to return a shallow copy of the object. This means that the values of all of the origical object’s fields are copied to the fields of the new object.

A property of shallow copies is that fields that refer to other objects will point to the same objects in both the original and the clone. For fields that contain primitive or immutable values (int, String, float, etc…), there is little chance of this causing problems. For mutable objects, however, cloning can lead to unexpected results. Figure 1 shows an example.


--------------------------------------------------------------------------------

import java.util.Vector;
public class Example1 {
public static void main(String[] args) {
// Make a Vector
Vector original = new Vector();
// Make a StringBuffer and add it to the Vector
StringBuffer text = new StringBuffer(”The quick brown fox”);
original.addElement(text);
// Clone the vector and print out the contents
Vector clone = (Vector) original.clone();
System.out.println(”A. After cloning”);
printVectorContents(original, “original”);
printVectorContents(clone, “clone”);
System.out.println(“——————————————————–”);
System.out.println();
// Add another object (an Integer) to the clone and
// print out the contents
clone.addElement(new Integer(5));
System.out.println(”B. After adding an Integer to the clone”);
printVectorContents(original, “original”);
printVectorContents(clone, “clone”);
System.out.println(“——————————————————–”);
System.out.println();
// Change the StringBuffer contents
text.append(” jumps over the lazy dog.”);
System.out.println(”C. After modifying one of original’s elements”);
printVectorContents(original, “original”);
printVectorContents(clone, “clone”);
System.out.println(“——————————————————–”);
System.out.println();
}

public static void printVectorContents(Vector v, String name) {
System.out.println(” Contents of \”" + name + “\”:”);
// For each element in the vector, print out the index, the
// class of the element, and the element itself
for (int i = 0; i < v.size(); i++) {
Object element = v.elementAt(i);
System.out.println(” ” + i + ” (” +element.getClass().getName() + “): ” +element);
}
System.out.println();
}
}

--------------------------------------------------------------------------------


Figure 1. Modifying Vector contents after cloning
In this example we create a Vector and add a StringBuffer to it. Note that StringBuffer (unlike, for example, String is mutable — it’s contents can be changed after creation. Figure 2 shows the output of the example in Figure 1.


--------------------------------------------------------------------------------


> java Example1
A. After cloning

Contents of “original”:

0 (java.lang.StringBuffer): The quick brown fox
Contents of “clone”:

0 (java.lang.StringBuffer): The quick brown fox
——————————————————–


B. After adding an Integer to the clone

Contents of “original”:

0 (java.lang.StringBuffer): The quick brown fox
Contents of “clone”:

0 (java.lang.StringBuffer): The quick brown fox

1 (java.lang.Integer): 5
——————————————————–


C. After modifying one of original’s elements

Contents of “original”:

0 (java.lang.StringBuffer): The quick brown fox jumps over the lazy dog.
Contents of “clone”:

0 (java.lang.StringBuffer): The quick brown fox jumps over the lazy dog.

1 (java.lang.Integer): 5
——————————————————–

--------------------------------------------------------------------------------


Figure 2. Output from the example code in Figure 1
In the first block of output (”A”), we see that the clone operation was successful: The original vector and the clone have the same size (1), content types, and values. The second block of output (”B”) shows that the original vector and its clone are distinct objects. If we add another element to the clone, it only appears in the clone, and not in the original. The third block of output (”C”) is, however, a little trickier. Modifying the StringBuffer that was added to the original vector has changed the value of the first element of both the original vector and its clone. The explanation for this lies in the fact that clone made a shallow copy of the vector, so both vectors now point to the exact same StringBuffer instance.

This is, of course, sometimes exactly the behavior that you need. In other cases, however, it can lead to frustrating and inexplicable errors, as the state of an object seems to change “behind your back”.

The solution to this problem is to make a deep copy of the object. A deep copy makes a distinct copy of each of the object’s fields, recursing through the entire graph of other objects referenced by the object being copied. The Java API provides no deep-copy equivalent to Object.clone(). One solution is to simply implement your own custom method (e.g., deepCopy()) that returns a deep copy of an instance of one of your classes. This may be the best solution if you need a complex mixture of deep and shallow copies for different fields, but has a few significant drawbacks:




You must be able to modify the class (i.e., have the source code) or implement a subclass. If you have a third-party class for which you do not have the source and which is marked final, you are out of luck.

You must be able to access all of the fields of the class’s superclasses. If significant parts of the object’s state are contained in private fields of a superclass, you will not be able to access them.

You must have a way to make copies of instances of all of the other kinds of objects that the object references. This is particularly problematic if the exact classes of referenced objects cannot be known until runtime.

Custom deep copy methods are tedious to implement, easy to get wrong, and difficult to maintain. The method must be revisited any time a change is made to the class or to any of its superclasses.

A common solution to the deep copy problem is to use Java Object Serialization (JOS). The idea is simple: Write the object to an array using JOS’s ObjectOutputStream and then use ObjectInputStream to reconsistute a copy of the object. The result will be a completely distinct object, with completely distinct referenced objects. JOS takes care of all of the details: superclass fields, following object graphs, and handling repeated references to the same object within the graph. Figure 3 shows a first draft of a utility class that uses JOS for making deep copies.


--------------------------------------------------------------------------------


import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
/**
* Utility for making deep copies (vs. clone()’s shallow copies) of
* objects. Objects are first serialized and then deserialized. Error
* checking is fairly minimal in this implementation. If an object is
* encountered that cannot be serialized (or that references an object
* that cannot be serialized) an error is printed to System.err and
* null is returned. Depending on your specific application, it might
* make more sense to have copy(…) re-throw the exception.
*
* A later version of this class includes some minor optimizations.
*/

public class UnoptimizedDeepCopy {
/**
* Returns a copy of the object, or null if the object cannot
* be serialized.
*/

public static Object copy(Object orig) {
Object obj = null;
try {
// Write the object out to a byte array
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(bos);
out.writeObject(orig);
out.flush();
out.close();
// Make an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in = new ObjectInputStream(
new ByteArrayInputStream(bos.toByteArray()));
obj = in.readObject();
}
catch(IOException e) {
e.printStackTrace();
}
catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
return obj;
}
}
--------------------------------------------------------------------------------


Figure 3. Using Java Object Serialization to make a deep copy
Unfortunately, this approach has some problems, too:


It will only work when the object being copied, as well as all of the other objects references directly or indirectly by the object, are serializable. (In other words, they must implement java.io.Serializable.) Fortunately it is often sufficient to simply declare that a given class implements java.io.Serializable and let Java’s default serialization mechanisms do their thing.

Java Object Serialization is slow, and using it to make a deep copy requires both serializing and deserializing. There are ways to speed it up (e.g., by pre-computing serial version ids and defining custom readObject() and writeObject() methods), but this will usually be the primary bottleneck.

The byte array stream implementations included in the java.io package are designed to be general enough to perform reasonable well for data of different sizes and to be safe to use in a multi-threaded environment. These characteristics, however, slow down ByteArrayOutputStream and (to a lesser extent) ByteArrayInputStream.

The first two of these problems cannot be addressed in a general way. We can, however, use alternative implementations of ByteArrayOutputStream and ByteArrayInputStream that makes three simple optimizations:


ByteArrayOutputStream, by default, begins with a 32 byte array for the output. As content is written to the stream, the required size of the content is computed and (if necessary), the array is expanded to the greater of the required size or twice the current size. JOS produces output that is somewhat bloated (for example, fully qualifies path names are included in uncompressed string form), so the 32 byte default starting size means that lots of small arrays are created, copied into, and thrown away as data is written. This has an easy fix: construct the array with a larger inital size.

All of the methods of ByteArrayOutputStream that modify the contents of the byte array are synchronized. In general this is a good idea, but in this case we can be certain that only a single thread will ever be accessing the stream. Removing the synchronization will speed things up a little. ByteArrayInputStream’s methods are also synchronized.

The toByteArray() method creates and returns a copy of the stream’s byte array. Again, this is usually a good idea: If you retrieve the byte array and then continue writing to the stream, the retrieved byte array should not change. For this case, however, creating another byte array and copying into it merely wastes cycles and makes extra work for the garbage collector.


An optimized implementation of ByteArrayOutputStream is shown in Figure 4.

--------------------------------------------------------------------------------
import java.io.OutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ByteArrayInputStream;
/**
* ByteArrayOutputStream implementation that doesn’t synchronize methods
* and doesn’t copy the data on toByteArray().
*/

public class FastByteArrayOutputStream extends OutputStream {
/**
* Buffer and size
*/
protected byte[] buf = null;
protected int size = 0;
/**
* Constructs a stream with buffer capacity size 5K
*/
public FastByteArrayOutputStream() {
this(5 * 1024);
}
/**
* Constructs a stream with the given initial size
*/

public FastByteArrayOutputStream(int initSize) {
this.size = 0;
this.buf = new byte[initSize];
}
/**
* Ensures that we have a large enough buffer for the given size.
*/
private void verifyBufferSize(int sz) {
if (sz > buf.length) {
byte[] old = buf;
buf = new byte[Math.max(sz, 2 * buf.length )];
System.arraycopy(old, 0, buf, 0, old.length);
old = null;
}
}
public int getSize() {
return size;
}
/**
* Returns the byte array containing the written data. Note that this
* array will almost always be larger than the amount of data actually
* written.
*/

public byte[] getByteArray() {
return buf;
}
public final void write(byte b[]) {
verifyBufferSize(size + b.length);
System.arraycopy(b, 0, buf, size, b.length);
size += b.length;
}
public final void write(byte b[], int off, int len) {
verifyBufferSize(size + len);
System.arraycopy(b, off, buf, size, len);
size += len;
}

public final void write(int b) {
verifyBufferSize(size + 1);
buf[size++] = (byte) b;
}

public void reset() {
size = 0;
}
/**
* Returns a ByteArrayInputStream for reading back the written data
*/

public InputStream getInputStream() {
return new FastByteArrayInputStream(buf, size);
}
}


--------------------------------------------------------------------------------


Figure 4. Optimized version of ByteArrayOutputStream
The getInputStream() method returns an instance of an optimized version of ByteArrayInputStream that has unsychronized methods. The implementation of FastByteArrayInputStream is shown in Figure 5.



--------------------------------------------------------------------------------


import java.io.InputStream;

import java.io.IOException;
/
* ByteArrayInputStream implementation that does not synchronize methods.
*/
public class FastByteArrayInputStream extends InputStream {
/
* Our byte buffer
*/
protected byte[] buf = null;
/
* Number of bytes that we can read from the buffer
*/
protected int count = 0;
/
* Number of bytes that have been read from the buffer
*/
protected int pos = 0;
public FastByteArrayInputStream(byte[] buf, int count) {
this.buf = buf;
this.count = count;
}
public final int available() {
return count - pos;
}

public final int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}

public final int read(byte[] b, int off, int len) {
if (pos >= count)
return -1;
if ((pos + len) > count)
len = (count - pos);
System.arraycopy(buf, pos, b, off, len);
pos += len;
return len;
}

public final long skip(long n) {
if ((pos + n) > count)
n = count - pos;
if (n < 0)
return 0;
pos += n;
return n;
}
}
--------------------------------------------------------------------------------


Figure 5. Optimized version of ByteArrayInputStream.
Figure 6 shows a version of a deep copy utility that uses these classes:



--------------------------------------------------------------------------------


import java.io.IOException;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectInputStream;
/**

* Utility for making deep copies (vs. clone()’s shallow copies) of
* objects. Objects are first serialized and then deserialized. Error
* checking is fairly minimal in this implementation. If an object is
* encountered that cannot be serialized (or that references an object
* that cannot be serialized) an error is printed to System.err and
* null is returned. Depending on your specific application, it might
* make more sense to have copy(…) re-throw the exception.

*/

public class DeepCopy {

/**
* Returns a copy of the object, or null if the object cannot
* be serialized.
*/

public static Object copy(Object orig) {
Object obj = null;
try {
// Write the object out to a byte array
FastByteArrayOutputStream fbos =new FastByteArrayOutputStream();
ObjectOutputStream out = new ObjectOutputStream(fbos);

out.writeObject(orig);
out.flush();
out.close();
// Retrieve an input stream from the byte array and read
// a copy of the object back in.
ObjectInputStream in =
new ObjectInputStream(fbos.getInputStream());
obj = in.readObject();
}
catch(IOException e) {
e.printStackTrace();
}
catch(ClassNotFoundException cnfe) {
cnfe.printStackTrace();
}
return obj;
}
}
--------------------------------------------------------------------------------

Figure 6. Deep-copy implementation using optimized byte array streams

The extent of the speed boost will depend on a number of factors in your specific application (more on this later), but the simple class shown in Figure 7 tests the optimized and unoptimized versions of the deep copy utility by repeatedly copying a large object.

--------------------------------------------------------------------------------


import java.util.Hashtable;
import java.util.Vector;
import java.util.Date;

public class SpeedTest {
public static void main(String[] args) {

// Make a reasonable large test object. Note that this doesn’t
// do anything useful — it is simply intended to be large, have
// several levels of references, and be somewhat random. We start
// with a hashtable and add vectors to it, where each element in
// the vector is a Date object (initialized to the current time),
// a semi-random string, and a (circular) reference back to the
// object itself. In this case the resulting object produces
// a serialized representation that is approximate 700K.

Hashtable obj = new Hashtable();

for (int i = 0; i < 100; i++) {

Vector v = new Vector();

for (int j = 0; j < 100; j++) {
v.addElement(new Object[] {
new Date(),"A random number: " + Math.random(),
obj});
}
obj.put(new Integer(i), v);
}
int iterations = 10;
// Make copies of the object using the unoptimized version
// of the deep copy utility.
long unoptimizedTime = 0L;
for (int i = 0; i < iterations; i++) {
long start = System.currentTimeMillis();
Object copy = UnoptimizedDeepCopy.copy(obj);
unoptimizedTime += (System.currentTimeMillis() - start);
// Avoid having GC run while we are timing...
copy = null;
System.gc();
}
// Repeat with the optimized version

long optimizedTime = 0L;
for (int i = 0; i < iterations; i++) {
long start = System.currentTimeMillis();
Object copy = DeepCopy.copy(obj);
optimizedTime += (System.currentTimeMillis() - start);
// Avoid having GC run while we are timing...
copy = null;
System.gc();
}
System.out.println("Unoptimized time: " + unoptimizedTime);
System.out.println(" Optimized time: " + optimizedTime);

}
}

--------------------------------------------------------------------------------

Figure 7. Testing the two deep copy implementations.
A few notes about this test:




The object that we are copying is large. While somewhat random, it will generally have a serialized size of around 700 Kbytes.

The most significant speed boost comes from avoid extra copying of data in FastByteArrayOutputStream. This has several implications:



Using the unsynchronized FastByteArrayInputStream speeds things up a little, but the standard java.io.ByteArrayInputStream is nearly as fast.

Performance is mildly sensitive to the initial buffer size in FastByteArrayOutputStream, but is much more sensitive to the rate at which the buffer grows. If the objects you are copying tend to be of similar size, copying will be much faster if you initialize the buffer size and tweak the rate of growth.



Measuring speed using elapsed time between two calls to System.currentTimeMillis() is problematic, but for single-threaded applications and testing relatively slow operations it is sufficient. A number of commercial tools (such as JProfiler) will give more accurate per-method timing data.

Testing code in a loop is also problematic, since the first few iterations will be slower until HotSpot decides to compile the code. Testing larger numbers of iterations aleviates this problems.

Garbage collection further complicates matters, particularly in cases where lots of memory is allocated. In this example, we manually invoke the garbage collector after each copy to try to keep it from running while a copy is in progress.

These caveats aside, the performance difference is sigificant. For example, the code as shown in Figure 7 (on a 500Mhz G3 Macintosh iBook running OSX 10.3 and Java 1.4.1) reveals that the unoptimized version requires about 1.8 seconds per copy, while the optimized version only requires about 1.3 seconds. Whether or not this difference is signficant will, of course, depend on the frequency with which your application does deep copies and the size of the objects being copied.

String empty check is more easy now with JDK6

Prior to JDK 6, we can check if a string is empty in 2 ways:


if(s != null && s.length() == 0)
if(("").equals(s))

Checking its length is more readable and may be a little faster. Starting from JDK 6, String class has a new convenience method isEmpty():

boolean isEmpty()
Returns true if, and only if, length() is 0.

It is just a shorthand for checking length. Of course, if the String is null, you will still get NullPointerException.
I don't see much value in adding this convenience method. Instead,
I'd like to see a static utility method that also handle null value:

public static boolean notEmpty(String s) {
return (s != null && s.length() > 0);
}


Another option, use StringUtils.isEmpty(String str) of Apache commons , can be downloaded from

http://commons.apache.org/

It checks for null string also and return true for empty

public static boolean isEmpty(String str) {
return str == null str.length() == 0;
}