Showing posts with label Core. Show all posts
Showing posts with label Core. Show all posts

Tuesday, December 6, 2011

File Handling in Java

For file handling in java, the package known as java.io is available. This package contains all the required classes needed to perform input and output (I/O) in Java.

Streams

The sequence of data can be defined as a stream. Java defines two types of streams which are given below :
1. Byte
2. Characters

Byte Stream

For dealing input and output of bytes, byte stream is employed. For reading and writing binary data it is incorporated. Binary Stream uses two abstract classes for input and output. These are InputStream class and OutputStream class respectively. To read data from the source InputStream is used and to write data to a destination OutputStream is used.
The class hierarchy of the Byte Stream is given below :

The byte stream classes are given below :
Byte Stream Classes Detail
InputStream The InputStream is an abstract super class .All the classes representing an input
stream of bytes is the subclass of this super class.
OutputStream The  OutputStream is an abstract super class .All the classes representing an output
 stream of bytes is the subclass of this super class.
FileInputStream In a file system, it gets input bytes from a file.
FileOutputStream Using it you can write data to a File or to a FileDescriptor.
ByteArrayInputStream A ByteArrayInputStream has an internal buffer. This buffer can retain bytes read from the stream
ByteArrayOutputStream Data can be written into a byte array using the output stream of ByteArrayOutputStream.
SequenceInputStream The input streams can be logically concatenated using SequenceInputStream.
StringBufferInputStream  The string's content supplies bytes read to an input stream which is created by an application.
The StringBufferInputStream class allows an application to do this.
FilterInputStream It has some additional input stream used as basic data source, These input streams can provide
transformation of data and extra functionality.
FilterOutputStream All the classes that filter output streams is the subclasses of the FilterOutputStream superclass.
DataInputStream It allows an application to read java's data type using an input stream which is independent of machine.
DataOutputStream It allows an application to write java's data type(primitive) to an output stream.
BufferedInputStream It provides additional functionality to the input stream such as capability to buffer. It also supports reset and mark methods.
BufferedOutputStream The buffered output stream is applied by this class.
PrintStream It provide ability to the other output stream to print several data values' representation.
PipedInputStream The data byte written on piped output stream is provided by PipedInputStream. But before that it must connect to the piped output stream.
PipedOutputStream For creating communication pipe, piped output stream should be connected to piped output stream.
PushbackInputStream To sum up the ability to "push back" or "unread" one byte to other input stream, a PushbackInputStream is used.
RandomAccessFile For accessing a file randomly (for reading or writing) this class is incorporated.
Methods defined by InputStream
After creating InputStream object, you can perform additional operations on the stream using given below methods :
  Methods       Description 
public void close() throws IOException{}  The output stream of a file is closed using this function. Before that it releases any resource. This function throws IOException.
protected void finalize()throws IOException {}  This function clears the connection to the file. It throws an IOException.
public int read(int r)throws IOException{}  This function reads the data from the InputStream and return int which is next byte of data. It also returns
-1 if end of file is reached.
public int read(byte[] r) throws IOException{}  This method reads data equal to length of r from the input stream using array. The total number of bytes read is returned after finishing reading. When end of file reached it returns -1.
public int available() throws IOException{}  This function returns the number of bytes available for reading from file input stream. The return type is int.
Method defined by OutputStream
Once you have OutputStream object in hand then there is a list of helper methods which can be used to write to stream or to do other operations on the stream.
   Methods      Description  
public void close() throws IOException{}  This function closes the output stream of the file and throws IOException.
protected void finalize()throws IOException{} This function closes the connection to the file and throws IOException.
public void write(int w)throws IOException{} Using this function, you can write specified bytes to the output stream.
public void write(byte[] w)  This function is used to write bytes of length equal to w to the output stream from the the mentioned byte array.

Character Stream

For handling the input and output of characters Character Stream is  incorporated, which streamlines internationalization.
The hierarchical distribution of Character stream is different from Byte Stream. The hierarchical tree of Character Stream is topped by the Reader and Writer abstract classes. Reader abstract class is used for input while Writer abstract class is used for output.
The method defined by Reader abstract class is given below :
Function / Method  Description
abstract void close( ) throws IOException The input source is closed using this function.
void mark(int numChars) throws IOException This function set a mark in the input stream at the current point. This Point will remain valid till numChars characters are read.
boolean markSupported( ) If the stream support mark( )/reset( ) , this function returns true.
int read( ) throws IOException The input streams' next available character is return by this function as an integer representation.
int read(char buffer[ ]) throws IOException This function reads the characters from buffer equal to the length of buffer.length and it returns the number of successful characters read.
abstract int read(char buffer[ ],int offset, int numChars) throws IOException This function returns the count of the characters successfully read from buffer starting from buffer[offset] up to numChars.
boolean ready( ) throws IOException If the input is pending, it returns true otherwise false.
void reset( ) throws IOException This function resets the input pointer to the previously set mark.
long skip(long numChars) throws IOException This function skips the number of input characters equal to numChars. It returns the count of actually skipped characters.
The method defined by Writer abstract class is given below :
Function / Method  Description 
Writer append(char ch) throws IOException This function adds ch at the end of the output stream which invoked it. It also returns reference to the stream.
Writer append(CharSequence chars) throws IOException This  function adds the chars to the end of the output stream which invoked it. It also returns a reference to the stream.
Writer append(CharSequence chars, int begin, int end) throws IOException This function adds a sub range of chars to the end of the output stream. It returns a reference to the stream.
abstract void close( ) throws IOException The output stream is closed by this function.
abstract void flush( ) throws IOException This function flushes the buffer of output.
void write(int ch) throws IOException This function writes the character to the output stream. The characters are in the low-order 16 bits of ch .
void write(char buffer[ ]) throws IOException Using this function you can write to the output stream -a complete array of characters .
abstract void write(char buffer[ ],int offset, int numChars) throws IOException This function is used to writes a sub range of numChars characters from the array buffer to the output stream beginning at buffer[offset].
void write(String str) throws IOException Using this function you can writes str to the output stream.
void write(String str, int offset, int numChars) Using this function, from the string str ,you can write a sub range of numChars characters.

The File Class

In spite of classes available to support file I/O, Java has a class named as File, which contains information about a file.  For manipulating a file or the computer's file system, this class is very effective and efficient. This class is used for creation of files and directories, file searching, file deletion etc.
Once you have File object in hand then there is a list of helper methods which can be used manipulate the files, which are given below :
   Methods      Description  
