Ada*_*ker 9 java serialization rmi anonymous-class
我在网上进行了一项小型研究并审查了该网站上的相关主题,但答案是矛盾的:有些人说这是不可能的,有些人说这是可能的,但很危险.
目标是将匿名类的对象作为RMI方法的参数传递.由于RMI要求,此类必须是可序列化的.这没问题,很容易使类Serializable.
但我们知道内部类的实例包含对外部类的引用(而匿名类是内部类).因此,当我们序列化内部类的实例时,外部类的实例被序列化以及字段.这里是问题出现的地方:外部类不可序列化,更重要的是 - 我不想序列化它.我想要做的只是发送匿名类的实例.
简单示例 - 这是一个RMI服务,其方法接受Runnable:
public interface RPCService {
Object call(SerializableRunnable runnable);
}
Run Code Online (Sandbox Code Playgroud)
以下是我想要调用该方法的方法
void call() {
myRpcService.call(new SerializableRunnable() {
@Override
public Object run {
System.out.println("It worked!");
}
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,我想要做的是向另一方发送"动作" - 系统A描述应该在系统B上运行的代码.这就像用Java发送脚本一样.
如果可能的话,我可以很容易地看到一些危险的后果:例如,如果我们从Runnable访问字段或捕获外部类的最终变量 - 我们将遇到麻烦,因为调用者实例不存在.另一方面,如果我在Runnable中使用安全代码(编译器可以检查它),那么我没有看到禁止此操作的原因.
因此,如果有人知道,如何在匿名类中正确覆盖方法writeObject()和readObject()方法,或者如何引用外部类transient或者解释为什么在java中不可能,它将非常有用.
UPD
另一个需要考虑的重要事项:外部类不存在于将执行该方法的环境中(系统B),这就是为什么应该完全排除有关它的信息以避免NoClassDefFoundError.
你可以尝试制作Caller.call()一种static方法.
但是,仍然需要在反序列化序列化实例的上下文中提供匿名类.这是不可避免的.
(很难想象匿名类可用的情况,但封闭类不是.)
所以,如果有人可以展示,我如何在我的匿名类中正确覆盖writeObject和readObject方法......
如果你制作Caller.call()静态,那么你会这样做,就像你想要的那样,我想.(我相信你可以找到适合自己的例子.)
实际上,(模块化匿名类可用性问题)它的工作原理.这里,该static main方法替代了一种static Classer.call()方法.该程序编译并运行,表明在静态方法中声明的匿名类可以被序列化和反序列化.
import java.io.*;
public class Bar {
private interface Foo extends Runnable, Serializable {}
public static void main (String[] args)
throws InterruptedException, IOException, ClassNotFoundException {
Runnable foo = new Foo() {
@Override
public void run() {
System.out.println("Lala");
}
};
Thread t = new Thread(foo);
t.start();
t.join();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(foo);
oos.close();
Foo foofoo = (Foo) new ObjectInputStream(
new ByteArrayInputStream(baos.toByteArray())).readObject();
t = new Thread(foofoo);
t.start();
t.join();
}
}
Run Code Online (Sandbox Code Playgroud)
另一个需要记住的重要事项是:在
Caller执行方法的环境中不存在类,因此我希望在序列化期间排除有关它的所有信息以避免NoClassDefFoundError.
没有办法避免这种情况.远程JVM中的反序列化抱怨的原因是类描述符包含对外部类的引用.反序列化方需要解析该引用,即使您设法破坏了引用,即使您从未在反序列化对象中显式或隐式使用合成变量.
问题是远程JVM的类加载器在加载内部类的类文件时需要知道外部类的类型.验证需要它.它需要反思.垃圾收集器需要它.
没有解决方法.
(我不确定这是否也适用于static内部阶级......但我怀疑它确实如此.)
尝试在没有外部类的情况下序列化匿名Runnable实例不仅指序列化问题,还指在另一个环境中执行任意代码的可能性.很高兴看到JLS参考,描述这个问题.
没有JLS参考.JLS中未指定序列化和类加载器.(类初始化是......但这是一个不同的问题.)
可以通过RMI在远程系统上运行任意代码.但是,您需要实现RMI动态类加载才能实现此目的.这是一个参考:
请注意,将远程类的动态类加载添加到RMI会引入重大的安全问题.你必须考虑类加载器泄漏之类的问题.
| 归档时间: |
|
| 查看次数: |
3897 次 |
| 最近记录: |