Environment, Virtual Machine, Class Loaders

How can I execute an operating system command from a Java application? (e.g. the "dir" or "ls" command)


(From
Marty Hall's Java Page)
import java.io.*;

/** A class that eases the pain of running external processes from
 *  applications.
 *  Lets you run a program three ways:
 *  
    *
  1. exec: Execute the command, returning immediately * even if the commmand is still running. This would be appropriate * for printing a file. *
  2. execWait: Execute the command, but don't return * until the command finishes. This would be appropriate for * sequential commands where the first depends on the second * having finished (e.g. javac followed by * java). *
  3. execPrint: Execute the command and print the output. * This would be appropriate for the UNIX command ls. *
* Note that, at least as of JDK 1.0, the path is not taken into * account, and you must specify the full pathname to * the command, and shell builtin commands will not work. * For instance, on UNIX the above three examples might look like: *
    *
  1. Exec.exec("/usr/ucb/lpr Some-File"); *
  2. Exec.execWait("/usr/local/bin/javac Foo.java"); * Exec.execWait("/usr/local/bin/java Foo"); *
  3. Exec.execPrint("/usr/bin/ls -al"); *
* The latest version of the source is at * * http://www.apl.jhu.edu/~hall/java/Exec.java. The latest * version of the documentation is at * * http://www.apl.jhu.edu/~hall/java/Exec.html. *

* No warranty of any kind is provided (obviously :-). * Permission is granted to use and/or modify the class file or sources * for any purpose. *

* 5/96 Marty Hall: *

* * @author Marty Hall (hall@apl.jhu.edu) * @version 0.9 5/9/96 */ public class Exec { //------------------------------------------------------------------- private static boolean verbose = true; /** Determines if the Exec class should print which * commands are being executed, and print error messages if * a problem is found. Default is true. * * @param verboseFlag true: print messages. False: don't. */ public static void setVerbose(boolean verboseFlag) { verbose = verboseFlag; } //------------------------------------------------------------------- /** Starts a process to execute the command. Returns immediately, * even if the new process is still running. * * @param command The full pathname of the command to be * executed. No shell builtins or shell meta-chars allowed. * @return false if a problem is known to occur, but since this * returns immediately, problems aren't usually found. * Returns true otherwise. */ public static boolean exec(String command) { return(exec(command, false, false)); } //------------------------------------------------------------------- /** Starts a process to execute the command. Waits for the process to * finish before returning. * * @param command The full pathname of the command to be * executed. No shell builtins or shell meta-chars allowed. * @return false if a problem is known to occur, either due to * an exception or from the subprocess returning a non-zero value. * Returns true otherwise. */ public static boolean execWait(String command) { return(exec(command, false, true)); } //------------------------------------------------------------------- /** Starts a process to execute the command. Prints all output the * command gives. * * @param command The full pathname of the command to be * executed. No shell builtins or shell meta-chars allowed. * @return false if a problem is known to occur, either due to * an exception or from the subprocess returning a non-zero value. * Returns true otherwise. */ public static boolean execPrint(String command) { return(exec(command, true, false)); } //------------------------------------------------------------------- private static boolean exec(String command, boolean printResults, boolean wait) { if (verbose) { printSeparator(); System.out.println("Executing '" + command + "'."); } try { Process p = Runtime.getRuntime().exec(command); if(printResults) { DataInputStream commandResult = new DataInputStream(new BufferedInputStream(p.getInputStream())); String s = null; try { while ((s = commandResult.readLine()) != null) System.out.println("Output: " + s); if (p.exitValue() != 0) { if (verbose) printError(command + " -- p.exitValue() != 0"); return(false); } } catch (Exception e) {} } else if (wait) { try { // Doesn't always wait. If the previous exec was a print-the-results // version, then this will NOT wait unless there is a // System.out.println call here! Odd... System.out.println(" "); int returnVal = p.waitFor(); if (returnVal != 0) { if (verbose) printError(command); return(false); } } catch (Exception e) { if (verbose) printError(command, e); return(false); } } } catch (Exception e) { if (verbose) printError(command, e); return(false); } return(true); } //------------------------------------------------------------------- private static void printError(String command, Exception e) { System.out.println("Error doing exec(" + command + "): " + e.getMessage()); System.out.println("Did you specify the full pathname?"); } private static void printError(String command) { System.out.println("Error executing '" + command + "'."); } //------------------------------------------------------------------- private static void printSeparator() { System.out.println ("===================================================================="); } //------------------------------------------------------------------- }
(Submitted by Rich Morgan)
Following is some code I found in the comp.lang.java newsgroup. Entered and tried it out. It works, but about every other time it gives some standard out or standard error msgs indicating that a process was started and terminated with an exit code.

The try - catch clause must be used since the exec command throws exceptions. Also you must put a full path name on the command that you wish to exec. This does not make sence to me because execing /usr/bin/env shows that the PATH environment variable lists paths where various commands can be found. For some reason the implementation of the exec method does not use the current PATH env variable.

Also note that wild card commands such as "ls /usr/* " do not work unless you invoke a shell to run the command:

/usr/bin/sh -c ls /usr/*

The original news group question was asked by brainec@yoyo

tested code follows:

import java.io.*;

public class ls {
        public static void main (String args[]) {
        try     {
                Process p  = Runtime.getRuntime().exec("/usr/bin/ls");
                DataInputStream dis = new DataInputStream(
                new BufferedInputStream(p.getInputStream()));
 
                String s = null;
                while ((s = dis.readLine()) != null) {
                        System.out.println(s);
                        }
                } catch (Exception e){
                        System.out.println("the detailed msg:" + e);
                        }
        }
}

How do I load and instantiate a class under program control?

"How do I use Class.newInstance() to dynamically instatiate objects?"

(Submitted by Lorenzo Patocchi)
The main of this pseudo application is to run a method of an interface, but not from a fixed class, this mean loading and using a class which the name is not known at the compilation.

class1 and class2 are two classes implementing the same interface,

public class class1 implements genericclass{
	public class1(){;}
	public void method1(){
		System.out.println("Hello, im class1 running method 1");
	}
}
public class class2 implements genericclass{
	public class2(){;}
	public void method1(){
		System.out.println("Hello, im class2 running method 1");
	}
}
Here is the interface ...
public interface genericclass{
	public void   method1();
}
Finally this is the dynamic class loader:
public class dynamicload{
	public static final String usage = "Usage: java dinamicload ";
	public String className;
	// WARNING: is important that this variable is declared
	//	    as static !
	public static genericclass genclass;
	
	public static void main(String args[]) {
		//Class c;
		//Object obj;
	
		if (args.length ==0){
			System.out.println(usage);
			return;
		}
		System.out.println("Class to Load: "+args[0]);
		
		try{
			// I just used a shortcut instantiating genclass
			//c = Class.forName(args[0]);
			//obj = c.newInstance();
			//System.out.println("Instantiated " + obj.getClass().getName());
			genclass = (genericclass) Class.forName(args[0]).newInstance();
			genclass.method1();

		}catch (InstantiationException instex){
			System.out.println(instex);
		}catch (IllegalAccessException illaccex){
			System.out.println(illaccex);
		}catch (ClassNotFoundException classnotfound){
			System.out.println(classnotfound);
			return;
		}	
	}
}
NOTE: "class1" or "class2" NEVER appear in dynamic class.

Now You can use it in this way:

% java dynamic class1
Class to Load: class1
Hello, im class1 running method 1

% java dynamic class2
Class to Load: class2
Hello, im class2 running method 1
(Submitted by Cliff Berg)
Here is a complete example which creates a simple class loader, and also tests out some of the methods in the Class class.

In one file, define the class you wish to dynamically instantiate...

import java.applet.*;

public class MyClass extends Applet
{
	public MyClass()
	{
	}

	public void init() 
	{
		System.out.println("MyClass.init()");
	}
}

Here is the code that instantiates and uses that class...

import java.awt.*;
import java.applet.*;
import java.io.*;
import java.util.*;

class ExtendedButton extends Button
{
	ExtendedButton(String s)
	{
		super(s);
	}

	public boolean handleEvent(Event e)
	{
		System.out.println("ExtendedButton.handleEvent()");
		return super.handleEvent(e);
	}
}

class MyClassLoader extends ClassLoader
{
	public Class loadClass(String name, boolean resolve)
		// Define the class loader's behavior
	throws
		java.lang.ClassNotFoundException
	{
		// Here we could call the browser's class loader, or define
		// our own...

		// attempt to read the class from the current directory
		try
		{
		FileInputStream fis = new FileInputStream(name + ".class");
		File f = new File(name + ".class");
		byte bytes[] = new byte[(int)(f.length())];
		int n = fis.read(bytes);
		Class c = defineClass(bytes, 0, bytes.length);
		System.out.println("Read class, size=" + String.valueOf(bytes.length));
		if (resolve) resolveClass(c);
		return c;
		}
		catch (NullPointerException e)
		{
		}
		catch (java.io.FileNotFoundException e)
		{
		}
		catch (java.io.IOException e)
		{
		}
		return null;
	}
}

public class TestLoadClass extends Applet
{
    public void init()
    {
    	try {

		ExtendedButton eb = new ExtendedButton("ExtendedButton");
		add(eb);

		//
		// Try out some Class methods...
		//

		// Print the name of the ExtendedButton class
		System.out.println("Instantiated " + eb.getClass().getName());

		// Print the name of the ExtendedButton class
		Class bc = Class.forName("ExtendedButton");
		System.out.println("Obtained class descriptor for " + bc.getName());

		// Get ExtendedButton's superclass
		Class ebc = bc.getSuperclass();
		System.out.println("ExtendedButton superclass: " + ebc.getName());

		
		// Load the MyClass class
		MyClassLoader cl = new MyClassLoader();
		String className = "MyClass";
		Class c = cl.loadClass(className, true);
		if (c == null) throw new ClassNotFoundException();
		System.out.println("Loaded " + c.getName());

		// Instantiate a MyClass
		Object o = c.newInstance();
		System.out.println("Instantiated " + o.getClass().getName());
		if (o instanceof MyClass)
			System.out.println("o is ok");
		else System.out.println("o not ok");
		Object oc = new MyClass();
		if (! (oc instanceof MyClass))
		{
			System.out.println("Error: class created as MyClass is "
				+ oc.getClass().getName());
		}
		Applet ac = new MyClass();
		if (! (ac instanceof MyClass))
		{
			System.out.println("Error: class created as MyClass is "
				+ ac.getClass().getName());
		}
		MyClass mc = new MyClass();
		if (! (mc instanceof MyClass))
		{
			System.out.println("Error: class created as MyClass is "
				+ mc.getClass().getName());
		}

		//MyClass v = (MyClass)o;	<- this fails in Beta 2, so use the
		//									next line instead
		Applet ap = (Applet)o;
		if (ap instanceof Applet)
			System.out.println("ap is Applet");	// this executes
		else System.out.println("ap not Applet");

		ap.init();

		}
		catch (java.lang.ClassNotFoundException e)
		{
		System.out.println("Exception...ClassNotFoundException");
		}
		catch (java.lang.IllegalAccessException e)
		{
		System.out.println("Exception...IllegalAccessException");
		}
		catch (java.lang.InstantiationException e)
		{
		System.out.println("Exception...InstantiationException");
		}

    }

    public void start() {}

    public void stop() {}

    public boolean handleEvent(Event e)
    {
		if (e.id == Event.WINDOW_DESTROY)
		{
	    	System.exit(0);
		}
		return false;
    }

    public static void main(String args[])
    {
		// Create a Frame
		MainFrame f = new MainFrame("TestLoadClass");

		// Instantiate the Applet
		TestLoadClass applet = new TestLoadClass();

		// Init and start the Applet
		applet.init();
		applet.start();

		// Add the Applet to the Frame
		f.add("West", applet);

		// Resize and show the Frame
		f.resize(300, 300);
		f.show();
    }
}


class MainFrame extends Frame
{
    public MainFrame(String s) {
      super(s);
    }

    // Handle close events by simply exiting
    public boolean handleEvent(Event e) {
	if (e.id == Event.WINDOW_DESTROY) {
	    System.exit(0);
	}
	return false;
    }
}




How can a new SecurityManager be used to set different security policies for an application?



How do I get the CLASSPATH variable (and other system variables)?


(Submitted by Cliff Berg)
To get the CLASSPATH variable, do this:
   String classpath = System.getProperty("java.class.path");
You can get all the system variables (and see which ones are available) by doing:
Properties p = System.getProperties();
System.out.println(p);
On Windows 95, the variables available this way on my system are (OK - so I haven't moved up to JDK 1.0 yet):
java.home=C:\JAVABETA2\JAVA\BIN\.., 
awt.toolkit=sun.awt.win32.MToolkit, 
java.version=1.0beta2, 
file.separator=\, 
line.separator=, 
java.vendor=Sun Microsystems Inc., 
user.name=cliff, 
os.arch=x86, 
os.name=Windows 95, 
java.vendor.url=http://www.sun.com/, 
user.dir=C:\test, 
java.class.path=.\;.\classes\;c:\JavaBeta2\java\classes\,
java.class.version=45.3, 
os.version=4.0, 
path.separator=;, 
user.home=C:\JAVABETA2\JAVA\BIN\..