public String getName() This function returns the file or directory's name specified by the pathname.
public String getParent() This function returns the parent directory pathname string. The pathname of the directory is passed to know it's parent pathname string. If the pathname doesn't have parent directory, it returns null.
public File getParent File() This function returns the parent directory abstract pathname and it returns null if it doesn't have parent directory.
public String getPath() To convert the abstract pathname into a pathname string, we use this function.
public boolean isAbsolute() This function return true if this abstract pathname is absolute otherwise returns false.
public String getAbsolutePath()  To find the absolute pathname string of the provided abstract pathname, we incorporate this method.
public boolean canRead()  This function is used to check if the application can read the file provided by this abstract
 pathname. This function returns true if the file name provided by the abstract pathname exists otherwise return false.
public boolean canWrite()  This function is used to check if the application can modify to the file provided through this abstract
 pathname. This function returns true if the file name provided by the abstract pathname exists and allowed to write, otherwise return false.
public boolean exists()  This function returns true if the file name provided by the abstract pathname exists otherwise return false.
public boolean isDirectory()  This function returns true if the file represented by the abstract pathname is a directory otherwise returns false.
public boolean isFile()  This function is used to test whether the file represented by the abstract pathname exist and also checks whether it is a normal file. If it is , it will return true otherwise return false.
public long lastModified()  This function is used to return the last modification time of the file represented by the abstract pathname.
public long length()  This function finds the length of the file of the file represented by the abstract pathname and return it. It returns unspecified if the pathname represented is a directory.
public boolean createNewFile()
 throws IOException
This function is used to create a new file which has the name provided by its abstract pathname. It will return true if the file created successfully otherwise returns false.
public boolean delete()  This function is used to delete the file/directory represented by the  abstract pathname.
public void deleteOnExit()  This function is used to delete the file represented by the  abstract pathname when the virtual machine terminates.
public String[] list()   This function returns an array of strings naming the files and directories in the directory specified by its abstract pathname.  
public String[] list(FilenameFilter filter)  This function returns an array of strings naming the files and directories in the directory specified by its abstract pathname that satisfy the specified filter.
public File[] listFiles()  This functions returns an array of abstract pathnames represented by the files in the directory.
public File[] listFiles(FileFilter filter)  This function returns an array of abstract pathnames represented by the files and directories
 in the directory represented by this abstract pathname that satisfy the
specified filter.
public boolean mkdir()  This function creates the directory named by this abstract pathname. this function returns true if the file created successfully otherwise false.
public boolean mkdirs()  This method creates the directory named by this abstract pathname, including any
necessary but nonexistent parent directories. Returns true if and only ifbr> the directory was created, along with all necessary parent directories;
false otherwise
public boolean renameTo(File dest)  This function renames the file represented by this abstract pathname. 
public boolean setLastModified(long time)  This function is used to set the last modification time of the file/ directory specified by the abstract
pathname.
public boolean setReadOnly()   This function sets the file provided through abstract pathname to read-only mode. If it succeeded, it returns true otherwise returns false.
public String toString()  This function is used to return the pathname string of the abstract pathname provided.
FileReader Class
FileReader class inherits from the InputStreamReader class. For reading streams of characters, this class is used.
Once you have FileReader object in hand then there is a list of helper methods which can be used manipulate the files :
Method / Function Description
public int read() throws IOException This function reads a single character at a time and returns the count of number of character read.
public int read(char [] c, int offset, int len) This function is used to read characters. An array is used to read characters.
FileWriter Class
FileWriter Class inherits from the OutputStreamWriter class. For writing streams of characters, this class is incorporated.
Methods / Function Description
public void write(int c) throws IOException Using this function, you can write a single character.
public void write(char [] c, int offset, int len) Using this function, you can write a part of an array specified by offset(starting) up to the length from offset.
public void write(String s, int offset, int len) Using this function, you can write a part of an String specified by offset(starting) up to the length(specified by len) from offset.

Sunday, November 27, 2011

Interface


In general, interface is the way just to say something to a media by using another media. Let's take the general life example. TV Remote is the interface because it is the medium to give the command to a TV in order to change the channels or to ON/OFF the TV. Electric switch is also the interface's example.

But in java programming language interface is nothing but the collection of methods with empty implementations and constants variables (variables with static and final declarations). All the methods in an interface are "public and abstract" by default. Since interfaces are abstract in nature so they can not be directly instantiated. To define the methods of an interface the keyword "implements" is used. 

Interfaces are similar to abstract classes but the major difference between these two is that interface have all the methods abstract while in case of abstract classes must have at least one abstract method. Interface combines the two functionality (template and multiple inheritance) of C++ language into one (in itself).  
 
Interface Definition
visibility mode interface InterfaceName {
        constant variable declarations
        
abstract method declarations
}

e.g.
public interface RacingCar {
  
public void startcar (int Obj); 
  
public void changegear (int Obj); 
  
public void incrrace (int Obj);
  
public void stopcar (int Obj);
}

Marker Interface
In java language programming, interfaces with no methods are known as marker interfaces. Marker interfaces are Serializable, Clonable, SingleThreadModel, Event listener. Marker Interfaces are implemented by the classes or their super classes in order to add some functionality.
e.g.  Suppose you want to persist (save) the state of an object then you have to implement the Serializable interface otherwise the compiler will throw an error. To make more clearly understand the concept of marker interface you should go through one more example.  
Suppose the interface Clonable is neither implemented by a class named Myclass nor it's any super class, then a call to the method clone() on Myclass's object will give an error. This means, to add this functionality one should implement the Clonable interface. While the Clonable is an empty interface but it provides an important functionality.

Difference between Interfaces and abstract classes
Some important difference between Interface and abstract classes are given here

    Features                             Interface                             Abstract Class
    Methods An interface contains all the methods with empty implementation.An abstract class must have at least one method with empty implementation.        
   VariablesThe variables in interfaces are final and static.Abstract classes may contain both instance as well as static variables.
    Multiple   Inheritance In java multiple inheritance is achieved by using the interface (by implementing more than one interface at a time)Abstract classes does not provide this functionality.
 Additional Functions  If we add a method to an interface then we will have to implement this interface by any class..In Abstract classes we can add a method with default implementation and then we can use it by extending the abstract class. 
Used WhenAll the features are implemented differently in different objects.When there are some common features shared by all the objects.
Diff
Can’t have ConstructorCan have Constructor

IMP TIP: 
Why u can’t create object for Abstract Class: Since abstract class contains incomplete methods, it is not possible to estimate the total memory required to create an object. So JVM can’t create objects to an abstract class.

