2013-03-22 1 views
0

나는 책에서 RMI를 작성하기로 결정했다. 나는 rmic로 스텁을 만들었고 rmiregistry를 시작했지만 자바 시작 서버를 작성하려고 할 때 실제로 문제가 발생했습니다. java -classpath D : \ RMI AddServer 예외 : java.rmi. ServerException : 서버 스레드에서 RemoteException이 발생했습니다. n ested exception : java.rmi.UnmarshalException : 인수를 비 정렬 화하는 중에 오류가 발생했습니다. 중첩 된 excep 기입니다 : java.lang.ClassNotFoundException가 :이자바 RMI ClassNotFound 예외

을 :(의 때문에 AddServerImpl_Stub 내가 도움, 나는 AddServerIntf.java

package rmi.app; 
import java.rmi.*; 
public interface AddServerIntf extends Remote { 
    double add(double d1,double d2) throws RemoteException;} 

AddServerImpl을 많은 시간을 잃었 필요하세요

package rmi.app; 
import java.rmi.*; 
import java.rmi.server.*; 
public class AddServerImpl extends UnicastRemoteObject implements AddServerIntf { 

public AddServerImpl() throws RemoteException {} 

public double add(double d1, double d2) throws RemoteException { 
     return d1+d2; 
    } 

} 

AddSer

package rmi.app; 
    import java.net.*; 
    import java.rmi.*; 
    public class AddServer { 
public static void main(String[] args) { 

    try { 

    AddServerImpl addServerImpl = new AddServerImpl(); 
    Naming.rebind("AddServer", addServerImpl);  
    } 
    catch (Exception e){ 
     System.out.println("Exception:"+e); 
    } 

} 

    } 

AddClient

package rmi.app; 
    import java.rmi.Naming; 
    public class AddClient { 
public static void main(String[] args) { 

    try{ 
     String addServerURL= "rmi://"+args[0]+ "/AddServer"; 
     AddServerIntf addServer =(AddServerIntf)Naming.lookup(addServerURL); 
     System.out.println("The first number is:"+args[1]); 
     double d1= Double.valueOf(args[1]).doubleValue(); 
     System.out.println("The second number is:"+args[2]); 
     double d2= Double.valueOf(args[2]).doubleValue(); 
     System.out.println("the sum is:"+ addServer.add(d1,d2)); 

    } 
    catch(Exception e){ 
     System.out.println("Exception : "+ e); 
    } 

} 

    } 
+0

어떤 Java 버전을 사용하고 있습니까? – wmorrison365

+0

제 대답을보세요. 제가 쓰고있을 때 코드에 질문을 넣었을 것입니다. 너 너무 가까웠다. –

답변

1

짧은 답변 VER : 레지스트리는 클래스 패스에 스텁을 가질 필요가있다.

긴 대답 : 당신이 시간 동안 모든 것을 할 필요하지 않은 원인 이되지 사용 rmic의를 수행하는 지난 10 년 내에서 RMI의 튜토리얼을 찾을 수 있습니다.

+0

이것은 힘들고, 나는 그것을 연구하는 데 거의 2 주를 보냈다. 재료는 매우 불완전하다. :-) –

+0

@PauloPedroso - "java rmi tutorial"의 상위 2 개 히트는 최신이며 합리적으로 모두 http://docs.oracle.com/javase/tutorial/rmi/index.html 및 http : // docs입니다. .oracle.com/javase/6/docs/technotes/guides/rmi/hello/hello-world.html (rmic는 사용하지 않음). – jtahlborn

+0

@PauloPedroso - 당신의 대답에 동의하지만 SecurityManager와 정책을 사용해서는 안되며 단지 자습서가 복잡합니다. – jtahlborn

2

저는 Java RMI 응용 프로그램도 작성 중이며 작동시키기 전에 많은 것을 경험했습니다. 많은 연구와 시도와 오류 후에 나는이 "조리법"을 얻었습니다 :

  1. SecurityManager를 설치하지 마십시오.
  2. 정책 파일을 사용하지 마십시오.
  3. 한 VM에서 다른 VM으로 이동할 클래스가 클라이언트와 서버 클래스 경로 (또는 동일한 jar/war)에 에 있는지 확인하십시오.
  4. 데이터베이스 액세스를 위해 최대 절전 모드를 사용하는 경우 클라이언트에도 jar 파일을 넣으십시오. Hibernate는 원래 클래스를 "변경"하고 클라이언트는 이 그것을 deserialize하기 위해 필요할 것이다. 당신은 또한 서버 측에서 스프링을 사용하는 경우
  5. 당신이 스프링 ORM스프링 데이터 JPA 클라이언트에서 항아리를 포함 할 수 있습니다, 당신은 JpaObjectRetrievalFailureException 다음에 ClassNotFoundException가 발생하는 경우;
  6. 나는 병 (rmi 서비스 전혀)의 외부에 아무것도를 달리고 있지 않다;
  7. Java 6을 사용하면서 스텁을 만들지 않았습니다.

내 서버는 순수하게이 일을한다 :

try { 
     try { 
      LocateRegistry.createRegistry(SERVER_PORT); 
     } catch (RemoteException e) { 
      LocateRegistry.getRegistry(SERVER_PORT); 
      e.printStackTrace(); 
     } 
     System.setProperty("java.rmi.server.hostname", SERVER_HOST); 
     connectionRequestHandler = new ConnectionRequestHandlerImpl(); 
     dataRequestHandler = new DataRequestHandlerImpl(); 
     String rmiUrl = "rmi://" + SERVER_HOST + ":" + SERVER_PORT + "/"; 
     Naming.rebind(rmiUrl + "ConnectionRequestHandler", connectionRequestHandler); 
     Naming.rebind(rmiUrl + "DataRequestHandler", dataRequestHandler); 
    } catch (RemoteException e1) { 
     e1.printStackTrace(); 
    } catch (MalformedURLException e) { 
     e.printStackTrace(); 
    } 
} 

그런 다음 클라이언트에 내가 뭐하는 거지 : 그것은 나를 위해 일하고 어떻게

String rmiUrl = "rmi://" + SERVER_HOST + ":" + SERVER_PORT + "/"; 
    try { 
     connectionRequestHandler = (ConnectionRequestHandler)Naming.lookup(rmiUrl + "ConnectionRequestHandler"); 
     dataRequestHandler = (DataRequestHandler)Naming.lookup(rmiUrl + "DataRequestHandler"); 
    } catch (MalformedURLException e) { 
     throw new RmiServicesDownException(e.getMessage()); 
    } catch (RemoteException e) { 
     throw new RmiServicesDownException(e.getMessage()); 
    } catch (NotBoundException e) { 
     throw new RmiServicesDownException(e.getMessage()); 
    } catch (Exception e){ 
     e.printStackTrace(); 
     return; 
    } 

이입니다. 다른 모든 문제는 첫 번째 설정에 비해 해결하기 쉽습니다.

+0

"코드베이스 기능을 사용하지 마십시오." * 배치 옵션입니다. 초기 개발을 망쳐 놓지 마십시오. 사용하려는 경우 SecurityManager 및 정책 파일을 위임한다는 사실을 기억하십시오.하지만 나중에 해당 내용을 파악할 수 있습니다. – EJP

0

SuperServer (0)를 호출하도록 AddServerImpl 생성자를 변경하십시오. 그렇다면 스텁을 생성 할 필요가 없습니다. UnicastRemoteObject의 Javadoc에 대한 서문을 참조하십시오.