Py4J与my_class.class属性的问题。是什么?

2 投票
1 回答
1743 浏览
提问于 2025-04-17 22:24

我正在尝试通过 Py4J 从 Python 访问 Java DAO 方法,但遇到了一个奇怪的问题。我有一个名为 MyApplication.java 的文件,可以正常编译,并且在 Python 中使用 Py4J 似乎也能部分工作:

import py4j.GatewayServer;

import company.common.dao.DAOFactory;
import company.sys.dao.ABCartDAO;

public class MyApplication {

  public String foo (int n) {
    ShoppingCart bar = DAOFactory.getDAO(ABCartDAO.class);
    String identifier bar.findit(n)
    return identifier;
  }

  public static void main(String[] args) {
    MyApplication app = new MyApplication();
    GatewayServer server = new GatewayServer(app);
    server.start();
  }
}

我可以通过 java MyApplication 启动服务器。但是,当我在 Python 中运行以下代码时:

from py4j.java_gateway import JavaGateway
gateway = JavaGateway()                   # connect to the JVM

# Testing that it works
random = gateway.jvm.java.util.Random()   # create a java.util.Random instance
number1 = random.nextInt(10)              # call the Random.nextInt method
number2 = random.nextInt(10)
print(number1,number2)

my_application = gateway.entry_point        

my_application.foo(4)

获取随机数的部分是成功的(这证明了 Py4J 在正常工作),但调用其中的操作时却失败了,错误信息是:

---------------------------------------------------------------------------
Py4JJavaError                             Traceback (most recent call last)
<ipython-input-14-d2345f6205bf> in <module>()
----> 1 my_application.foo(4)

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/py4j/java_gateway.pyc in __call__(self, *args)
    535         answer = self.gateway_client.send_command(command)
    536         return_value = get_return_value(answer, self.gateway_client,
--> 537                 self.target_id, self.name)
    538 
    539         for temp_arg in temp_args:

/Users/josh/anaconda/envs/py27/lib/python2.7/site-packages/py4j/protocol.pyc in get_return_value(answer, gateway_client, target_id, name)
    298                 raise Py4JJavaError(
    299                     'An error occurred while calling {0}{1}{2}.\n'.
--> 300                     format(target_id, '.', name), value)
    301             else:
    302                 raise Py4JError(

Py4JJavaError: An error occurred while calling t.foo.
: java.lang.NoClassDefFoundError: company/sys/dao/ABCartDAO
        at MyApplication.foo(MyApplication.java:26)
        at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
        at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.lang.reflect.Method.invoke(Method.java:606)
        at py4j.reflection.MethodInvoker.invoke(MethodInvoker.java:231)
        at py4j.reflection.ReflectionEngine.invoke(ReflectionEngine.java:379)
        at py4j.Gateway.invoke(Gateway.java:259)
        at py4j.commands.AbstractCommand.invokeMethod(AbstractCommand.java:132)
        at py4j.commands.CallCommand.execute(CallCommand.java:79)
        at py4j.GatewayConnection.run(GatewayConnection.java:207)
        at java.lang.Thread.run(Thread.java:744)

这是为什么呢?

如果这有关系的话,我在 pom.xml 中使用以下内容来构建我的 Java 文件:

  <dependency>
    <groupId>net.sf.py4j</groupId>
    <artifactId>py4j</artifactId>
    <type>jar</type>
    <version>0.8.1</version>
   </dependency>

我是否需要在编译我的 .class 文件时包含一些额外的依赖项?这是 Py4J 的一个 bug 吗?或者说是某个不支持的功能?

1 个回答

1

这里有很多不相关的问题。先回答第一个:

假设我定义了一个叫做 MyClass 的类,那么 MyClass.class 里面存的是什么?是字符串吗?(如果是,那 MyClass 的值是什么呢?)还是其他东西?

MyClass.class 里面存的是一个指向 Class 对象的引用。这个对象可以用来做很多事情,最主要的是获取关于这个类的运行时信息,方便调试和反射。它也是通过非静态方法 getClass() 返回的内容:

Class<?> clz = MyClass.class;
Class<?> clz = new MyClass().getClass();

我对 Py4J 不是很熟悉,但你可能可以用后者来访问某个对象实例的 Class。请注意,getClass()java.lang.Object 的一个基础方法。

撰写回答