Sunday, October 2, 2011

Can I dynamically load, unload or reload a JAR?

/*
 * ClassLoader - JarFileLoader.java, Oct 3, 2011 1:06:13 PM
 * 
 * Copyright 2011 Varra Ltd, Inc. All rights reserved.
 * Varra proprietary/confidential. Use is subject to license terms.
 */
package com.varra.net;

import java.io.File;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.jar.JarFile;

import com.varra.util.EnhancedTimerTask;
import com.varra.util.GlobalThread;

/**
 * The Class JarFileLoader.
 * 
 * @author Rajakrishna V. Reddy
 * @version 1.0
 */
public class JarFileLoader extends URLClassLoader
{
   
    /**
     * Instantiates a new jar file loader.
     * 
     * @param urls
     *            the urls
     */
    public JarFileLoader()
    {
        super(new URL[] {});
    }
   
    /**
     * Adds the file.
     * 
     * @param file
     *            the file
     * @throws MalformedURLException
     *             the malformed url exception
     */
    public void addFile(File file) throws MalformedURLException
    {
        addURL(file.toURI().toURL());
    }
   
    /**
     * Closes all open jar files.
     */
    public void close()
    {
        try
        {
            Class<?> clazz = java.net.URLClassLoader.class;
            Field ucp = clazz.getDeclaredField("ucp");
            ucp.setAccessible(true);
            Object sunMiscURLClassPath = ucp.get(this);
            Field loaders = sunMiscURLClassPath.getClass().getDeclaredField("loaders");
            loaders.setAccessible(true);
            Object collection = loaders.get(sunMiscURLClassPath);
            for (Object sunMiscURLClassPathJarLoader : ((Collection<?>) collection).toArray())
            {
                try
                {
                    Field loader = sunMiscURLClassPathJarLoader.getClass().getDeclaredField("jar");
                    loader.setAccessible(true);
                    Object jarFile = loader.get(sunMiscURLClassPathJarLoader);
                    ((JarFile) jarFile).close();
                }
                catch (Throwable t)
                {
                    // if we got this far, this is probably not a JAR loader so
                    // skip it
                }
            }
        }
        catch (Throwable t)
        {
            // probably not a SUN VM
        }
        return;
    }
   
    /**
     * The main method.
     * 
     * @param args
     *            the arguments
     */
    public static void main(String args[])
    {
        try
        {
            System.out.println("First attempt...");
            Class.forName("com.varra.temp.Class1");
        }
        catch (Exception ex)
        {
            System.out.println("Failed.");
        }
        try
        {
            JarFileLoader clazzLoader = new JarFileLoader();
            clazzLoader.addFile(new File("/krishna/RapidHealthAgent/FileWatcher/bin/filewatcher-1.0.jar"));
            clazzLoader.addFile(new File("/krishna/RapidHealthAgent/FileTailer/bin/filetailer-1.0.jar"));
           
            Package[] packages = clazzLoader.getPackages();
            for (Package package1 : packages)
            {
                if (package1.getName().startsWith("com"))
                {
                    System.out.println("B4 Paks: "+package1.getName());
                }
            }
            System.out.println("Second attempt...");
            Class<?> fileWatcherClass = clazzLoader.loadClass("com.mt.filewatcher.FileWatcher");
            final Method method = fileWatcherClass.getMethod("getFileWatcher", null);
            final Object fileWatcher = method.invoke(null, null);
            final GlobalThread globalThread = GlobalThread.getGlobalThread(1);
            globalThread.start();
            globalThread.onTimerTask((EnhancedTimerTask) fileWatcher);
           
            Class<?> testTailer = clazzLoader.loadClass("com.mt.filetailer.TestTailer");
            testTailer.newInstance();
            System.out.println("loadClass: " + testTailer);
            packages = clazzLoader.getPackages();
            for (Package package1 : packages)
            {
                if (package1.getName().startsWith("com"))
                {
                    System.out.println("B4 Paks: "+package1.getName());
                }
            }
            System.out.println("Success!");
        }
        catch (Exception ex)
        {
            System.out.println("Failed.");
            ex.printStackTrace();
        }
    }
}

Saturday, October 1, 2011

The SSL/TLS-based RMI Socket Factories in J2SE 5.0

Since J2SE 5.0 client and server SSL/TLS-based RMI Socket Factories are part of the Java platform. The newly defined java package javax.rmi.ssl defines two new classes:
These two new classes allow to export SSL/TLS-protected remote objects and RMI registries in a standard and portable way. You can specify the cipher suites and protocols to be enabled and if client authentication is required by the server. You don't need anymore to implement and deploy your custom SSL/TLS-based RMI Socket Factories thus avoiding the hassle of having to add to your client classpath your custom factories.
Let's introduce the SSL/TLS-based RMI Socket Factories capabilities through an example that will be incrementally modified.
The example is comprised of the following java classes:
  • Hello: The remote interface defining a single remote method sayHello().
  • HelloImpl: The remote object implementing the Hello remote interface.
  • HelloClient: The client invoking the sayHello() remote method in the Hello remote interface.
  • RmiRegistry: This class denotes the RMI registry and allows to create it with custom factories. The RMI registry can be also created in the same JVM as HelloImpl but let's create it in a separate JVM because this will make clearer the use of SSL/TLS to export remote objects and RMI registries.

Let's have a look first at the example without any SSL/TLS protection at all.
  • Hello:
    public interface Hello extends Remote {
        public String sayHello() throws RemoteException;
    }
  • HelloImpl:
    public class HelloImpl extends UnicastRemoteObject implements Hello {
        public HelloImpl() throws RemoteException {
            super();
        }
        public String sayHello() {
            return "Hello World!";
        }
        public static void main(String args[]) throws Exception {
            // Get reference to the RMI registry running on port 3000 in the local host
            Registry registry = LocateRegistry.getRegistry(null, 3000);
            // Bind this object instance to the name "HelloServer"
            HelloImpl obj = new HelloImpl();
            registry.bind("HelloServer", obj);
            System.out.println("HelloServer bound in registry");
        }
    }
  • HelloClient:
    public class HelloClient {
        public static void main(String args[]) throws Exception {
            // Get reference to the RMI registry running on port 3000 in the local host
            Registry registry = LocateRegistry.getRegistry(null, 3000);
            // Lookup the remote reference bound to the name "HelloServer"
            Hello obj = (Hello) registry.lookup("HelloServer");
            String message = obj.sayHello();
            System.out.println(message);
        }
    }
  • RmiRegistry:
    public class RmiRegistry {
        public static void main(String[] args) throws Exception {
            // Start RMI registry on port 3000
            LocateRegistry.createRegistry(3000);
            System.out.println("RMI registry running on port 3000");
            // Sleep forever
            Thread.sleep(Long.MAX_VALUE);
        }
    }
