Loading Java Classes from a Remote Machine
An Introduction |
Prof. David Bernstein |
Computer Science Department |
bernstdh@jmu.edu |
import java.io.FileOutputStream; import java.io.InputStream; import java.io.IOException; import java.net.URL; /** * An object that is responsible for retrieving classes from an * HTTP server and writing them to a local file * * @version 1.0 * @author Prof. David Bernstein, James Madison University */ public class HTTPClassRetriever { private String uri; public static final String EXT = ".class"; /** * Explicit Value Constructor * * @param uri The host and path to load from */ public HTTPClassRetriever(String uri) { this.uri = uri; } /** * Retrieve the class using HTTP * * @param name The name of the class (without the extension) * @param The bytes that comprise the class */ public void retrieveClass(String name) throws IOException { byte[] bytes; FileOutputStream out; bytes = requestBytes(name); out = new FileOutputStream(name+EXT); out.write(bytes); } /** * Request the bytes in the class using an HTTP GET request * * @param name The name of the class (without the extension) * @param The bytes that comprise the class */ private byte[] requestBytes(String name) throws IOException { byte[] bytes; InputStream in; URL u; u = new URL(uri + name + EXT); in = u.openStream(); bytes = new byte[in.available()]; in.read(bytes); return bytes; } }
import java.lang.reflect.*; /** * Retrieve a class containing an application * (i.e., a class with a void main(String[] args)) * from an HTTP server, save it locally, and execute it. * Example: * * java HTTPApplicationLauncher https://w3.cs.jmu.edu/bernstdh/web/common/lectures/javaexamples/classloader/ Example * * @version 1.0 * @author Prof. David Bernstein, James Madison University */ public class HTTPApplicationLauncher { /** * The entry point of this application * * @param args The command-line arguments (URL, class) */ public static void main(String[] args) throws Exception { Class appClass; Class[] parameters; HTTPClassRetriever retriever; int realArgsLength; Method mainMethod; Object[] oargs; String[] realArgs; // Construct an HTTPClassRetriever that retrieves from // the host and path in args[0] retriever = new HTTPClassRetriever(args[0]); // Retrieve and save the class in args[1] retriever.retrieveClass(args[1]); // Get the Class appClass = Class.forName(args[1]); // We need the signature of the main method which includes // the class of the argument. The easiest way to do // this is to use reflection and get the class of args parameters = new Class[1]; parameters[0] = args.getClass(); // Get the main method mainMethod = appClass.getDeclaredMethod("main", parameters); // Copy the remaining command line arguments realArgsLength = Math.max(args.length - 2, 0); realArgs = new String[realArgsLength]; if (realArgsLength > 0) System.arraycopy(args, 2, realArgs, 0, realArgsLength); oargs = new Object[]{realArgs}; // Initialize with realArgs // Invoke main // Note: First argument is null because it's static mainMethod.invoke(null, oargs); } }
import java.io.InputStream; import java.io.IOException; import java.net.URL; /** * An object that is responsible for loading classes from an * HTTP server. * * @version 1.0 * @author Prof. David Bernstein, James Madison University */ public class HTTPClassLoader extends ClassLoader { private String uri; public static final String EXT = ".class"; /** * Explicit Value Constructor * * @param uri The host and path to load from */ public HTTPClassLoader(String uri) { this.uri = uri; } /** * Finds the class with the specified name * * @param name The name of the class (without extension) * @return The resulting Class object */ protected Class findClass(String name) throws ClassNotFoundException { byte[] bytes; Class c; bytes = null; try { bytes = requestBytes(name); c = defineClass(name, bytes, 0, bytes.length); if (c == null) throw new ClassNotFoundException(name); } catch (IOException ioe) { throw new ClassNotFoundException(name); } return c; } /** * Request the bytes in the class using an HTTP GET request * * @param name The name of the class (without the extension) * @param The bytes that comprise the class */ private byte[] requestBytes(String name) throws IOException { byte[] bytes; InputStream in; URL u; u = new URL(uri + name + EXT); in = u.openStream(); bytes = new byte[in.available()]; in.read(bytes); return bytes; } }
import java.lang.reflect.*; /** * Load an application (i.e., a class with a void main(String[] args)) * from an HTTP server and execute it. * * Example: * * java HTTPApplicationLoader https://w3.cs.jmu.edu/bernstdh/web/common/lectures/javaexamples/classloader/ OtherExample Fred * * @version 1.0 * @author Computer Science Department, James Madison University */ public class HTTPApplicationLoader { /** * The entry point of this application * * @param args The command-line arguments (URL, class) */ public static void main(String[] args) throws Exception { Class appClass; Class[] parameters; HTTPClassLoader classLoader; int realArgsLength; Method mainMethod; Object[] oargs; String[] realArgs; // Construct an HTTPClassLoader that retrieves from // the host and path in args[0] classLoader = new HTTPClassLoader(args[0]); //setContextClassLoader(classLoader); // Load the class in args[1] // Note: To get an instance use appClass.newInstance() appClass = classLoader.loadClass(args[1]); // We need the signature of the main method which includes // the class of the argument. The easiest way to do // this is to use reflection and get the class of args parameters = new Class[1]; parameters[0] = args.getClass(); // Get the main method mainMethod = appClass.getDeclaredMethod("main", parameters); // Copy the remaining command line arguments realArgsLength = Math.max(args.length - 2, 0); realArgs = new String[realArgsLength]; if (realArgsLength > 0) System.arraycopy(args, 2, realArgs, 0, realArgsLength); oargs = new Object[]{realArgs}; // Initialize with realArgs // Invoke main // Note: First argument is null because it's static mainMethod.invoke(null, oargs); } }