Showing posts with label runtime. Show all posts
Showing posts with label runtime. Show all posts

Tuesday, 24 May 2011

Java shutdown hooks

Java allows you to add shutdown hooks to your code. A shutdown hook is simply a thread that has been left in the initialized state. When your JVM is about to shutdown, the shutdown hook thread kicks in. The finalization processes of java objects run after the shutdown hooks complete. The JVM allows you to register more than one shutdown hook.

public class Task
{
public static void main(String[] args)
{
Runtime runtime = Runtime.getRuntime();
Thread thread = new Thread(new ShutDownListener());
runtime.addShutdownHook(thread);
someProcess();
}

private static void someProcess()
{
try
{
System.out.println("I am busy");
Thread.sleep(2000);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
}
}

class ShutDownListener implements Runnable
{
@Override
public void run()
{
System.out.println("I am shutting down");
}
}


The Task class is a simple class that runs a process. Once this process finishes up, we want the JVM to run a shutdown hook to notify us that the JVM is shutting down. When this program is run, the output is

I am busy
I am shutting down


The shutdown hook still executes. So the hook will execute even if there are errors / exceptions in the main program. What happens when the hook itself throws an error / exception ?. The uncaught exception will by default be printed to System.err and propagated to the VM. The behavior is comparable to a thread encountering an uncaught exception.

It seems pretty robust. However the shutdown hook is not guaranteed to execute. If a user closes the app abruptly or the VM crashes, or you click on the little red button on the eclipse console view, the shutdown hook will not run. It is not a good idea to use a shutdown hook to release critical resources (I have seen some code snippets that do this). It might end up not running and cause damage. The shutdown hook will execute only on normal termination or orderly shutdown.

Use the shutdown hook if you would like to do trivial operations with it. You can write code inside the hook that can clean up after the program (say delete a temporary file). Or write a bye bye message. The code inside the hook should not do critical things like release DB connections that your program acquired. Doing something like that is asking for trouble, since this code may never run.

Also keep in mind that hooks run concurrently. Each hook is registered as a Thread with the VM and each Thread will run in parallel with the other hooks. If the hooks synchronize over resources incorrectly you will end up dead locking the application.

The hooks also need to finish up quickly. If they do not, that poses a problem. The application will wait for ever to exit gracefully.

So now you know what shutdown hooks are and how to use them, if you ever need to.

In Summary


  • Do not write shutdown hooks to do critical tasks
  • Make sure your shut down hooks complete quickly
  • Consider using one shutdown hook instead of several. If you decide to use several shutdown hooks, make their activities thread safe.
  • Hook code flow should not depend on the method in which the application was shutdown. How an application terminates is never guaranteed.

Monday, 9 May 2011

How to run external programs by using Java ProcessBuilder class?

The class java.lang.ProcessBuilder, in Java 1.5, is used to create operating system processes. Each process builder manages these process attributes : (See Java API Document)