In order to run the example open a shell window, go to the directory containing the compiled class files and call:
  • $ java RmiRegistry &
    RMI registry running on port 3000
  • $ java HelloImpl &
    HelloServer bound in registry
  • $ java HelloClient
    Hello World!

Now let's export the HelloImpl remote object with the SSL/TLS-based RMI Socket Factories using the default constructors. This means that the default protocol and cipher suites will be chosen by the default SSL socket factory implementation and only server authentication will be required. Let's assume a keystore containing a self-signed certificate has been created beforehand. Also, the server's certificate has been imported as a trusted certificate into a truststore. More detailed information about how to set up all the SSL configuration can be found in the JSSE Reference Guide. The keystore and trustore location and their related passwords are supplied in the command-line through the system properties used by the Sun's JSSE implementation:
  • javax.net.ssl.keyStore
  • javax.net.ssl.keyStorePassword
  • javax.net.ssl.trustStore
  • javax.net.ssl.trustStorePassword
When the client invokes the sayHello() method the server will send its certificate to the client. The client will then verify it against its truststore to see if it is a trusted certificate. If true, the method invocation goes on. Otherwise, the SSL handshake fails and an exception is thrown.
The following file needs to be changed as follows:
  • HelloImpl:
    public class HelloImpl extends UnicastRemoteObject implements Hello {
        public HelloImpl() throws RemoteException {
            super(0, new SslRMIClientSocketFactory(), new SslRMIServerSocketFactory());
        }
        public String sayHello() {
            return "Hello World!";
        }
        public static void main(String args[]) throws Exception {
            // Get reference to the RMI registry running on port 3000 in the local host
            Registry registry = LocateRegistry.getRegistry(null, 3000);
            // Bind this object instance to the name "HelloServer"
            HelloImpl obj = new HelloImpl();
            registry.bind("HelloServer", obj);
            System.out.println("HelloServer bound in registry");
        }
    }
In order to run the example open a shell window, go to the directory containing the compiled class files and call:
  • $ java -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword RmiRegistry &
    RMI registry running on port 3000
  • $ java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password HelloImpl &
    HelloServer bound in registry
  • $ java -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword HelloClient
    Hello World!

Now let's export the HelloImpl remote object with the SSL/TLS-based RMI Socket Factories which require client authentication too. Now when the client invokes the sayHello() method the server will send its certificate to the client. The client will then verify it against its truststore to see if it is a trusted certificate. What's new here is that the client has to send also a certificate to the server. The server will verify the client's certificate against its truststore in order to see if it's trusted. If both server and client authentication succeeds, the method invocation goes on. Otherwise, the SSL handshake fails and an exception is thrown.
The following file needs to be changed as follows:
  • HelloImpl:
    public class HelloImpl extends UnicastRemoteObject implements Hello {
        public HelloImpl() throws RemoteException {
            super(0, new SslRMIClientSocketFactory(),
                     new SslRMIServerSocketFactory(null, null, true));
        }
        public String sayHello() {
            return "Hello World!";
        }
        public static void main(String args[]) throws Exception {
            // Get reference to the RMI registry running on port 3000 in the local host
            Registry registry = LocateRegistry.getRegistry(null, 3000);
            // Bind this object instance to the name "HelloServer"
            HelloImpl obj = new HelloImpl();
            registry.bind("HelloServer", obj);
            System.out.println("HelloServer bound in registry");
        }
    }
In order to run the example open a shell window, go to the directory containing the compiled class files and call:
  • $ java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword RmiRegistry &
    RMI registry running on port 3000
  • $ java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword HelloImpl &
    HelloServer bound in registry
  • $ java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword HelloClient
    Hello World!

Now let's export the HelloImpl remote object with the SSL/TLS-based RMI Socket Factories which require client authentication and the use of the TLSv1 protocol and the SSL_RSA_WITH_RC4_128_MD5 cipher suite. Now when the client invokes the sayHello() method besides verifying the client and server certificates the SSL handshake will fail if any of the server or client JSSE implementations does not support the supplied protocol and/or cipher suite. The enabled protocols and cipher suites are specified through the SslRMIServerSocketFactory constructor in the server side and through the system properties defined by SslRMIClientSocketFactory in the client side:
  • javax.rmi.ssl.client.enabledCipherSuites
  • javax.rmi.ssl.client.enabledProtocols
The following file needs to be changed as follows:
  • HelloImpl:
    public class HelloImpl extends UnicastRemoteObject implements Hello {
        public HelloImpl() throws RemoteException {
            super(0, new SslRMIClientSocketFactory(),
                     new SslRMIServerSocketFactory(new String[] {"SSL_RSA_WITH_RC4_128_MD5"},
                                                   new String[] {"TLSv1"},
                                                   true));
        }
        public String sayHello() {
            return "Hello World!";
        }
        public static void main(String args[]) throws Exception {
            // Get reference to the RMI registry running on port 3000 in the local host
            Registry registry = LocateRegistry.getRegistry(null, 3000);
            // Bind this object instance to the name "HelloServer"
            HelloImpl obj = new HelloImpl();
            registry.bind("HelloServer", obj);
            System.out.println("HelloServer bound in registry");
        }
    }
In order to run the example open a shell window, go to the directory containing the compiled class files and call:
  • $ java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_MD5 -Djavax.rmi.ssl.client.enabledProtocols=TLSv1 RmiRegistry &
    RMI registry running on port 3000
  • $ java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword HelloImpl &
    HelloServer bound in registry
  • $ java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword -Djavax.rmi.ssl.client.enabledCipherSuites=SSL_RSA_WITH_RC4_128_MD5 -Djavax.rmi.ssl.client.enabledProtocols=TLSv1 HelloClient
    Hello World!

