2015-05-28 1 views
2

Извините за письмо, но используйте переводчика, надеюсь, вы можете помочь мне с примером RMI, который я тестирую.Ошибка при выполнении клиента RMI

я вижу следующее сообщение об ошибке при запуске клиента:

java.rmi.ServerException: RemoteException occurred in server thread; nested exception is: 
    java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is: 
    java.lang.ClassNotFoundException: client.Pi 

Структура проекта заключается в следующем.

|-Cliente\ 
| |-client\ ComputePi (main class) and Pi(Task) 
|  |-->ComputePi.java 
|  |-->ComputePi.class 
|  |-->Pi.java 
|  |-->Pi.class 
| |-compute\ 
|  |-->Compute.java 
|  |-->Compute.class 
|  |-->Task.java 
|  |-->Task.class 
| |-public\ 
|  |-classes\ 
|   |-->compute.jar 
|   |-client\ 
|   |--> Pi.class 
|-->client.policy 

|-Servidor\ 
| |-compute\ 
|  |-->Compute.java 
|  |-->Compute.class 
|  |-->Task.java 
|  |-->Task.class 
| |-engine\ 
|  |-->ComputeEngine.java 
|  |-->ComputeEngine.class 
| |-public\ 
|  |-classes\ 
|   |-->compute.jar 
|-->server.policy 

Сервер запускается нормально, но когда я запускаю клиент, он отправляет мне ошибку, показанную выше. Когда я запускаю клиент, я делаю следующее:

java -cp c:\Users\Mauricio\Documents\RMI\Cliente;c:\Users\Mauricio\Documents\RMI\Cliente\public\classes\compute.jar 
    -Djava.rmi.server.codebase=file:/c:/Users/Mauricio/Documents/RMI/Cliente/public/classes/ 
    -Djava.security.policy=c:/Users/Mauricio/Documents/RMI/Cliente/client.policy 
    client.ComputePi 127.0.0.1 45 

Помогите мне понять, что вызывает эту ошибку?

Извините, что не поставил перед кодом.

Класс Вычислительный

package compute; 

import java.rmi.Remote; 
import java.rmi.RemoteException; 

public interface Compute extends Remote { 
    <T> T executeTask(Task<T> t) throws RemoteException; 
} 

Класс Задача

package compute; 

public interface Task<T> { 
    T execute(); 
} 

Класс ComputePi

package client; 

import java.rmi.registry.LocateRegistry; 
import java.rmi.registry.Registry; 
import java.math.BigDecimal; 
import compute.Compute; 

public class ComputePi { 
    public static void main(String args[]) { 
     if (System.getSecurityManager() == null) { 
      System.setSecurityManager(new SecurityManager()); 
     } 
     try { 
      String name = "Compute"; 
      Registry registry = LocateRegistry.getRegistry(args[0]); 
      Compute comp = (Compute) registry.lookup(name); 
      Pi task = new Pi(Integer.parseInt(args[1])); 
      BigDecimal pi = comp.executeTask(task); 
      System.out.println(pi); 
     } catch (Exception e) { 
      System.err.println("ComputePi exception:"); 
      e.printStackTrace(); 
     } 
    }  
} 

Класс Пи

package client; 

import compute.Task; 
import java.io.Serializable; 
import java.math.BigDecimal; 

public class Pi implements Task<BigDecimal>, Serializable { 

    private static final long serialVersionUID = 227L; 

    /** constants used in pi computation */ 
    private static final BigDecimal FOUR = 
     BigDecimal.valueOf(4); 

    /** rounding mode to use during pi computation */ 
    private static final int roundingMode = 
     BigDecimal.ROUND_HALF_EVEN; 

    /** digits of precision after the decimal point */ 
    private final int digits; 

    /** 
    * Construct a task to calculate pi to the specified 
    * precision. 
    */ 
    public Pi(int digits) { 
     this.digits = digits; 
    } 

    /** 
    * Calculate pi. 
    */ 
    public BigDecimal execute() { 
     return computePi(digits); 
    } 

    /** 
    * Compute the value of pi to the specified number of 
    * digits after the decimal point. The value is 
    * computed using Machin's formula: 
    * 
    *   pi/4 = 4*arctan(1/5) - arctan(1/239) 
    * 
    * and a power series expansion of arctan(x) to 
    * sufficient precision. 
    */ 
    public static BigDecimal computePi(int digits) { 
     int scale = digits + 5; 
     BigDecimal arctan1_5 = arctan(5, scale); 
     BigDecimal arctan1_239 = arctan(239, scale); 
     BigDecimal pi = arctan1_5.multiply(FOUR).subtract(
            arctan1_239).multiply(FOUR); 
     return pi.setScale(digits, 
          BigDecimal.ROUND_HALF_UP); 
    } 
    /** 
    * Compute the value, in radians, of the arctangent of 
    * the inverse of the supplied integer to the specified 
    * number of digits after the decimal point. The value 
    * is computed using the power series expansion for the 
    * arc tangent: 
    * 
    * arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + 
    *  (x^9)/9 ... 
    */ 
    public static BigDecimal arctan(int inverseX, 
            int scale) 
    { 
     BigDecimal result, numer, term; 
     BigDecimal invX = BigDecimal.valueOf(inverseX); 
     BigDecimal invX2 = 
      BigDecimal.valueOf(inverseX * inverseX); 

     numer = BigDecimal.ONE.divide(invX, 
             scale, roundingMode); 

     result = numer; 
     int i = 1; 
     do { 
      numer = 
       numer.divide(invX2, scale, roundingMode); 
      int denom = 2 * i + 1; 
      term = 
       numer.divide(BigDecimal.valueOf(denom), 
          scale, roundingMode); 
      if ((i % 2) != 0) { 
       result = result.subtract(term); 
      } else { 
       result = result.add(term); 
      } 
      i++; 
     } while (term.compareTo(BigDecimal.ZERO) != 0); 
     return result; 
    } 
} 