  • a command, a list of strings which signifies the external program file to be invoked and its arguments, if any. Which string lists represent a valid operating system command is system-dependent. For example, it is common for each conceptual argument to be an element in this list, but there are operating systems where programs are expected to tokenize command line strings themselves - on such a system a Java implementation might require commands to contain exactly two elements.
  • an environment, which is a system-dependent mapping from variables to values. The initial value is a copy of the environment of the current process (see System.getenv()).
  • a working directory. The default value is the current working directory of the current process, usually the directory named by the system property user.dir.
  • a redirectErrorStream property. Initially, this property is false, meaning that the standard output and error output of a subprocess are sent to two separate streams, which can be accessed using the Process.getInputStream() and Process.getErrorStream() methods. If the value is set to true, the standard error is merged with the standard output. This makes it easier to correlate error messages with the corresponding output. In this case, the merged data can be read from the stream returned by Process.getInputStream(), while reading from the stream returned by Process.getErrorStream() will get an immediate end of file.

The java.lang.ProcessBuilder and java.lang.Process classes are available for executing and communicating with external programs. With an instance of the java.lang.ProcessBuilder class, it can execute an external program and return an instance of a subclass of java.lang.Process. The class Process provides methods for performing input from the process, performing output to the process, waiting for the process to complete, checking the exit status of the process, and destroying (killing) the process.

//running a 
String[] command = {"CMD", "/C", "dir"};
ProcessBuilder probuilder = new ProcessBuilder( command );

//You can set up your work directory
probuilder.directory(new File("c:\\vaanidemo"));

Process process = probuilder.start();

//Read out dir output
InputStream is = process.getInputStream();
InputStreamReader isr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(isr);
String line;
System.out.printf("Output of running %s is:\n",
Arrays.toString(command));
while ((line = br.readLine()) != null) {
System.out.println(line);
}

//Wait to get exit value
try {
int exitValue = process.waitFor();
System.out.println("\n\nExit Value is " + exitValue);
} catch (InterruptedException e) {
e.printStackTrace();
}

Saturday, 12 March 2011

Runtime Exceptions--The Controversy

Because the Java language does not require methods to catch or specify runtime exceptions, it's tempting for programmers to write code that throws only runtime exceptions or to make all of their exception subclasses inherit from RuntimeException. Both of these programming shortcuts allow programmers to write Java code without bothering with all of the nagging errors from the compiler and without bothering to specify or catch any exceptions. While this may seem convenient to the programmer, it sidesteps the intent of Java's catch or specify requirement and can cause problems for the programmers using your classes.
InputFile.java:8: Warning: Exception
java.io.FileNotFoundException must be caught, or it must be
declared in throws clause of this method.
fis = new FileInputStream(filename);
^

Why did the Java designers decide to force a method to specify all uncaught checked exceptions that can be thrown within its scope? Because any exception that can be thrown by a method is really part of the method's public programming interface: callers of a method must know about the exceptions that a method can throw in order to intelligently and conciously decide what to do about those exceptions. The exceptions that a method can throw are as much a part of that method's programming interface as its parameters and return value.

Your next question might be: "Well then, if it's so good to document a method's API including the exceptions that it can throw, why not specify runtime exceptions, too?"

Runtime exceptions represent problems that are detected by the runtime system. This includes arithmetic exceptions (such as when dividing by zero), pointer exceptions (such as trying to access an object through a null reference), and indexing exceptions (such as attempting to access an array element through an index that is too large or too small).

Runtime exceptions can occur anywhere in a program and in a typical program can be very numerous. Typically, the cost of checking for runtime exceptions exceeds the benefit of catching or specifying them. Thus the compiler does not require that you catch or specify runtime exceptions, although you can.

Checked exceptions represent useful information about the operation of a legally specified request that the caller may have had no control over and that the caller needs to be informed about--for example, the file system is now full, or the remote end has closed the connection, or the access privileges don't allow this action.

What does it buy you if you throw a RuntimeException or create a subclass of RuntimeException just because you don't want to deal with specifying it? Simply, you get the ability to throw an exception without specifying that you do so. In other words, it is a way to avoid documenting the exceptions that a method can throw. When is this good? Well, when is it ever good to avoid documenting a method's behavior? The answer is "hardly ever."


Rules of Thumb:



  • A method can detect and throw a RuntimeException when it's encountered an error in the virtual machine runtime. However, it's typically easier to just let the virtual machine detect and throw it. Normally, the methods you write should throw Exceptions, not RuntimeException.

  • Similarly, you create a subclass of RuntimeException when you are creating an error in the virtual machine runtime (which you probably aren't). Otherwise you should subclass Exception.

  • Do not throw a runtime exception or create a subclass of RuntimeException simply because you don't want to be bothered with specifying the exceptions your methods can throw.

Wednesday, 22 December 2010

Getting java run time memory statistics

   public static void logJVMStatistics()
    {
        System.out.println("JVM Statistics -- Max : " + Runtime.getRuntime().maxMemory() + "; " +
                            "Free: " + Runtime.getRuntime().freeMemory() + "; " +
                            "Total: " + Runtime.getRuntime().totalMemory());
    }