Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-6287178

SecurityManager.checkAccept(..) method extremely slow!

    XMLWordPrintable

Details

    • Bug
    • Resolution: Cannot Reproduce
    • P3
    • None
    • 5.0
    • security-libs

    Description

      FULL PRODUCT VERSION :
      java version "1.5.0_02"
      Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_02-b09)
      Java HotSpot(TM) Client VM (build 1.5.0_02-b09, mixed mode, sharing)

      ADDITIONAL OS VERSION INFORMATION :
      Microsoft Windows XP [Version 5.1.2600]

      EXTRA RELEVANT SYSTEM CONFIGURATION :
      Simple LAN, DNS Server not configured all clients configured with 192.168.0.X ip addresses.


      A DESCRIPTION OF THE PROBLEM :
         If you try to use a SecurityManager for RMI without a DNS server, checkAccept(..) method usually try to lookup DNS server for client hostnames or IP addresses. This takes long time.

         I use this permission in policy file;

      permission java.net.SocketPermission "*:1024-", "accept,connect,resolve";

      So I permit all hosts with "*". I think if I give a "*" for hostname no DNS lookups must occur. Because we don't need any hostname or ip address for this permission.


      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      Please compile following files and try to run;

      Run server with this command;

      java -Djava.security.policy=server.policy Server 192.168.0.1 1977

      And go another machine which has Windows XP on it and run client with;

      java Client 192.168.0.1 1977

      DON'T USE DNS SERVER.

      On server machine you will see; (Note: Server machine IP: 192.168.0.1)

      checkAccept(String host, int port) -> 34000 ms. -> 192.168.0.2 -> 1566
      checkAccept(String host, int port) -> 17000 ms. -> 192.168.0.2 -> 1567
      checkAccept(String host, int port) -> 17000 ms. -> 192.168.0.2 -> 1568
      checkAccept(String host, int port) -> 17016 ms. -> 192.168.0.2 -> 1568
      checkAccept(String host, int port) -> 17000 ms. -> 192.168.0.2 -> 1568
      -> sayHello called. -> clientHost=192.168.0.2 -> name='Call #1'

      On Client machine you will see; (Note: Client machine IP: 192.168.0.2)

      -> Object lookup OK: Proxy[Hello,RemoteObjectInvocationHandler[UnicastRef [liveRef: [endpoint:[192.168.0.1:1977](remote),objID:[-6c2a94f5:1037e68ebb8:-8000, 0]]]]]
      -> Lookup Time: 91001 ms.


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -
      Fast responses.
      ACTUAL -
      Very slow responses.

      ERROR MESSAGES/STACK TRACES THAT OCCUR :
      no errors, just slow responses

      REPRODUCIBILITY :
      This bug can be reproduced always.

      ---------- BEGIN SOURCE ----------
      // Hello.java ----------
      import java.rmi.Remote;
      import java.rmi.RemoteException;

      public interface Hello extends Remote {
          public String sayHello(String name) throws RemoteException;
      }

      // HelloImpl.java ----------
      import java.sql.Timestamp;
      import java.rmi.server.RemoteServer;
      import java.rmi.server.*;

      public class HelloImpl implements Hello {

          public HelloImpl() {
          }

          public String sayHello(String name) {
              String result = null;
              Timestamp timestamp = new Timestamp(System.currentTimeMillis());
              result = "Hello " + name + ". Server Time Is: " + timestamp.toString();
              String clientHost = null;
              try {
                  clientHost = RemoteServer.getClientHost();
              } catch (ServerNotActiveException ex) {
                  ex.printStackTrace();
              }
              System.out.print("-> sayHello called. -> clientHost=" + clientHost);
              System.out.println(" -> name=" + name);
              return result;
          }

      }

      // MrSeaRMISecurityManager.java ----------
      import java.rmi.RMISecurityManager;

      public class MrSeaRMISecurityManager extends RMISecurityManager {

          public MrSeaRMISecurityManager() {
          }

          public void checkConnect(String host, int port) {
              long start = 0, end = 0;
              start = System.currentTimeMillis();
              super.checkConnect(host, port);
              end = System.currentTimeMillis();
              System.out.println("checkConnect(String host, int port) -> " +
                                 (end - start) + " ms. -> " + host + " -> " + port);
          }

          public void checkConnect(String host, int port, Object context) {
              long start = 0, end = 0;
              start = System.currentTimeMillis();
              super.checkConnect(host, port, context);
              end = System.currentTimeMillis();
              System.out.println(
                      "checkConnect(String host, int port, Object context) -> " +
                      (end - start) + " ms. -> " + host + " -> " + port);
          }

          public void checkAccept(String host, int port) {
              long start = 0, end = 0;
              start = System.currentTimeMillis();
              super.checkAccept(host, port);
              end = System.currentTimeMillis();
              System.out.println(
                      "checkAccept(String host, int port) -> " + (end - start) +
                      " ms. -> " + host + " -> " + port);
          }

      }

      // Server.java ----------
      import java.rmi.Naming;
      import java.rmi.Remote;
      import java.rmi.RemoteException;
      import java.rmi.registry.Registry;
      import java.rmi.registry.LocateRegistry;
      import java.rmi.server.ExportException;
      import java.rmi.server.UnicastRemoteObject;
      import java.net.UnknownHostException;
      import java.net.MalformedURLException;
      import java.net.URL;
      import java.rmi.RMISecurityManager;

      public class Server {
          private static final String OBJECT_NAME = "Hello";
          private String host;
          private int port;
          private String fullObjectBaseURL;
          private Registry rmiRegistry;

          public Server(String host, int port) {
              this.host = host;
              this.port = port;
              this.fullObjectBaseURL = "//" + this.host + ":" + this.port + "/";
          }

          private void startRMIRegistry() throws RemoteException {
              this.rmiRegistry = null;
              try {
                  this.rmiRegistry = LocateRegistry.createRegistry(this.port);
                  System.out.println("-> rmiregistry started. Port: " + this.port);
              } catch (ExportException eex) {
                  System.out.println("-> rmiregistry was working. Port: " + this.port);
                  this.rmiRegistry = LocateRegistry.getRegistry(this.host, this.port);
              }
          }

          private void createExportAndRebindObject() throws RemoteException,
                  MalformedURLException {
              HelloImpl helloImpl = new HelloImpl();
              System.setProperty("java.rmi.server.hostname", this.host);
              Remote remoteObject = UnicastRemoteObject.exportObject(
                      (Remote) helloImpl, this.port);
              System.out.println("-> Object export OK: " + remoteObject.toString());
              String rebindName = this.fullObjectBaseURL + Server.OBJECT_NAME;
              long start = System.currentTimeMillis();
              Naming.rebind(rebindName, remoteObject);
              long end = System.currentTimeMillis();
              System.out.println("-> Object rebind OK: " + rebindName);
              System.out.println("-> Rebind Time: " + (end - start) + " ms.");
          }

          public static void main(String[] args) throws UnknownHostException,
                  RemoteException, MalformedURLException {
              String host = null;
              String port = null;
              if (args.length > 0) {
                  host = args[0];
              }
              if (args.length > 1) {
                  port = args[1];
              }
              if (port != null) {
                  try {
                      Integer.parseInt(port);
                  } catch (NumberFormatException nfex) {
                      port = null;
                  }
              }
              if (host == null || port == null) {
                  System.out.println("Usage; Server host port");
                  System.exit( -1);
              }
              Server server = new Server(host, Integer.parseInt(port));
              // set our security manager
              System.setSecurityManager(new MrSeaRMISecurityManager());
              //
              server.startRMIRegistry();
              server.createExportAndRebindObject();
              //
              String[] list = server.rmiRegistry.list();
              for (int i = 0; i < list.length; i++) {
                  System.out.println("-> rmiregistry.list[" + i + "]=" + list[i]);
              }
              // wait forever
              while (true) {
                  try {
                      Thread.currentThread().sleep(Long.MAX_VALUE);
                  } catch (InterruptedException ex) {
                      ex.printStackTrace();
                  }
              }
          }

      }

      // Client.java
      import java.rmi.RemoteException;
      import java.rmi.Naming;
      import java.rmi.NotBoundException;
      import java.rmi.Remote;
      import java.net.MalformedURLException;
      import java.io.IOException;

      public class Client {
          private static final String OBJECT_NAME = "Hello";
          private String host;
          private int port;
          private String fullObjectBaseURL;

          public Client(String host, int port) {
              this.host = host;
              this.port = port;
              this.fullObjectBaseURL = "//" + this.host + ":" + this.port + "/";
          }

          private Remote getRemoteObject() throws RemoteException,
                  MalformedURLException, NotBoundException {
              Remote result = null;
              String rebindName = this.fullObjectBaseURL + Client.OBJECT_NAME;
              long start = System.currentTimeMillis();
              result = Naming.lookup(rebindName);
              long end = System.currentTimeMillis();
              System.out.println("-> Object lookup OK: " + result);
              System.out.println("-> Lookup Time: " + (end - start) + " ms.");
              return result;
          }

          public static void main(String[] args) throws RemoteException,
                  MalformedURLException, NotBoundException {
              String host = null;
              String port = null;
              if (args.length > 0) {
                  host = args[0];
              }
              if (args.length > 1) {
                  port = args[1];
              }
              if (port != null) {
                  try {
                      Integer.parseInt(port);
                  } catch (NumberFormatException nfex) {
                      port = null;
                  }
              }
              if (host == null || port == null) {
                  System.out.println("Usage; Client host port");
                  System.exit( -1);
              }
              Client client = new Client(host, Integer.parseInt(port));

              Hello hello = (Hello) client.getRemoteObject();

              long start = 0;
              long end = 0;
              String result = null;
              int callNo = 0;
              System.out.println("");
              while (true) {
                  callNo++;
                  start = System.currentTimeMillis();
                  result = hello.sayHello("'Call #" + callNo + "'");
                  end = System.currentTimeMillis();
                  System.out.println("-> RMI Call OK. Result -------> " + result);
                  System.out.println("-> Call Time: " + (end - start) + " ms.");
                  try {
                      System.out.println("Press enter to make a new remote call.");
                      System.in.read();
                  } catch (IOException ex) {
                      ex.printStackTrace();
                  }
              }
          }

      }

      // server.policy ----------
      grant codebase "file:/-" {
          permission java.util.PropertyPermission "java.rmi.server.hostname", "write";
          permission java.net.SocketPermission "*:1024-", "accept,connect,resolve";
      };

      ---------- END SOURCE ----------

      CUSTOMER SUBMITTED WORKAROUND :
      1. Just disable SecurityManager and DON'T USE any SecurityManager without DNS server. (This is not a reasonable workaround.)

      2. Add a line into Server's "hosts" file for every client like this;

      192.168.0.1 server
      192.168.0.2 client1
      192.168.0.3 client2
      ###@###.### 2005-06-17 09:12:46 GMT

      Attachments

        Issue Links

          Activity

            People

              mullan Sean Mullan
              jssunw Jitender S (Inactive)
              Votes:
              0 Vote for this issue
              Watchers:
              0 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved:
                Imported:
                Indexed: