Run outside class files from a running Java program (6/7/99)

The JavaWorld experts answer your most pressing Java questions -- every week

Q: How can I run outside class files from a running Java program? I'm working on a Java IDE and need to execute Java classes that the compiler generates in a portable form.

A: If you're trying to run the class files from the same process, you should use reflection to find the main method at runtime, then invoke it.

Let's say you wanted to invoke the following class dynamically:

public class Invoked {
public static void main(String[] args) {
System.out.println("hello there!");
 }
}

You could write this next class to find the above class's mainmethod and then invoke it:

import java.lang.reflect.*;
public class Invoker {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.err.println("Usage: java Invoker ");
      System.exit(1);
    }
    Class[] argTypes = new Class[1];
    argTypes[0] = String[].class;
    try {
      Method mainMethod = Class.forName
      (args[0]).getDeclaredMethod("main",argTypes);
      Object[] argListForInvokedMain = new Object[1];
      argListForInvokedMain[0] = new String[0];
      // Place whatever args you
      // want to pass into other
      // class's main here.
      mainMethod.invoke(null, 
      // This is the instance on which you invoke
      // the method; since main is static, you can pass
      // null in.
      argListForInvokedMain);
      }
      catch (ClassNotFoundException ex) {
        System.err.println("Class "+args[0]+" 
        not found in classpath.");
      }
      catch (NoSuchMethodException ex) {
        System.err.println("Class "+args[0]+" 
        does not define public static 
        void main(String[])");
      }
      catch (InvocationTargetException ex) {
        System.err.println("Exception while 
        executing "+args[0]+":"+ex.getTargetException());
      }
      catch (IllegalAccessException ex) {
        System.err.println("main(String[]) in 
        class "+args[0]+" is not public");
      }
   }
}

To run the invoker, type:

java Invoker Invoked

This will simply execute the main method of Invoked in the same process (and, in fact, the same thread) as the one from which you invoked it. You can put this in a different thread if you like.

If you're trying to invoke the class in a different process, you should use the java.lang.Runtime class. If, for example, you were trying to invoke the same class as above, your invoker might look like this:

public class InvokerFromSeparateProcess {
  public static void main(String[] args) {
    if (args.length != 1) {
      System.err.println("Usage: java
      InvokerFromSeparateProcess ");
      System.exit(1);
    }
    try {
      Process p = Runtime.getRuntime().exec
      ("java "+args[0]);
    }
    catch (java.io.IOException ex) {
      System.err.println("Problems invoking class "+args[0]+": "+ex);
    }
  }
}

To run it, type:

java InvokerFromSeparateProcess Invoked

You may notice that the output of Invoked disappears. This is because the new process's standard output stream doesn't automatically go to stdout.

You can get the process's standard output stream by calling p.getInputStream(). To use the information that was sent to standard output, you have to be able to read it -- which is why you get it from the process as an input stream.

Random Walk Computing is the largest Java/CORBA consulting boutique in New York, focusing on solutions for the financial enterprise. Known for their leading-edge Java expertise, Random Walk consultants publish and speak about Java in some of the most respected forums in the world.