{"id":560,"library":"py4j","title":"Py4J: Python to Java Bridge","description":"Py4J enables Python programs to dynamically access Java objects in a Java Virtual Machine (JVM). It facilitates method calls and allows access to Java collections as if they were native Python objects. Py4J also supports callbacks, enabling Java programs to call Python objects. The current version is 0.10.9.9, and it maintains a consistent release cadence with a strong focus on backward compatibility.","status":"active","version":"0.10.9.9","language":"python","source_language":"en","source_url":"https://github.com/py4j/py4j","tags":["java","jvm","interoperability","bridge","rpc"],"install":[{"cmd":"pip install py4j","lang":"bash","label":"Install Py4J"}],"dependencies":[{"reason":"Py4J requires a running Java Virtual Machine (JVM) to connect to, for which JDK 7+ is necessary.","package":"Java Development Kit (JDK) 7+","optional":false},{"reason":"Py4J officially supports and is tested with Python versions 3.8 and newer.","package":"Python 3.8+","optional":false}],"imports":[{"symbol":"JavaGateway","correct":"from py4j.java_gateway import JavaGateway"},{"symbol":"GatewayParameters","correct":"from py4j.java_gateway import GatewayParameters"}],"quickstart":{"code":"import os\nfrom py4j.java_gateway import JavaGateway, GatewayParameters\nimport subprocess\nimport time\n\n# --- Java Gateway Server Setup (for demonstration) ---\n# In a real application, the Java Gateway Server would be started separately.\n# For this example, we'll try to start a minimal one programmatically.\n# This assumes 'py4j<version>.jar' is in the classpath. For simplicity, \n# we'll use a placeholder for py4j.jar path. Users need to replace it.\n# Usually, py4j.jar is found in your Python environment's site-packages/py4j/ directory.\n\n# NOTE: Replace '/path/to/py4j<version>.jar' with the actual path to your Py4J JAR file.\n# You can find it by running: `python -c \"import py4j; import os; print(os.path.join(os.path.dirname(py4j.__file__), 'py4j0.10.9.9.jar'))\"`\nPY4J_JAR_PATH = os.environ.get('PY4J_JAR_PATH', '/path/to/py4j0.10.9.9.jar') # Update this path!\n\njava_code = \"\"\"\nimport py4j.GatewayServer;\n\npublic class AdditionApplication {\n    public int addition(int first, int second) {\n        return first + second;\n    }\n\n    public static void main(String[] args) {\n        AdditionApplication app = new AdditionApplication();\n        GatewayServer server = new GatewayServer(app, 25333);\n        server.start();\n        System.out.println(\"Gateway Server Started on port 25333\");\n    }\n}\n\"\"\"\n\n# Attempt to compile and run the Java code for quickstart demo\n# This is a simplification and might require manual setup for complex environments.\n# In a production setting, the Java server would be a separate, long-running process.\n\n# Create temporary files for Java code and compiled class\njava_file_name = \"AdditionApplication.java\"\nclass_file_name = \"AdditionApplication.class\"\n\nwith open(java_file_name, \"w\") as f:\n    f.write(java_code)\n\ntry:\n    # Compile Java code (requires javac in PATH)\n    compile_process = subprocess.run(\n        [\"javac\", \"-cp\", PY4J_JAR_PATH, java_file_name],\n        capture_output=True, text=True\n    )\n    if compile_process.returncode != 0:\n        print(\"Java compilation failed:\", compile_process.stderr)\n        print(\"Please ensure javac is in your PATH and PY4J_JAR_PATH is correct.\")\n        # Fallback for systems without javac or if compilation fails: manual start instruction\n        print(\"Alternatively, you can manually compile and run the Java server:\")\n        print(f\"1. Save the Java code above as {java_file_name}\")\n        print(f\"2. Compile: javac -cp {PY4J_JAR_PATH} {java_file_name}\")\n        print(f\"3. Run: java -cp {PY4J_JAR_PATH}:. AdditionApplication\")\n        # If on Windows, use ';' instead of ':' for classpath separator in commands\n        raise RuntimeError(\"Java compilation failed, cannot run quickstart.\")\n\n    # Run Java Gateway Server in a separate process\n    # Using 'nohup' and '&' for background on *NIX, or 'start' on Windows\n    if os.name == 'nt': # Windows\n        java_server_command = [\"java\", \"-cp\", f\".;{PY4J_JAR_PATH}\", \"AdditionApplication\"]\n        java_process = subprocess.Popen(java_server_command, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)\n    else: # Unix-like\n        java_server_command = [\"java\", \"-cp\", f\":{PY4J_JAR_PATH}\", \"AdditionApplication\"]\n        java_process = subprocess.Popen(java_server_command, preexec_fn=os.setsid)\n\n    print(\"Starting Java Gateway Server...\")\n    time.sleep(5) # Give Java server time to start\n\n    # --- Python Client --- \n    gateway = JavaGateway(gateway_parameters=GatewayParameters(port=25333))\n\n    # Access the Java entry point (AdditionApplication instance)\n    addition_app = gateway.entry_point\n\n    # Call a Java method\n    number1 = 5\n    number2 = 3\n    result = addition_app.addition(number1, number2)\n    print(f\"Python calling Java: {number1} + {number2} = {result}\")\n\n    # Access JVM directly for standard Java objects\n    java_list = gateway.jvm.java.util.ArrayList()\n    java_list.add(\"Hello from Python!\")\n    print(f\"Java list created and modified from Python: {java_list}\")\n\nexcept Exception as e:\n    print(f\"An error occurred during quickstart: {e}\")\nfinally:\n    # Clean up Java process if it was started\n    if 'java_process' in locals() and java_process.poll() is None:\n        print(\"Shutting down Java Gateway Server...\")\n        if os.name == 'nt':\n            subprocess.run([\"taskkill\", \"/F\", \"/T\", \"/PID\", str(java_process.pid)], capture_output=True)\n        else:\n            os.killpg(os.getpgid(java_process.pid), 15) # Send SIGTERM\n        java_process.wait(timeout=5)\n    \n    # Clean up temporary files\n    os.remove(java_file_name) if os.path.exists(java_file_name) else None\n    os.remove(class_file_name) if os.path.exists(class_file_name) else None\n    # Also remove AdditionApplication$*.class files if they exist\n    for f in os.listdir('.'):\n        if f.startswith('AdditionApplication$') and f.endswith('.class'):\n            os.remove(f)\n","lang":"python","description":"This quickstart demonstrates how to connect a Python client to a Java Gateway Server, access an entry point object, and call Java methods. It includes a simplified Python-driven setup for the Java server (which usually runs independently). The example performs basic addition via a custom Java class and interacts with a standard Java `ArrayList`. Users *must* replace `/path/to/py4j<version>.jar` with the actual path to their Py4J JAR file for the Java compilation and execution to succeed."},"warnings":[{"fix":"Use explicit collection conversion. Either configure Py4J for automatic conversion (see documentation on 'Collections Conversion') or manually construct Java collection types via `gateway.jvm.java.util.ArrayList()` and populate them before passing.","message":"Py4J does not automatically convert pure Python `list` objects to Java `List` objects when passed as arguments to Java methods. This will result in an `InvalidGatewayException` or similar error if not handled.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure your Java Gateway Server application is running and listening on the correct host and port (default is `localhost:25333`) before initializing `JavaGateway` in Python. Verify network connectivity if connecting remotely.","message":"Attempting to connect to the Java Gateway Server before it has started, or if it is not running on the expected host/port, will result in a `socket.error: [Errno 111] Connection refused`.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Do not rely on Python magic members being accessible from Java. If you were implicitly or explicitly relying on these, you will need to refactor your Python code or Java code to pass explicit values or methods.","message":"Starting with Py4J 0.10.9.9, Python's magic members (e.g., `__name__`, `__class__`) are no longer sent to the Java side, raising an `AttributeError` instead. This prevents unintended exposure and potential issues on the Java side.","severity":"breaking","affected_versions":"0.10.9.9 and later"},{"fix":"Consult the Py4J documentation and Java documentation regarding `--add-opens` flags if you encounter `InaccessibleObjectException` or similar errors related to reflection when using Java 11+. Ensure your Py4J JAR is compatible with your Java version. The Py4J project has a strong commitment to backward compatibility, but system-level changes in Java may require configuration updates.","message":"For Java versions 11 and later, changes related to the Java Platform Module System (JPMS) and reflective access (e.g., `setAccessible`) might require specific JVM arguments (`--add-opens`) or adjustments to how the Py4J Java Gateway Server is launched, particularly for complex applications.","severity":"gotcha","affected_versions":"Java 11+ (with Py4J 0.9.x to 0.10.x)"},{"fix":"If you are upgrading from an older Py4J version (pre-0.7) and previously implemented custom handling for `byte[]` due to the reference behavior, you might need to remove or adapt that code as Py4J now handles the conversion automatically and passes by value. Test your code thoroughly after upgrading.","message":"Prior to Py4J 0.7, Java `byte[]` arrays passed to Python were treated as references, requiring individual calls for each byte access. Since 0.7, `byte[]` are passed by value and converted to Python `bytearray` (Python 2.x) or `bytes` (Python 3.x), and vice versa.","severity":"breaking","affected_versions":"Prior to 0.7 (behavior changed in 0.7)"},{"fix":"Install a suitable Java Development Kit (JDK) for your operating system. After installation, ensure that the `bin` directory of your JDK installation (e.g., `/usr/lib/jvm/java-XX-openjdk/bin` on Linux, `C:\\Program Files\\Java\\jdk-XX\\bin` on Windows) is correctly added to your system's `PATH` environment variable. You may need to restart your terminal or environment for the changes to take effect.","message":"The error `[Errno 2] No such file or directory: 'javac'` indicates that the Java Development Kit (JDK) is either not installed on your system or its executable directory (`bin`) is not included in your system's PATH environment variable. `javac` is the Java compiler and is required for compiling Java source files, which may be part of Py4J's quickstart examples, internal processes, or custom Java code you are trying to use.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure a compatible Java Development Kit (JDK) is installed on your system. Verify that the `javac` executable's directory (e.g., `JDK_HOME/bin`) is included in your system's PATH environment variable. For Docker environments, ensure the base image or subsequent steps install the JDK.","message":"The `javac` command was not found, indicating that a Java Development Kit (JDK) is either not installed, not correctly configured, or not in the system's PATH. Some Py4J quickstart processes or applications may require `javac` for compilation.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-05-12T15:08:17.071Z","next_check":"2026-06-26T00:00:00.000Z","problems":[{"fix":"Install the py4j package using pip: `pip install py4j` or ensure your `PYTHONPATH` correctly includes the directory where py4j is installed, especially in PySpark environments where it might be within `SPARK_HOME/python/lib/py4j-*-src.zip`.","cause":"The 'py4j' Python package is not installed in the current Python environment or is not accessible in the `PYTHONPATH`.","error":"ModuleNotFoundError: No module named 'py4j'"},{"fix":"Set the `PYTHONPATH` environment variable to include the `py4j` zip file located within your Spark installation (e.g., `export PYTHONPATH=$SPARK_HOME/python/lib/py4j-*-src.zip:$PYTHONPATH`) or explicitly install `py4j` using `pip` if not using PySpark's bundled version.","cause":"Similar to `ModuleNotFoundError`, this error typically occurs when the `py4j` library or its `java_gateway` submodule cannot be found in the `PYTHONPATH`, often specific to PySpark setups where `py4j` is bundled within Spark's installation.","error":"ImportError: No module named py4j.java_gateway"},{"fix":"Examine the full traceback (including the Java stack trace provided within the `Py4JJavaError` message) to identify the specific Java exception and its cause, then debug the corresponding Java code or Python logic interacting with it.","cause":"This generic error indicates that an exception occurred within the Java Virtual Machine (JVM) when a Python program tried to call a Java method or access a Java object, and Py4J propagated that Java exception back to Python.","error":"py4j.protocol.Py4JJavaError: An error occurred while calling"},{"fix":"Ensure the Java Gateway server is running and listening on the expected host and port (default 25333). Verify network connectivity and firewall settings. If running in containers, ensure ports are exposed and accessible between containers.","cause":"This error occurs when the Python client cannot establish a network connection with the Java Gateway server, often due to the Java server not running, being on a different host/port, or firewall issues. It often appears alongside `ConnectionRefusedError`.","error":"py4j.protocol.Py4JNetworkError: An error occurred while trying to connect to the Java server (127.0.0.1:XXXXX)"},{"fix":"Check the Java gateway server logs for any unhandled exceptions or crashes that might prevent a response. Ensure sufficient memory and resources for the Java process, especially in Spark environments, as this can sometimes relate to out-of-memory issues or task failures.","cause":"This error signifies that the Python side sent a command to the Java gateway, but the Java side did not send back an expected response, often indicating an issue with the Java process or an unexpected termination of the Java call.","error":"py4j.protocol.Py4JNetworkError: Answer from Java side is empty"}],"ecosystem":"pypi","meta_description":null,"install_score":100,"install_tag":"verified","quickstart_score":80,"quickstart_tag":"verified","pypi_latest":null,"install_checks":{"last_tested":"2026-05-12","tag":"verified","tag_description":"installs cleanly on critical runtimes, fast import, recently tested","results":[{"runtime":"python:3.10-alpine","python_version":"3.10","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.17,"mem_mb":8.1,"disk_size":"18.6M"},{"runtime":"python:3.10-slim","python_version":"3.10","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.13,"mem_mb":8.1,"disk_size":"19M"},{"runtime":"python:3.11-alpine","python_version":"3.11","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.29,"mem_mb":8.6,"disk_size":"20.7M"},{"runtime":"python:3.11-slim","python_version":"3.11","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.28,"mem_mb":8.6,"disk_size":"21M"},{"runtime":"python:3.12-alpine","python_version":"3.12","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.21,"mem_mb":8.6,"disk_size":"12.5M"},{"runtime":"python:3.12-slim","python_version":"3.12","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.22,"mem_mb":8.6,"disk_size":"13M"},{"runtime":"python:3.13-alpine","python_version":"3.13","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.24,"mem_mb":8.7,"disk_size":"12.1M"},{"runtime":"python:3.13-slim","python_version":"3.13","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.26,"mem_mb":8.5,"disk_size":"13M"},{"runtime":"python:3.9-alpine","python_version":"3.9","os_libc":"alpine (musl)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.19,"mem_mb":7.9,"disk_size":"18.1M"},{"runtime":"python:3.9-slim","python_version":"3.9","os_libc":"slim (glibc)","variant":"default","exit_code":0,"wheel_type":null,"failure_reason":null,"install_time_s":null,"import_time_s":0.14,"mem_mb":7.9,"disk_size":"19M"}]},"quickstart_checks":{"last_tested":"2026-04-23","tag":"verified","tag_description":"quickstart runs on critical runtimes, recently tested","results":[{"runtime":"python:3.10-alpine","exit_code":0},{"runtime":"python:3.10-slim","exit_code":0},{"runtime":"python:3.11-alpine","exit_code":0},{"runtime":"python:3.11-slim","exit_code":0},{"runtime":"python:3.12-alpine","exit_code":0},{"runtime":"python:3.12-slim","exit_code":0},{"runtime":"python:3.13-alpine","exit_code":0},{"runtime":"python:3.13-slim","exit_code":0},{"runtime":"python:3.9-alpine","exit_code":0},{"runtime":"python:3.9-slim","exit_code":0}]}}