【问题标题】:How (at an implementation level) does Java RMI load+define classes?Java RMI 如何(在实现级别)加载+定义类?
【发布时间】:2012-01-19 20:16:38
【问题描述】:

当 RMI(Sun VM 中的 sun.rmi 实现)反序列化对象时,作为远程​​调用的参数或返回值的一部分,它需要从类的名称(序列化中的字符串数据)到Class 对象。 RMI 如何决定使用哪个ClassLoader 来定义类?

【问题讨论】:

    标签: java serialization classloader rmi


    【解决方案1】:

    默认情况下,Java 反序列化在堆栈中搜索第一个非系统类并使用其类加载器(即第一个非空类加载器)。 RMI 将注释添加到串行流中,以提供应从中下载类的位置(URL)。默认情况下,RMI 类加载器使用该位置来查找其他类。有一个系统属性可以关闭该行为(这不是一个坏主意)。

    【讨论】:

    • 所以,基本上,假设没有指定远程代码库,一个返回值会被加载到存根中调用的类的类加载器加载? (或者定义存根是实例的特定代理类的类加载器?)在服务器上呢?直到 UnicastServerRef 对导出的对象进行实际调用,此时参数都已反序列化,所有堆栈帧都应该是系统类,因为它位于 RMI 的调度线程之一上。对吗?
    • @jon 我相信你要么得到服务器对象的类加载器,要么得到它导出的上下文(通常相同)。
    • 这些都不是“默认”的。您必须在导出远程对象的 JVM 上设置 java.rmi.server.codebase 属性才能启动整个过程。我不知道您指的“系统类”是什么。 RMI 不使用“默认 Java 序列化”,它添加了自己的一个覆盖 resolveClass() 的层。
    • @EJP Tom 的回答是正确的。他准确地描述了标准的 Java 反序列化(即 ObjectInputStream); “系统类”是指由空 ClassLoader 加载的类。 RMI 反序列化(即 MarshalInputStream)的默认设置是尊重流中的任何注释(只要安装了 SecurityManager),否则会退回到默认的 ObjectInputStream 行为(调用方)或更复杂的东西(调用方)。稍后会写一些更详细的内容。
    • @jon 就代码库功能而言,这肯定是不正确的。我不知道“关闭该行为的系统类”可能是什么。
    猜你喜欢
    • 1970-01-01
    • 2017-01-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-16
    • 1970-01-01
    相关资源
    最近更新 更多