Let's finally protect the access to the RMI registry with SSL/TLS. In order to do that the methods taking as input parameters RMI socket factories in the LocateRegistry class, i.e. createRegistry and getRegistry will be used. The SSL/TLS-based RMI Socket Factories used to create the RMI registry must require client authentication as this is the only way the RMI registry can refuse requests from clients sending untrusted certificates.
The following files need to be changed as follows:
  • HelloImpl:
    public class HelloImpl extends UnicastRemoteObject implements Hello {
        public HelloImpl() throws RemoteException {
            super(0, new SslRMIClientSocketFactory(),
                     new SslRMIServerSocketFactory(null, null, true));
        }
        public String sayHello() {
            return "Hello World!";
        }
        public static void main(String args[]) throws Exception {
            // Get reference to the RMI registry running on port 3000 in the local host
            Registry registry = LocateRegistry.getRegistry(null, 3000, new SslRMIClientSocketFactory());
            // Bind this object instance to the name "HelloServer"
            HelloImpl obj = new HelloImpl();
            registry.bind("HelloServer", obj);
            System.out.println("HelloServer bound in registry");
        }
    }
  • HelloClient:
    public class HelloClient {
        public static void main(String args[]) throws Exception {
            // Get reference to the RMI registry running on port 3000 in the local host
            Registry registry = LocateRegistry.getRegistry(null, 3000, new SslRMIClientSocketFactory());
            // Lookup the remote reference bound to the name "HelloServer"
            Hello obj = (Hello) registry.lookup("HelloServer");
            String message = obj.sayHello();
            System.out.println(message);
        }
    }
  • RmiRegistry:
    public class RmiRegistry {
        public static void main(String[] args) throws Exception {
            // Start RMI registry on port 3000
            LocateRegistry.createRegistry(3000,
                                          new SslRMIClientSocketFactory(),
                                          new SslRMIServerSocketFactory(null, null, true));
            System.out.println("RMI registry running on port 3000");
            // Sleep forever
            Thread.sleep(Long.MAX_VALUE);
        }
    }
In order to run the example open a shell window, go to the directory containing the compiled class files and call:
  • $ java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword RmiRegistry &
    RMI registry running on port 3000
  • $ java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword HelloImpl &
    HelloServer bound in registry
  • $ java -Djavax.net.ssl.keyStore=keystore -Djavax.net.ssl.keyStorePassword=password -Djavax.net.ssl.trustStore=truststore -Djavax.net.ssl.trustStorePassword=trustword HelloClient
    Hello World! 

Feel free to download the resource zip file in attachment and play with it or tailor it to your specific application needs.
 

Monday, September 26, 2011

Getting the IP Address and Hostname of the Local Machine



This code will list all interfaces and attached inet addresses on local machine, And fetch you teh actual ip address of the host.     

       
        final String hostname = InetAddress.getLocalHost().getHostName();
        String ip = InetAddress.getLocalHost().getHostAddress();
        final Enumeration<NetworkInterface> ifaces = NetworkInterface.getNetworkInterfaces();
        for (NetworkInterface iface : Collections.list(ifaces))
        {
            /*final Enumeration<NetworkInterface> virtualIfaces = iface.getSubInterfaces();
            for (NetworkInterface viface : Collections.list(virtualIfaces))
            {
                System.out.println(iface.getDisplayName() + " VIRT " + viface.getDisplayName());
                final Enumeration<InetAddress> vaddrs = viface.getInetAddresses();
                for (InetAddress vaddr : Collections.list(vaddrs))
                {
                    System.out.println("\t" + vaddr.toString());
                }
            }*/
            final Enumeration<InetAddress> raddrs = iface.getInetAddresses();
            for (InetAddress addr : Collections.list(raddrs))
            {
                if (!addr.isLoopbackAddress() && addr.isSiteLocalAddress())
                {  
                    ip = addr.getHostAddress();
                }
            }
        }


Saturday, September 24, 2011

Want to know where your class is loaded up from?

In general there is no guarantee that u can always get the location(Basically URL) from where ur instance or object is loaded but luck u can’t completely discard.. :)

The following class which i am putting tries to find out the location of teh instance from where it is loaded. All you need to do is call the getClass method on your concerned instance and pass the output to this method.

package com.varra.classloader;

import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;

public class FindClassLoaction {

public static URL getClassLocation (final Class clazz)
{
URL clazzLocation = null;
final String clazzFileName = clazz.getName().replace (‘.’, ‘/’).concat (“.class”);

final ProtectionDomain pd = clazz.getProtectionDomain ();
if (pd != null)
{
final CodeSource codeSourceOfClazz = pd.getCodeSource();
if (codeSourceOfClazz != null) clazzLocation = codeSourceOfClazz.getLocation ();

if (clazzLocation != null)
{
if (“file”.equals (clazzLocation.getProtocol ()))
{
try
{
if (clazzLocation.toExternalForm ().endsWith (“.jar”) ||
clazzLocation.toExternalForm ().endsWith (“.zip”))
clazzLocation = new URL (“jar:”.concat (clazzLocation.toExternalForm ())
.concat(“!/”).concat (clazzFileName));
else if (new File (clazzLocation.getFile ()).isDirectory ())
clazzLocation = new URL (clazzLocation, clazzFileName);
}
catch (MalformedURLException ignore) {}
}
}
}

if (clazzLocation == null)
{
final ClassLoader clsLoader = clazz.getClassLoader ();

clazzLocation = clsLoader != null ?
clsLoader.getResource (clazzFileName) :
ClassLoader.getSystemResource (clazzFileName);
}

return clazzLocation;
}

}


or


public static void which(Class aClass) throws Exception {
System.out.println(aClass.getProtectionDomain().getCodeSource().getLocation());
}

or

Start the java program with -verbose switch and it will print out the class being loaded and the jar/location from where it is being picked up. Sounds simple right? Yeah, but one caveat is, this would work only with Tiger(JDK5) version onwards. Good luck in your classloading issues, if any.


