Received incorrect object type from Py4J gateway

256 views
Skip to first unread message

Josh

unread,
Jun 17, 2019, 2:56:26 PM6/17/19
to Py4J Support and Comments

I am using Java callback functions in Python using Py4J.


Java openjdk 11.0.3

Python 3

Py4J 0.10.8.1


I have successfully used Py4J in the past to use Java callback functions in Python. However, I recently added a new callback class using the same pattern I used before, but now I get the following error with the new class.

AttributeError: 'JavaMember' object has no attribute '_get_object_id'

In my attempts to track down the issue, I printed out the Java objects in Python. The old class StatusCallback shows an object type of TestsJNI$StatusCallback@548ebebc, but the new class shows an object type of <py4j.java_gateway.JavaMember object at 0x7f8dc69817f0>.


This explains the AttributeError I got. But I can't figure out why I am not getting py4j.java_gateway.JavaMember instead of something like TestsJNI$UploadCallback.


Java Code

import py4j.GatewayServer;

public class TestsJNI
{
    public static boolean functionCalled = false;

    public static class UploadCallback
    {
        public static void callback()
        {
            functionCalled = true;
        }

        // I have also tried these functions
        //public static void callback(int a)
        //{
        //  functionCalled = true;
        //}

        //public static void callback(int a, boolean b)
        //{
        //  functionCalled = true;
        //}
    }
    public static UploadCallback uploadCallback = new UploadCallback();

    public static class StatusCallback
    {
        public static void callback()
        {
            functionCalled = true;
        }
    }
    public static StatusCallback statusCallback = new StatusCallback();

    public static void main(String args[])
    {
        TestsJNI testApp = new TestsJNI();

        // Py4J server
        GatewayServer server = new GatewayServer(testApp);
        server.turnLoggingOff();
        server.start();
    }
}

Python Code

from py4j.java_gateway import JavaGateway, GatewayParameters, get_field

javaCmd = ("java -cp /mnt/c/Workspace/tests/java/:.:/home/fred/.local/share/py4j/py4j0.10.8.1.jar TestsJNI")
print(javaCmd)
self.jvmProcess = Popen(javaCmd, shell=True, preexec_fn=os.setsid)
time.sleep(1.0)

# Connect to JVM via Py4J gateway
logging.getLogger("py4j").setLevel(logging.ERROR)
self.gateway = JavaGateway(gateway_parameters=GatewayParameters(auto_field=True))

entryPoint = self.gateway.entry_point
self.jni = entryPoint.autoguidanceJNI
self.jniObj = self.gateway.entry_point

testObj = self.jniObj.uploadCallback
print("upload testObj = " + str(testObj))
ret = False

testObj = self.jniObj.StatusCallback
print("status testObj = " + str(testObj));

Python Output

upload testObj = <py4j.java_gateway.JavaMember object at 0x7f8dc69817f0>
status testObj = TestsJNI$StatusCallback@548ebebc

My Question

Why does Py4J give me a py4j.java_gateway.JavaMember object for the UploadCallback class and a TestsJNI$StatusCallback object for the StatusCallback class?

Barthelemy Dagenais

unread,
Jun 20, 2019, 6:25:58 AM6/20/19
to Py4J Support and Comments
Hi,

I'll need to perform some tests. Maybe the auto_field is confused by the static declarations, but I believe I would have encountered this bug before.

A few observations:
- This does not look like the whole code. I see reference to self. in the python code and to autoguidanceJNI, which is not declared anywhere.
- I see a reference to jniObj.StatusCallback (with capital S) and not jniObj.statusCallback. Is this on purpose?
- Did you try accessing the fields using get_field instead of auto_field: https://www.py4j.org/faq.html#how-to-access-a-field

HTH,
Bart

--
You received this message because you are subscribed to the Google Groups "Py4J Support and Comments" group.
To unsubscribe from this group and stop receiving emails from it, send an email to py4j+uns...@py4j.org.
To view this discussion on the web visit https://groups.google.com/a/py4j.org/d/msgid/py4j/be9c05bf-a0b2-4b33-8316-41d7e10d1799%40py4j.org.

Josh

unread,
Jun 20, 2019, 11:50:13 AM6/20/19
to Py4J Support and Comments
Correct it is not the whole code, it would be too large to paste here.
The capital S is just a typo here, sorry.
Yes, I have tried using `get_field` but I got the same results.

Barthelemy Dagenais

unread,
Jun 24, 2019, 9:08:31 AM6/24/19
to Py4J Support and Comments
Hi,

I did some additional tests and could not reproduce your issue with get_field.

I recreated this test:

public class ExampleClass {


public static class UploadCallback {
public static void callback() {
         System.out.println("Callback called");
      }
}

public static UploadCallback uploadCallback = new UploadCallback();
Then:

In [1]: from py4j.java_gateway import JavaGateway, get_field

In [2]: gateway = JavaGateway()

In [3]: example = gateway.entry_point.getNewExample()

In [4]: upload = get_field(example, "uploadCallback")

In [5]: upload.callback()

And the JVM prints "Callback called"

Is it possible that something else is interfering ?


--
You received this message because you are subscribed to the Google Groups "Py4J Support and Comments" group.
To unsubscribe from this group and stop receiving emails from it, send an email to py4j+uns...@py4j.org.

Josh Henrie

unread,
Jun 24, 2019, 5:15:05 PM6/24/19
to py...@py4j.org
It is very possible that something was interfering.
In an attempt to resolve the issue I reverted to using Py4J 0.10.7 and at the same time changed a bunch of other things. And the error went away.

Unfortunately, I am not sure what changes I made to fix the issue.

I do know that I have a machine with Py4J 0.10.8.1 and the scripts run fine, so I don't think that downgrading Py4J was the solution.

Reply all
Reply to author
Forward
0 new messages