通过 rmi 参数发送对象时出现异常
Exception when send an object through rmi arguments
当我尝试将一个对象作为参数发送给 rmi 时,出现了这样的异常:
HelloClient exception: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: IntegralClient (no security manager: RMI class loader disabled)
你能帮我弄清楚我的代码和 rmi 服务器-客户端关系实现有什么问题吗?
这是我的代码:
服务器端:
import java.rmi.*;
import java.rmi.server.*;
public class IntegralServer
{
public static void main (String[] argv)
{
try
{
IntegralComputeEngine integralCounter = new IntegralComputeEngine();
Naming.rebind("rmi://localhost/integral", integralCounter);
System.out.println("Integral Server is ready.");
}
catch (Exception e)
{
System.out.println("Addition Server failed: " + e);
}
}
}
客户端:
import java.rmi.*;
public class IntegralClient
{
public static void main(String[] args)
{
try
{
IntegralComputeEngineInterface integralCounter = (IntegralComputeEngineInterface) Naming.lookup("rmi://localhost/integral");
double result = integralCounter.computeIntegral(createFunction(), -1, 1);
System.out.println("Result is: " + result);
}
catch (Exception e)
{
System.out.println("HelloClient exception: " + e);
}
}
private static Function createFunction()
{
return new Function()
{
@Override
public double valueIn(double x)
{
return 1-x;
}
};
}
}
函数接口(驻留在客户端和服务器项目中):
import java.io.Serializable;
public interface Function extends Serializable
{
public double valueIn(double x);
}
IntegralComputeEngineInterface(驻留在客户端和服务器项目中):
import java.rmi.*;
public interface IntegralComputeEngineInterface extends Remote
{
public double computeIntegral(Function function, double from, double to) throws RemoteException;
}
IntegralComputeEngineInterface(仅驻留在服务器上):
import java.rmi.*;
import java.rmi.server.*;
public class IntegralComputeEngine extends UnicastRemoteObject implements IntegralComputeEngineInterface
{
private final double ACCURACY = 100;
protected IntegralComputeEngine() throws RemoteException
{super();}
@Override
public double computeIntegral(Function function, double from, double to) throws RemoteException
{
double stepValue = (to - from) / ACCURACY;
double stepLength = Math.abs(stepValue);
double result = 0.0;
for(int i = 0; i < ACCURACY; i++)
{result += stepLength * function.valueIn(from + stepValue*(i + 0.5));}
return result;
}
}
这是我的项目组织截图:
非常感谢对我的问题的任何帮助!
我发现了这个:
远程对象的参数或来自远程对象的 return 值可以是任何可序列化的对象。这包括基本类型、远程对象和实现 java.io.Serializable 接口的非远程对象。有关如何使 类 可序列化的更多详细信息,请参阅 "Java Object Serialization Specification." 类,对于本地不可用的参数或 return 值,由 RMI 系统动态下载。有关 RMI 在读取参数、return 值和异常时如何下载参数和 return 值 类 的更多信息,请参阅有关 "Dynamic Class Loading" 的部分。
Here.
据此,我传递的参数应该没有问题,但它们仍然存在。
您应该创建一个新的 class、扩展 UnicastRemoteObject 并同时实现您的函数,它将能够毫无问题地通过 rmi 参数发送此类对象。
所以,我将您的函数更改为 FunctionInterface,创建了新的 class 函数:
import java.rmi.RemoteException;
import java.rmi.server.*;
public class Function extends UnicastRemoteObject implements FunctionInterface
{
protected Function() throws RemoteException
{super();}
@Override
public double valueIn(double x)
{
return 1-x;
}
}
所以我的 IntegralClient 现在看起来是这样的:
import java.rmi.*;
public class IntegralClient
{
public static void main(String[] args)
{
try
{
IntegralComputeEngineInterface integralCounter = (IntegralComputeEngineInterface) Naming.lookup("rmi://localhost/integral");
double result = integralCounter.computeIntegral(createFunction(), -1, 1);
System.out.println("Result is: " + result);
}
catch (Exception e)
{
System.out.println("HelloClient exception: " + e);
}
}
private static Function createFunction() throws RemoteException
{
// return new FunctionInterface()
// {
// @Override
// public double valueIn(double x)
// {
// return 1-x;
// }
// };
return new Function();
}
}
而且有效!
当我尝试将一个对象作为参数发送给 rmi 时,出现了这样的异常:
HelloClient exception: java.rmi.ServerException: RemoteException occurred in server thread; nested exception is:
java.rmi.UnmarshalException: error unmarshalling arguments; nested exception is:
java.lang.ClassNotFoundException: IntegralClient (no security manager: RMI class loader disabled)
你能帮我弄清楚我的代码和 rmi 服务器-客户端关系实现有什么问题吗?
这是我的代码:
服务器端:
import java.rmi.*;
import java.rmi.server.*;
public class IntegralServer
{
public static void main (String[] argv)
{
try
{
IntegralComputeEngine integralCounter = new IntegralComputeEngine();
Naming.rebind("rmi://localhost/integral", integralCounter);
System.out.println("Integral Server is ready.");
}
catch (Exception e)
{
System.out.println("Addition Server failed: " + e);
}
}
}
客户端:
import java.rmi.*;
public class IntegralClient
{
public static void main(String[] args)
{
try
{
IntegralComputeEngineInterface integralCounter = (IntegralComputeEngineInterface) Naming.lookup("rmi://localhost/integral");
double result = integralCounter.computeIntegral(createFunction(), -1, 1);
System.out.println("Result is: " + result);
}
catch (Exception e)
{
System.out.println("HelloClient exception: " + e);
}
}
private static Function createFunction()
{
return new Function()
{
@Override
public double valueIn(double x)
{
return 1-x;
}
};
}
}
函数接口(驻留在客户端和服务器项目中):
import java.io.Serializable;
public interface Function extends Serializable
{
public double valueIn(double x);
}
IntegralComputeEngineInterface(驻留在客户端和服务器项目中):
import java.rmi.*;
public interface IntegralComputeEngineInterface extends Remote
{
public double computeIntegral(Function function, double from, double to) throws RemoteException;
}
IntegralComputeEngineInterface(仅驻留在服务器上):
import java.rmi.*;
import java.rmi.server.*;
public class IntegralComputeEngine extends UnicastRemoteObject implements IntegralComputeEngineInterface
{
private final double ACCURACY = 100;
protected IntegralComputeEngine() throws RemoteException
{super();}
@Override
public double computeIntegral(Function function, double from, double to) throws RemoteException
{
double stepValue = (to - from) / ACCURACY;
double stepLength = Math.abs(stepValue);
double result = 0.0;
for(int i = 0; i < ACCURACY; i++)
{result += stepLength * function.valueIn(from + stepValue*(i + 0.5));}
return result;
}
}
这是我的项目组织截图:
非常感谢对我的问题的任何帮助!
我发现了这个: 远程对象的参数或来自远程对象的 return 值可以是任何可序列化的对象。这包括基本类型、远程对象和实现 java.io.Serializable 接口的非远程对象。有关如何使 类 可序列化的更多详细信息,请参阅 "Java Object Serialization Specification." 类,对于本地不可用的参数或 return 值,由 RMI 系统动态下载。有关 RMI 在读取参数、return 值和异常时如何下载参数和 return 值 类 的更多信息,请参阅有关 "Dynamic Class Loading" 的部分。 Here.
据此,我传递的参数应该没有问题,但它们仍然存在。
您应该创建一个新的 class、扩展 UnicastRemoteObject 并同时实现您的函数,它将能够毫无问题地通过 rmi 参数发送此类对象。
所以,我将您的函数更改为 FunctionInterface,创建了新的 class 函数:
import java.rmi.RemoteException;
import java.rmi.server.*;
public class Function extends UnicastRemoteObject implements FunctionInterface
{
protected Function() throws RemoteException
{super();}
@Override
public double valueIn(double x)
{
return 1-x;
}
}
所以我的 IntegralClient 现在看起来是这样的:
import java.rmi.*;
public class IntegralClient
{
public static void main(String[] args)
{
try
{
IntegralComputeEngineInterface integralCounter = (IntegralComputeEngineInterface) Naming.lookup("rmi://localhost/integral");
double result = integralCounter.computeIntegral(createFunction(), -1, 1);
System.out.println("Result is: " + result);
}
catch (Exception e)
{
System.out.println("HelloClient exception: " + e);
}
}
private static Function createFunction() throws RemoteException
{
// return new FunctionInterface()
// {
// @Override
// public double valueIn(double x)
// {
// return 1-x;
// }
// };
return new Function();
}
}
而且有效!