首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Py4J回调接口在将打包的.jar用作插件时抛出“无效接口名称”

Py4J回调接口在将打包的.jar用作插件时抛出“无效接口名称”
EN

Stack Overflow用户
提问于 2018-11-13 19:41:58
回答 1查看 267关注 0票数 1

我的代码与py4j网站上显示的示例完全相同:

用Python实现Java接口

但是我的类都在同一个src.main.java包中

(代码见下文)

问题:--如果我以ListenerApplication为主进行gradle fatjar构建,然后执行jar,一切都正常。如果我构建了gradle fatjar并通过插件接口访问代码,我会得到以下错误:

代码语言:javascript
复制
Py4JError: An error occurred while calling o0.registerListener. Trace:
py4j.Py4JException: Invalid interface name: ExampleListener
    at py4j.Protocol.getPythonProxy(Protocol.java:429)
    at py4j.Protocol.getObject(Protocol.java:311)
    at py4j.commands.AbstractCommand.getArguments(AbstractCommand.java:82)
    at py4j.commands.CallCommand.execute(CallCommand.java:77)
    at py4j.GatewayConnection.run(GatewayConnection.java:238)
    at java.lang.Thread.run(Thread.java:748)

问题:为什么在将.jar作为插件运行而不是作为应用程序运行时,Py4J在查找"ExampleListener“时有问题?我甚至可以补充:

代码语言:javascript
复制
public String classtest() throws Exception {
    System.out.println("classtest called");
    Class<?> py = Class.forName("ExampleListener");
    return py.toString();
}

在作为插件和应用程序运行时,ListenerApplication将返回正确的接口!有趣的是,如果我运行这个程序加上netbeans的插件,一切都很好!当应用程序直接运行时,Netbeans会以某种方式公开接口吗?

插件接口

代码语言:javascript
复制
import org.micromanager.MenuPlugin;
import org.micromanager.Studio;
import org.scijava.plugin.Plugin;
import org.scijava.plugin.SciJavaPlugin;
import py4j.GatewayServer;

@Plugin(type = MenuPlugin.class)
public class Py4JPluginInterface implements MenuPlugin, SciJavaPlugin{
    private static final String menuName = "Simpletest_gradle";
    private static final String tooltipDescription = "py4j gateway";
    private static final String version =  "0.1";
    private static final String copyright = "copyright";

    @Override
    public String getSubMenu() {
        return "Simpletest_gradle";
    }

    @Override
    public void onPluginSelected() {
        GatewayServer gatewayServer = new GatewayServer(new ListenerApplication());
        gatewayServer.start();
        System.out.println("Gateway Started at IP:port = "+gatewayServer.getAddress()+":"+gatewayServer.getPort());
    }

    @Override
    public void setContext(Studio app) {
    }

    @Override
    public String getName() {
        return menuName;
    }

    @Override
    public String getHelpText() {
        return tooltipDescription;
    }

    @Override
    public String getVersion() {
        return version;
    }

    @Override
    public String getCopyright() {
        return copyright;
    }

}

接口:

代码语言:javascript
复制
//py4j/examples/ExampleListener.java
package py4j.examples;

public interface ExampleListener {

    Object notify(Object source);

}

应用程序:

代码语言:javascript
复制
package py4j.examples;

import py4j.GatewayServer;

import java.util.ArrayList;
import java.util.List;

public class ListenerApplication {

    List<ExampleListener> listeners = new ArrayList<ExampleListener>();

    public void registerListener(ExampleListener listener) {
        listeners.add(listener);
    }

    public void notifyAllListeners() {
        for (ExampleListener listener: listeners) {
            Object returnValue = listener.notify(this);
            System.out.println(returnValue);
        }
    }

    @Override
    public String toString() {
        return "<ListenerApplication> instance";
    }

    public static void main(String[] args) {
        ListenerApplication application = new ListenerApplication();
        GatewayServer server = new GatewayServer(application);
        server.start(true);
    }
}

python侦听器

代码语言:javascript
复制
from py4j.java_gateway import JavaGateway, CallbackServerParameters


class PythonListener(object):

    def __init__(self, gateway):
        self.gateway = gateway

    def notify(self, obj):
        print("Notified by Java")
        print(obj)
        gateway.jvm.System.out.println("Hello from python!")

        return "A Return Value"

    class Java:
        implements = ["py4j.examples.ExampleListener"]

if __name__ == "__main__":
    gateway = JavaGateway(
        callback_server_parameters=CallbackServerParameters())
    listener = PythonListener(gateway)
    gateway.entry_point.registerListener(listener)
    gateway.entry_point.notifyAllListeners()
    gateway.shutdown()
EN

回答 1

Stack Overflow用户

发布于 2019-07-24 23:31:09

对于那些感兴趣的人来说,这是一个类加载程序问题,显然在插件/OSGI应用程序中很常见。

参见维护人员的响应:https://github.com/bartdag/py4j/issues/339#issuecomment-473655738

我只是在Java端ListenerApplication构造函数中添加了以下内容:

代码语言:javascript
复制
    RootClassLoadingStrategy rmmClassLoader = new RootClassLoadingStrategy();
    ReflectionUtil.setClassLoadingStrategy(rmmClassLoader);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53288375

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档