The luck factor here is that u can’t guarantee the fact that every class is loaded with some ProtectionDomain i.e. It depends on the classloader whether it is creating the ProtectionDomain before loading the class….:(

also the CodeSource can be null depending on the classloader implementation. U can almost be sure that protection domain and code source will be populated for the classloders which are instance of URLClassLoader. So better you can put a check on the claasloader whether its an instance of URLClassLoader to be on safe side.

Sun’s implementation seems to allow finding the class file as resource ..

enjoy….

Of Thread dumps and stack traces …

Thread dumps and stack traces are probably some of the least understood features of java. Why else would I come across developers who have no clue what do do after looking at an Exception stack trace?

Street Side Programmer?!

An ex-colleague of mine, Manoj “The Anger” Acharya, had coined the phrase Street Side Programmer [a la Server Side Programmer] and he would dole out this title to all those who would come to him with annoying questions. Nothing annoyed him more than having some one come and ask him I am getting some exception when I do *blah* *blah*. His typical answer *bleep*’ing Street Side Programmers … what is some exception supposed to mean?! Doesn’t it have a name? Doesn’t it have a stack trace??
I was reminded of him the other day, when a trainee learning java came to me saying My program is not running … there seems to be some problem … can you come and take a look?. The kid is quite sweet, so instead of telling him about Anger, I just went to his seat. The command prompt had something like this:
C:\learn\classes>java Test
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: 5
        at Test.run(Test.java:11)
        at Test.<init>(Test.java:4)
        at Test.main(Test.java:19)
I wonder if the book he was reading had any section on reading stack traces. [Monsieur Bruce Eckel ... are you listening?!] I really think any introduction to java book should have this as one of the earliest chapters … right after defining a class and method! Some one makes an error while trying out samples, or is tinkering around with the code, which typically results in an exception … what is one supposed to do next?!

Anatomy of a Stack Trace

Well I explained that an exception stack trace is java’s way of telling you exactly what went wrong and where it went wrong. The first line of the stack trace gives you the exception name and the exception message and what follows is the “stack trace”. The stack trace is to be read from top to bottom, line by line. Each line has the name of the class and the name of the method being executed followed by the file name and line number in parentheses. 
In this case a java.lang.ArrayIndexOutOfBoundsException with the message “5” was raised. To know where it was raised, we look at the next line. It tells us that the exception was raised while executing the run method of the Test class at line number 11 in Test.java file. The next line tells us that the run method was called by the constructor [the stack trace shows Constructors as <init> and static blocks in a class as <clinit>] of the Test class at line number 4 in Test.java file. The next line tells us that the constructor was called by the main method of Test class at line number 19 of Test.java file.
So the java stack trace would read in English would be like:
You accessed an array with an index of 5, however the array does not have 6 elements [thanks to zero based index]. This happened when I was executing the run method of Test class which happens to be in line number 11 of Test.java file. The run method was called by the constructor of Test class at line number 4 of Test.java file. The constructor was called by the main method of the Test class at line number 19 of Test.java file. 
Well… there is a wealth of information here. It tells you exactly what the VM was doing when the exception was raised. Let us see how to debug the issue given all this information. The Test.java file looks like this: 
1    public class Test
2    {
3        public Test(int[] nums){
4            run(nums);
5        }
6
7        private void run(int[] nums)
8        {
9            int n = nums.length;
10           for (int i = 0; i < nums.length; i++) {
11               int num = nums[n];
12               System.out.println(num);
13           }
14       }
15
16       public static void main(String argv[])
17               throws Exception
18       {
19           new Test(new int[]{1,3,5,7,9});
20       }
21   } 
Stepping through the code [as per the stack trace], we called the main method, which invoked the constructor at line number 19, which in turn called the run method at line number 4. Hey the stack trace was correct after all! Now we look at line number 11 where the exception was raised. The exception says that we accessed an array with incorrect index. The only array we are accessing at line number 11 is the num array. The index being used to access the array was n. So what the VM is trying to tell you is that the n is larger that the size of the array nums. Which is in fact true. n happens to be the length of the array. So it IS greater than the last index of the array. What the user really wanted to do was use i as the loop index and not n.
Another common exception raised is the java.lang.NullPointerException. The NPE!  A NullPointerException is Java’s way of telling a user that a null object reference was being used. Take a look at the following lines from a stack trace [snipped for brevity]:
java.lang.NullPointerException:
        at foo.bar.MyServlet.doGet(MyServlet.java:36)
So now we know that a null object was being referened at line number 36 of MyServlet.java. The code for the servlet looks something like:
35    String userNameParam = request.getParameter("username");
36    if(userNameParam.equals("root"))
37    {
The only object reference being used in line number 36 happens to be userNameParam. So it was null when the VM was executing that line. Now we track down what values were assigned to the userNameParam. Line number 35 happens to be the only assignment in this case. It assigns the value of userNameParam to request.getParameter("username"). Since the VM told us that the userNameParam was null, it means that the method request.getParameter("username") returned a null value. Looking at the documentation of the method we know that the method may return null. So the users of the method need to code taking that into consideration. In this case we would change the condition like so:  
35    String userNameParam = request.getParameter("username");
36    if(userNameParam!=null && userNameParam.equals("root"))
37    {
Thanks to stack traces some one who is not even aware of the code can pin point the exact location of the error. In most of the cases a stack trace is definitely starting points for debugging erroneous behavior. Who wants messy
core dumps anyways when you have readable stack traces?!

Innovative uses of stack traces

Once you know what a stack trace provides, there are a lot of innovative ways to use it. Basically answer questions like how did I get here or to record the location of an event.
Recently a customer noticed that the VM was performing Full GC’s very frequently. This would happen even when the application is completely idle. Looking at java -verbose:gc -XX:+PrintGCTimeStamps ... , we realized that the Full GC would occur every one minute … on the dot. We then tried adding the -XX:+DisableExplicitGC option and voila no more full GCs! So looks like some one was doing a System.gc somewhere at every one minute.
So how do we find out who is calling it?! You would extract the System.java file from <jdk-home>/src.zip!/java/lang/System.java and edit it like so:
736    public static void gc() {
737	       new Exception("Some one triggered Full GC from here").printStackTrace();
738            Runtime.getRuntime().gc();
739       }
740
Compile the modified file and prepend it to your bootclasspath using the option -Xbootclasspath/p:outputDir. Next time we ran the application, we got the stack trace:
java.lang.Exception: Some one triggered Full GC from here
        at java.lang.System.gc(System.java:737)
	at sun.misc.GC$Daemon.run(GC.java:92)
Adding one more stack trace to GC.java [You will not find sources for the com.sun.* and sun.* packages in the src.zip that comes with your jdk. You will have to download it from Sun's Community Source site.] we get to know that sun.rmi.transport.ObjectTable is triggering the full GC based on an interval specified by the system property sun.rmi.dgc.server.gcInterval. The default value for the property happens to be one minute.
So using the printStackTrace method we could debug where Full GC was being triggered explicitly. You could
ofcourse do the same by setting a method break point for the System.gc method. Or you could be
a smart google’er and stumble upon the “Other considerations” section of the
GC options page!
Instead of doing a new Exception(…).printStackTrace(), you could alternatively do a Thread.dumpStack() which internally does the same. The only disadvantage is that Thread,dumpStack() does take a message as its
parameter.
Some times it makes sense to create an exception object and hold a reference to it until a later point in time. Suppose you have a class which looks like:
1    import java.io.IOException;
2
3    /** 
4     * A class that represents a heavy weight resource. 

5     */
6    public class Resource
7    {
8        private boolean closed;
9
10       public void close() throws IOException{
11           if(closed)
12               throw new IOException("Resource already closed.");
13           //resource cleanup 

14           closed=true;
15       }
16       //code snipped for brevity ...
The class throws an exception when a user invokes close on an already closed resource. The stack trace of the IOException is going to tell you where in the code you tried to close the already closed connection. For example the following output tells you that when you called close on the Resource at line 41 of ResourceTest.java it was already closed.
C:\learn\classes>java ResourceTest
java.io.IOException: Resource already closed.
        at Resource.close(Resource.java:12)
        at ResourceTest.closeResource(ResourceTest.java:37)
        at ResourceTest.run(ResourceTest.java:26)
        at ResourceTest.main(ResourceTest.java:50)
But now what if you want to know where did you close it the first time?! You would change the code like so:
1    import java.io.IOException;
2
3    /** 
4     * A class that represents a heavy weight resource. 
5     */ 

6    public class Resource
7    {
8        private boolean closed;
9
10       private Exception closedAt;
11
12       public void close() throws IOException{
13           if(closed) {
14               closedAt.printStackTrace();
15               throw new IOException("Resource already closed.");
16           }
17           //resource cleanup 

18           closed=true;
19           closedAt=new Exception("Resource closed here the first time.");
20       }
21       //code snipped for brevity ...
The output would after making the changes would look like …
C:\learn\classes>java ResourceTest
java.lang.Exception: Resource closed here the first time.
        at Resource.close(Resource.java:19)
        at ResourceTest.useResource(ResourceTest.java:32)
        at ResourceTest.run(ResourceTest.java:25)
        at ResourceTest.main(ResourceTest.java:50)
java.io.IOException: Resource already closed.
        at Resource.close(Resource.java:15)
        at ResourceTest.closeResource(ResourceTest.java:41)
        at ResourceTest.run(ResourceTest.java:26)
        at ResourceTest.main(ResourceTest.java:50)
So now from the stack traces we know that a close was called first at line 32 of ResourceTest.java and later at line 41 we called a close on the same resource for the second time.
There are a lot of multi threaded problems [NullPointers] which we were not able to debug with a debugger because the whole application would become too slow to simulate the problem scenario. However, by using Exception objects to track threads which were setting the fields to null, we were able to resolve the issues. A word of caution though … creating exception objects is resource intensive. Creating too many exception objects takes lot of CPU. And if you are holding references to all the objects it requires memory too!

Thread dump 101

If the stack trace which gives the information on what a thread was doing at that moment can help us in so many ways, just imagine the possibilites if you could find out what every single thread in the Java VM is doing at any given moment! A Full Thread Dump or a thread dump for short gives us exactly that information. Consider the following source
1    public class Test
2    {
3        public Test(char[] chars){
4            System.out.println("New line at "+findNewLine(chars));
5        }
6
7        private int findNewLine(char[] chars)
8        {
9            int i = 0;
10           char aChar;
11           do{
12               aChar = chars[i];
13           }while(aChar!='\n');
14           return i;
15       }
16
17       public static void main(String argv[])
18               throws Exception
19       {
20           new Test("Hello World!\nHowz goin?!">.toCharArray());
21       }
22   }
The method findNewLine is supposed to return the first index of a new line character in a given char array. [Purists please don't mail me with the list of reasons why this approach is not right ... the idea here is not really to write the best way to find a new line character!] Now when you run the program it just won’t print the result. One look at top in unix or the task manager in windows we get to know that VM has taken the CPU for a spin…. 100% CPU consumption for ever! Now wouldn’t you want to know what the VM is doing. Why is it taking all this CPU and not printing the output it is supposed. 
One way to do this would be rerun the program in debug mode. Use the debugger and debug the application. However, many a times you come across such the situation on a live system after running the app for a long duration. Since it is a live system and we hit the issue only after running the application for a long duration we can not leave it in debug mode for ever. The first line of defense under such circumstances is the thread dump.
Run the program from the command prompt and when the CPU peaks take a thread dump. You can get a thread dump by pressing the following at the command prompt: Ctrl+\ for unices or Ctrl+Break for windows machines. If you are running your application as a back ground process in unix, you could execute kill -SIGQUIT <pid> from another command prompt. The above signals the VM to generate a full thread dump. Sun’s VM prints the dump on the error stream while IBM’s JDK generates a new file with the thread dump every time you send the signal. In our case the thread dump would look something like this:
C:\learn\classes>java Test
Full thread dump Java HotSpot(TM) Client VM (1.4.2_04-b05 mixed mode):

"Signal Dispatcher" daemon prio=10 tid=0x0091db28 nid=0x744 waiting on condition [0..0]

"Finalizer" daemon prio=9 tid=0x0091ab78 nid=0x73c in Object.wait() [1816f000..1816fd88]
        at java.lang.Object.wait(Native Method)
        - waiting on <0x10010498> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        - locked <0x10010498> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(Unknown Source)
        at java.lang.ref.Finalizer$FinalizerThread.run(Unknown Source)

"Reference Handler" daemon prio=10 tid=0x009196f0 nid=0x738 in Object.wait() [1812f000..1812fd88]
        at java.lang.Object.wait(Native Method)
        - waiting on <0x10010388> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Unknown Source)
        at java.lang.ref.Reference$ReferenceHandler.run(Unknown Source)
        - locked <0x10010388> (a java.lang.ref.Reference$Lock)

"main" prio=5 tid=0x00234998 nid=0x4c8 runnable [6f000..6fc3c]
        at Test.findNewLine(Test.java:13)
        at Test.<init>(Test.java:4)
        at Test.main(Test.java:20)

"VM Thread" prio=5 tid=0x00959370 nid=0x6e8 runnable

"VM Periodic Task Thread" prio=10 tid=0x0023e718 nid=0x74c waiting on condition
"Suspend Checker Thread" prio=10 tid=0x0091cd58 nid=0x740 runnable
The thread dump generated here is on Sun’s JDK 1.4.2. Though the output differs from version to version and from vendor to vendor, the basic structure is the same. The output is somewhat like going over all the threads and doing a Thread.dumpStack in each of them. In this case we can see that, at the time we took the thread dump, there were seven threads:
  1. Signal Dispatcher
  2. Finalizer
  3. Reference Handler
  4. main
  5. VM Thread
  6. VM Periodic Task Thread
  7. Suspend Checker Thread 
Each thread name is followed by whether the thread is a daemon thread or not. Then comes prio the priority of the thread [ex: prio=5]. I am not sure what the tid and nid are. My best guess is that they are the Java thread id and the native thread id. Would love if someone could comment on that. Then what follows the state of the thread. It is either:
  • Runnable [marked as R in some VMs]: This state indicates that the thread
    is either running currently or is ready to run the next time the OS thread
    scheduler schedules it. 
  • Suspended [marked as S in some VMs]: I presume this indicates that the
    thread is not in a runnable state. Can some one please confirm?!
  • Object.wait() [marked as CW in some VMs]: indicates that the thread is
    waiting on an object using Object.wait()
  • waiting for monitor entry [marked as MW in some VMs]: indicates that the
    thread is waiting to enter a synchronized block
What follows the thread description line is a regular stack trace. 

Debugging run away CPU

When we are trying to debug a run away CPU, as in this case, what we need to look at is the set of Runnable threads  in the thread dump. The question to ask is: What was the thread which was consuming CPU doing? At the instant we took the above thread dump, the thread was at line 13 of Test.java. Well … looks like it was checking the condition for the while loop. But eventually it should have returned right?! So we take a few more thread dumps. Each time it shows us the thread is within the while loop. This definitely indicates from the first time you took a dump to the last time you took a dump, the thread never got out of the loop. The problem is narrowed down that loop. Putting the loop under the magnifying glass, we realize that the counter i was never being incremented.
Well … if you have a single class in your application it is no big deal! But when you have gazillions of classes, narrowing down the problem to a single loop within single class is a big saver! I have found this a useful tool even when I am using a debugger. It helps me choose a good location to set my first break point!

Debugging performance issues

Its the night before the release and your application is not performing good enough. You really don’t have enough time to run the app through a profiler. Take heart! Like Ramesh says … there are always some low hanging fruits! The way a java profiler works is, it takes snapshots of what the CPU was doing at frequent intervals and generates a statistical report on where most of the CPU time was being spent during the run. If your application is performing so poorly that you could take say 10-12 thread dumps before an operation completes, you would get a rough idea of distribution of CPU time. Some of the easy kills I can think of:
  • Symptom: High CPU consumption and poor response time

    Thread dump profile: Most of the dumps show the same thread in the same method or same class

    Solution: The method/class is the one which is definitely taking a lot of CPU. See if you can optimize these calls. Some of the REALLY easy kills we have had in this category is using a Collection.remove(Object) where the backend collection is a List. Change the backed collection to be a HashSet. A word of caution though: There have been times when the runnable threads are innocent and the GC is the one consuming the CPU.
  • Symptom: Low CPU consumption most of which is kernel time and poor response time

    Thread dump profile: Most thread dumps have the runnable threads performing some IO operations

    Solution: Most likely your application is IO bound. If you are reading a lot of files from the disc, see if you can implement Producer-Consumer pattern. The Producer can perform the IO operations and Consumers do the processing on the data which has been read by the producer. If you notice that most IO operations are from the data base driver, see if you can reduce the number of queries to the database or see if you can cache the results of the query locally.
  • Symptom: Medium/Low CPU consumption in a highly multithreaded application

    Thread dump profile: Most threads in most thread dumps are waiting for a monitor on same object

    Solution: The thread dump profile says it all. See if you can: eliminate the need for synchronization [using ThreadLocal/Session-scopeobjects] or reduce the amount of code being executed within the synchronized block.
  • Symptom: Medium/Low CPU consumption in a highly multithreaded application

    Thread dump profile: Most threads in most thread dumps are waiting for a resource

    Solution: If all the threads are choked for resources, say waiting on the pool to create EJB-bean objects/DB Connection objects, see if you can increase the pool size.

Debugging “hang” problems

A textbook case of deadlock is the easiest to debug with the newer JDKs. At the end of the thread dump you will find something like this:
Found one Java-level deadlock:
=============================
"Thread-1":
  waiting to lock monitor 0x0091a27c (object 0x140fa790, a java.lang.Class),
  which is held by "Thread-0"

"Thread-0":
  waiting to lock monitor 0x0091a25c (object 0x14026800, a java.lang.Class),
  which is held by "Thread-1"

Java stack information for the threads listed above:
===================================================
"Thread-1":
        at Deadlock$2.run(Deadlock.java:48)
        - waiting to lock <0x140fa790> (a java.lang.Class)
        - locked <0x14026800> (a java.lang.Class)
"Thread-0":
        at Deadlock$1.run(Deadlock.java:33)
        - waiting to lock <0x14026800> (a java.lang.Class)
        - locked <0x140fa790> (a java.lang.Class)

Found 1 deadlock.
But many a times we come across hang’s which are not deadlocks. One thing that easily comes to my mind is a resource limit. For example in an EJB container you have set the maximum bean pool size to 1000. Now say two threads have started executing a finder each returning a collection of 1000 odd beans. Assuming a decent CPU time slice distribution it could happen that the first thread iterates over 500 beans and the next thread iterates over the 500 beans. At this moment both the threads need more beans to proceed further. However the container will not create new beans as the bean pool limit has been reached. So both the threads wait for some beans to be release to the pool … which is not going to happen. We have a hung app here…. however it is not a java-level deadlock. It is an artificial deadlock introduced due to resource limitation.
When your app is not responding and your CPU consumption is 0%, take a thread dump. If it does not have a java level dead lock, then take multiple thread dumps. If all of them show that the threads are waiting for resources [EJBs or DBConnections] see if you can increase the pool limit or decrease the number of resources required within a transaction. 

Finally

Thread Dumps and stackTraces are really good tools … they may not replace a debugging/profiling tools but are definitely good starting points and huge time savers. Unfortunately, I think they are undersold. Classes don’t teach you about them, Books don’t talk about them and tools don’t support them. I mean I can run any class from my IDE. I has buttons to Start/Pause and Stop the app from within the IDE. But why can’t I have a button for “Generate full Thread dump”. Every time I need to generate a thread dump, I have to rerun the application from
command line.
Well … maybe things are not so bad after all. What if the IDEs don’t support generation of a thread dump?! Most of them now open up the file and line number if you double click on a line in the exception stack trace obtained on runninga program! And what if the books don’t talk about it? People like Ashman make sure anyone joining the support team gets their dope on thread dump from me! ;)