Revolutionary RMI: Dynamic class loading and behavior objects

Find out how RMI can help you define extensible, distributed object-oriented frameworks

1 2 3 Page 3
Page 3 of 3

Step 1. Start the HTTP process that will serve the class files to remote RMI objects in the dynamic/viewer directory. This server will listen on port 8002.

> start java httpd 8002

Step 2. Start the Scribble Viewer process.

> java -Djava.rmi.server.codebase=http://fred:8002/    >>>
       -Djava.security.policy=dynamic.policy    >>>
       ScribbleViewerFrame STEELRAIN

Again, don't forget to end the codebase URL with a slash (/).

Step 3. FRED's display now has a Scribble Viewer displaying the drawing and BUBBA's HTTP server console reads:

> java httpd 8001
httpd running on port: 8001
document root is: E:\dynamic\client\.
Request from STEELRAIN: ScribbleViewer_Stub.class
Request from STEELRAIN: ScribbleX.class
Request from STEELRAIN: ScribbleLine.class
Request from STEELRAIN: ScribblePoint.class
Request from FRED: ScribbleX.class
Request from FRED: ScribbleLine.class
Request from FRED: ScribblePoint.class

Security precautions

That was a long answer to a short question. And usually the same student who asked the original question asks the follow-up question: Aren't there security issues with dynamically loading code from a remote, untrusted host? As a matter of fact, many potential problems can arise. Consider this shape class:

public class ScribbleVirus implements ScribbleShape {
  public void draw(Graphics g) {
      System.exit(0);
   }
}

Now we can inject the virus into the system with this simple class:

public class PoisonPill {
   public static void main(String args[]) throws Exception {
      System.setSecurityManager(new RMISecurityManager());
      String host = "localhost";
      if (args.length > 0) {
         host = args[0];
      }
      //locate server
      String url = "rmi://"+ host + "/Scribble Server";
      ScribblePadServer server = 
                (ScribblePadServer)Naming.lookup(url);
      //create a ScribbleVirus and add to the drawing     ScribbleVirus virus = new ScribbleVirus();
      server.addShape(virus);
   }
}

This is a nasty virus because the ScribbleVirus will be delivered to the clients and promptly terminate the Java runtime all the while leaving the virus active in the Scribble Server's list of shapes. The Scribble Server will not be affected because it stores the shapes but never calls ScribbleShape.draw(). You can take several steps to protect your distributed applications from evil or clumsy classes.

The most severe form of protection offered by RMI is the java.rmi.useCodebaseOnly system property. Defining this system property tells the RMI system to load classes only from the local host's codebase. This setting will prevent the RMI system from remotely loading class files across the network. A severe but effective precaution to protect your server.

Specifying security policy files provides a more flexible mechanism for specifying dynamic class loading policies. You must be using JDK 1.2 to take advantage of this mechanism, but it provides the capability to selectively enable VM capabilities on a per-host or per-class basis, such as invoking System.exit(), listening on ports, creating threads, and accessing the filesystem. The new security model is quite extensive and is way beyond the scope of this article. For more information on this very important subject see the security links in the Resources.

Conclusion

After playing around with the code for a while, I'm sure you'll be quite excited and start running around the room looking at the havoc you can create. Serious learning at the rim of Java's capabilities and exercise too!

RMI is all about passing objects between address spaces; behavior objects and dynamic class loading represent two very important RMI capabilities that make this possible. Future articles in this column will discuss custom RMI sockets and RMI activation, two technologies that rely heavily on both capabilities. In the meantime, you can take the "jump" and add increased runtime extensibility to your distributed applications.

Note: The next Enterprise Java column will appear in the February 1999 issue of JavaWorld.

Andy Krumel graduated from the US Naval Academy and started his career as a naval aviator; however, after a series of engine fires, radio failures, and assorted other mishaps, a career in computer programming looked more long-lived. Today, Andy is the founder of K&A Software, a rapidly growing, three-year-old Silicon Valley training and consulting firm specializing in Java and distributed applications. Andy and his cohorts will do just about anything to spread the word about Java's fantastic capabilities, from speaking at conferences, to teaching corporate training classes, to even writing an article. When not pontificating, Andy is squirreled away creating solutions for one of K&A's corporate clients.

Learn more about this topic

  • Download the complete source in zip format; you will need to have JDK 1.1.x and Swing 1.1 Beta 3 release, or the JDK 1.2 Release Candidate 1 (which includes Swing) to run the code http://www.javaworld.com/jw-12-1998/enterprise/jw-12-enterprise.zip
  • Download the Java Swing Toolkit from JavaSoft http://developer.java.sun.com/developer/earlyAccess/jfc/index.html
  • Bryan Morgan's "Java 1.2 extends Java's distributed object capabilities" (JavaWorld, April 1998) provides an excellent step-by-step RMI example http://www.javaworld.com/javaworld/jw-04-1998/jw-04-distributed.html
  • Sun's online RMI tutorial offers an excellent starting point for those needing a little RMI brush up http://java.sun.com/docs/books/tutorial/rmi/index.html
  • Sun's Java security home page, with specifications whitepapers, articles, and more http://java.sun.com/security/index.html
  • Sun's RMI Web page http://www.javasoft.com/products/jdk/rmi/
  • Always go to the specification if you want to know all the details http://java.sun.com/products/jdk/1.2/docs/guide/rmi/spec/rmiTOC.doc.html
1 2 3 Page 3
Page 3 of 3