我的代码与py4j网站上显示的示例完全相同:
但是我的类都在同一个src.main.java包中
(代码见下文)
问题:--如果我以ListenerApplication为主进行gradle fatjar构建,然后执行jar,一切都正常。如果我构建了gradle fatjar并通过插件接口访问代码,我会得到以下错误:
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“时有问题?我甚至可以补充:
public String classtest() throws Exception {
System.out.println("classtest called");
Class<?> py = Class.forName("ExampleListener");
return py.toString();
}在作为插件和应用程序运行时,ListenerApplication将返回正确的接口!有趣的是,如果我运行这个程序加上netbeans的插件,一切都很好!当应用程序直接运行时,Netbeans会以某种方式公开接口吗?
插件接口
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;
}
}接口:
//py4j/examples/ExampleListener.java
package py4j.examples;
public interface ExampleListener {
Object notify(Object source);
}应用程序:
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侦听器
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()发布于 2019-07-24 23:31:09
对于那些感兴趣的人来说,这是一个类加载程序问题,显然在插件/OSGI应用程序中很常见。
参见维护人员的响应:https://github.com/bartdag/py4j/issues/339#issuecomment-473655738
我只是在Java端ListenerApplication构造函数中添加了以下内容:
RootClassLoadingStrategy rmmClassLoader = new RootClassLoadingStrategy();
ReflectionUtil.setClassLoadingStrategy(rmmClassLoader);https://stackoverflow.com/questions/53288375
复制相似问题