Класс ComputeEngine

package client; 

import compute.Task; 
import java.io.Serializable; 
import java.math.BigDecimal; 

public class Pi implements Task<BigDecimal>, Serializable { 

    private static final long serialVersionUID = 227L; 

    /** constants used in pi computation */ 
    private static final BigDecimal FOUR = 
     BigDecimal.valueOf(4); 

    /** rounding mode to use during pi computation */ 
    private static final int roundingMode = 
     BigDecimal.ROUND_HALF_EVEN; 

    /** digits of precision after the decimal point */ 
    private final int digits; 

    /** 
    * Construct a task to calculate pi to the specified 
    * precision. 
    */ 
    public Pi(int digits) { 
     this.digits = digits; 
    } 

    /** 
    * Calculate pi. 
    */ 
    public BigDecimal execute() { 
     return computePi(digits); 
    } 

    /** 
    * Compute the value of pi to the specified number of 
    * digits after the decimal point. The value is 
    * computed using Machin's formula: 
    * 
    *   pi/4 = 4*arctan(1/5) - arctan(1/239) 
    * 
    * and a power series expansion of arctan(x) to 
    * sufficient precision. 
    */ 
    public static BigDecimal computePi(int digits) { 
     int scale = digits + 5; 
     BigDecimal arctan1_5 = arctan(5, scale); 
     BigDecimal arctan1_239 = arctan(239, scale); 
     BigDecimal pi = arctan1_5.multiply(FOUR).subtract(
            arctan1_239).multiply(FOUR); 
     return pi.setScale(digits, 
          BigDecimal.ROUND_HALF_UP); 
    } 
    /** 
    * Compute the value, in radians, of the arctangent of 
    * the inverse of the supplied integer to the specified 
    * number of digits after the decimal point. The value 
    * is computed using the power series expansion for the 
    * arc tangent: 
    * 
    * arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + 
    *  (x^9)/9 ... 
    */ 
    public static BigDecimal arctan(int inverseX, 
            int scale) 
    { 
     BigDecimal result, numer, term; 
     BigDecimal invX = BigDecimal.valueOf(inverseX); 
     BigDecimal invX2 = 
      BigDecimal.valueOf(inverseX * inverseX); 

     numer = BigDecimal.ONE.divide(invX, 
             scale, roundingMode); 

     result = numer; 
     int i = 1; 
     do { 
      numer = 
       numer.divide(invX2, scale, roundingMode); 
      int denom = 2 * i + 1; 
      term = 
       numer.divide(BigDecimal.valueOf(denom), 
          scale, roundingMode); 
      if ((i % 2) != 0) { 
       result = result.subtract(term); 
      } else { 
       result = result.add(term); 
      } 
      i++; 
     } while (term.compareTo(BigDecimal.ZERO) != 0); 
     return result; 
    } 
} 
+0

Никто не может, пока вы не разместите какой-либо код. Будь благоразумен. – EJP

ответ

0

java.lang.ClassNotFoundException: client.Pi

Сервер не client.Pi на своих CLASSPATH или через кодовую клиенту либо. file: кодовые базы не работают, если только сервер и клиент находятся на одной машине, и в этом случае почти нет смысла использовать функцию codebase.

Смотрите также @ ответ Марио вновь java.rmi.server.useCodebaseOnly.

+1

Должен ли я загрузить его, но я делаю и не знаю почему. Добавить в общую папку для доступа. –

+0

Или как это добавить? –

+0

Точно так же вы кладете все остальные классы серверов. – EJP

1

Я считаю, что ошибка, вы получаете, потому что вы пропустили следующий флаг при запуске сервера:

-Djava.rmi.server.useCodebaseOnly=false

Проблема заключается в том с сервером, а не с клиентом. Клиент сообщает об ошибке сервера.

На момент написания этого учебника Oracle RMI отсутствует этот флаг; так что это не ваша вина.

https://docs.oracle.com/javase/tutorial/rmi/running.html

Если вы пропустили флаг, сервер не будет загружать любой код, который он не имеет в своем собственном коде. Другими словами, если клиент находится на другой машине, чем сервер, а класс Pi существует только на клиенте, сервер не сможет загрузить его. Ошибка, которую вы видите, - это точная ошибка, которую я получал, пока не добавлю флаг.

Я понимаю, что из JVM v1.7 on значение по умолчанию для useCodebaseOnly составляет true. (Истинное значение позволяет повысить безопасность, но делает это для сломанного учебника.)

Короче говоря, добавьте флаг, установленный в false, к команде запуска сервера. Удачи!