【问题标题】:Delegation of custom class loader in RMIRMI 中自定义类加载器的委托
【发布时间】:2019-10-31 17:13:58
【问题描述】:

更新:添加了更多信息,因为解决方法无法可靠运行

我有一个 RMI 模块,我使用自定义类加载器 vie spring bean 加载该模块。此类加载器也用于加载该模块。

ClassLoader 继承自 URLClassLoader。该自定义类加载器的父类加载器设置为 AppClassLoader。

在这个模块中,我根据这个类加载器使用 conxt 类加载器启动 RMI 注册表。

现在,如果我进行 RMI 调用,RMI 注册表:

  • 能够在我提供给类加载器的 URL 路径中发现类
  • 无法在父类加载器中发现类。

通过在 RMI 服务器端启用调试

"-Djava.rmi.server.logCalls=true",
"-Dsun.rmi.server.logLevel=VERBOSE",
"-Dsun.rmi.loader.logLevel=VERBOSE",

我能够验证 RMI 注册表使用了正确的类加载器(也是对父级的引用)

我尝试将来自 AppClassLoader 的 URL 添加到我的 ClassLoader。首先,它似乎工作,但它只是随机工作。

目前我从 RMI 日志中得到以下输出

Nov 04, 2019 2:56:33 PM sun.rmi.server.LoaderHandler loadClass
FEINER: RMI TCP Connection(4)-10.45.42.206: (thread context class loader: class org.jvoicexml.config.JVoiceXmlClassLoader[repo=jsapi20,...,file:/C:/Users/dwalka/Documents/git/JVoiceXML/org.jvoicexml/build/libs/org.jvoicexml-0.7.9.jar,...,parent=sun.misc.Launcher$AppClassLoader@3d4eac69])
Nov 04, 2019 2:56:33 PM sun.rmi.server.LoaderHandler loadClass
FEIN: RMI TCP Connection(4)-10.45.42.206: class "org.jvoicexml.UuidSessionIdentifer" not found via codebase
java.lang.ClassNotFoundException: org.jvoicexml.UuidSessionIdentifer

父类加载器如下所示

2019-11-04T14:56:08,505 [JVoiceXmlMain       ] INFO   cexml.jndi.classserver.ClassloaderServer (    56) - parent class loader 'sun.misc.Launcher$AppClassLoader@3d4eac69'
...
2019-11-04T14:56:08,506 [JVoiceXmlMain       ] INFO   cexml.jndi.classserver.ClassloaderServer (    64) - parent class loader entry: 'file:/C:/Users/dwalka/Documents/git/JVoiceXML/org.jvoicexml/build/libs/org.jvoicexml-0.7.9.jar'
...

旁注:找到来自 JDK 的类,例如 java.net.URI

jar 包含类

C:\Users\dwalka\Documents\git\JVoiceXML\org.jvoicexml\build\libs>jar -tf org.jvoicexml-0.7.9.jar | findstr "UuidSessionIdentifer"
org/jvoicexml/UuidSessionIdentifer.class

我做了一些单元测试以确保它可以正常工作(没有 RMI)。它找到类

  • 在同一个罐子里
  • 来自讨论中的罐子
  • 来自不在 CLASSPATH 中的其他 jars

这是我的类加载器

    public final class JVoiceXmlClassLoader extends URLClassLoader {
        /** The repository that this class loader is responsible for. */
        private final String repository;

        /**
         * Constructs a new object.
         * @param parent the parent class loader.
         */
        public JVoiceXmlClassLoader(final ClassLoader parent) {
            this(parent, null);
        }

        /**
         * Constructs a new object.
         * @param parent the parent class loader.
         * @param repo the repository that this class loader is responsible for
         */
        public JVoiceXmlClassLoader(final ClassLoader parent, final String repo) {
            super(new URL[0], parent);
            repository = repo;
        }

        /**
         * Retrieves the used repository
         * @return the repository.
         * @since 0.7.9
         */
        public String getRepository() {
            return repository;
        }

        /**
         * {@inheritDoc}
         */
        @Override
        public void addURL(final URL url) {
            super.addURL(url);
        }

    }

设置了安全管理器

"-Djava.security.manager",
"-Djava.security.policy=${project(':org.jvoicexml').buildDir}/config/jvoicexml.policy",

而且政策文件非常宽松

grant {
    permission java.security.AllPermission;
};

奇怪的是,它以前可以正常工作。从那以后我所做的改变

  • 切换到 Windows 10
  • 与此同时,我验证了在 Linux (Ubuntu) 下也会出现同样的问题
  • 更新到 Gradle 5.4.1

【问题讨论】:

    标签: java classloader rmi urlclassloader


    【解决方案1】:

    问题的根本原因既不是类加载器也不是 RMI。当与 eclipse 和 gradle 混在一起时,这似乎是一个 CLASSPATH 问题。

    【讨论】:

    • 好像发布问题和回答问题的人是一样的?相同的个人资料图片。祝你好运。
    猜你喜欢
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-02
    • 1970-01-01
    • 1970-01-01
    • 2021-08-29
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多