Py4J: Python to Java Bridge
raw JSON → 0.10.9.9 verified Tue May 12 auth: no python install: verified quickstart: verified
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.
pip install py4j Common errors
error ModuleNotFoundError: No module named 'py4j' ↓
cause The 'py4j' Python package is not installed in the current Python environment or is not accessible in the `PYTHONPATH`.
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. error ImportError: No module named py4j.java_gateway ↓
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.
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. error py4j.protocol.Py4JJavaError: An error occurred while calling ↓
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.
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. error py4j.protocol.Py4JNetworkError: An error occurred while trying to connect to the Java server (127.0.0.1:XXXXX) ↓
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`.
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.
error py4j.protocol.Py4JNetworkError: Answer from Java side is empty ↓
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.
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.
Warnings
gotcha 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. ↓
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.
gotcha 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`. ↓
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.
breaking 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. ↓
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.
gotcha 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. ↓
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.
breaking 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. ↓
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.
gotcha 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. ↓
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.
gotcha 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. ↓
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.
Install compatibility verified last tested: 2026-05-12
python os / libc status wheel install import disk
3.10 alpine (musl) - - 0.17s 18.6M
3.10 slim (glibc) - - 0.13s 19M
3.11 alpine (musl) - - 0.29s 20.7M
3.11 slim (glibc) - - 0.28s 21M
3.12 alpine (musl) - - 0.21s 12.5M
3.12 slim (glibc) - - 0.22s 13M
3.13 alpine (musl) - - 0.24s 12.1M
3.13 slim (glibc) - - 0.26s 13M
3.9 alpine (musl) - - 0.19s 18.1M
3.9 slim (glibc) - - 0.14s 19M
Imports
- JavaGateway
from py4j.java_gateway import JavaGateway - GatewayParameters
from py4j.java_gateway import GatewayParameters
Quickstart verified last tested: 2026-04-23
import os
from py4j.java_gateway import JavaGateway, GatewayParameters
import subprocess
import time
# --- Java Gateway Server Setup (for demonstration) ---
# In a real application, the Java Gateway Server would be started separately.
# For this example, we'll try to start a minimal one programmatically.
# This assumes 'py4j<version>.jar' is in the classpath. For simplicity,
# we'll use a placeholder for py4j.jar path. Users need to replace it.
# Usually, py4j.jar is found in your Python environment's site-packages/py4j/ directory.
# NOTE: Replace '/path/to/py4j<version>.jar' with the actual path to your Py4J JAR file.
# 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'))"`
PY4J_JAR_PATH = os.environ.get('PY4J_JAR_PATH', '/path/to/py4j0.10.9.9.jar') # Update this path!
java_code = """
import py4j.GatewayServer;
public class AdditionApplication {
public int addition(int first, int second) {
return first + second;
}
public static void main(String[] args) {
AdditionApplication app = new AdditionApplication();
GatewayServer server = new GatewayServer(app, 25333);
server.start();
System.out.println("Gateway Server Started on port 25333");
}
}
"""
# Attempt to compile and run the Java code for quickstart demo
# This is a simplification and might require manual setup for complex environments.
# In a production setting, the Java server would be a separate, long-running process.
# Create temporary files for Java code and compiled class
java_file_name = "AdditionApplication.java"
class_file_name = "AdditionApplication.class"
with open(java_file_name, "w") as f:
f.write(java_code)
try:
# Compile Java code (requires javac in PATH)
compile_process = subprocess.run(
["javac", "-cp", PY4J_JAR_PATH, java_file_name],
capture_output=True, text=True
)
if compile_process.returncode != 0:
print("Java compilation failed:", compile_process.stderr)
print("Please ensure javac is in your PATH and PY4J_JAR_PATH is correct.")
# Fallback for systems without javac or if compilation fails: manual start instruction
print("Alternatively, you can manually compile and run the Java server:")
print(f"1. Save the Java code above as {java_file_name}")
print(f"2. Compile: javac -cp {PY4J_JAR_PATH} {java_file_name}")
print(f"3. Run: java -cp {PY4J_JAR_PATH}:. AdditionApplication")
# If on Windows, use ';' instead of ':' for classpath separator in commands
raise RuntimeError("Java compilation failed, cannot run quickstart.")
# Run Java Gateway Server in a separate process
# Using 'nohup' and '&' for background on *NIX, or 'start' on Windows
if os.name == 'nt': # Windows
java_server_command = ["java", "-cp", f".;{PY4J_JAR_PATH}", "AdditionApplication"]
java_process = subprocess.Popen(java_server_command, creationflags=subprocess.CREATE_NEW_PROCESS_GROUP)
else: # Unix-like
java_server_command = ["java", "-cp", f":{PY4J_JAR_PATH}", "AdditionApplication"]
java_process = subprocess.Popen(java_server_command, preexec_fn=os.setsid)
print("Starting Java Gateway Server...")
time.sleep(5) # Give Java server time to start
# --- Python Client ---
gateway = JavaGateway(gateway_parameters=GatewayParameters(port=25333))
# Access the Java entry point (AdditionApplication instance)
addition_app = gateway.entry_point
# Call a Java method
number1 = 5
number2 = 3
result = addition_app.addition(number1, number2)
print(f"Python calling Java: {number1} + {number2} = {result}")
# Access JVM directly for standard Java objects
java_list = gateway.jvm.java.util.ArrayList()
java_list.add("Hello from Python!")
print(f"Java list created and modified from Python: {java_list}")
except Exception as e:
print(f"An error occurred during quickstart: {e}")
finally:
# Clean up Java process if it was started
if 'java_process' in locals() and java_process.poll() is None:
print("Shutting down Java Gateway Server...")
if os.name == 'nt':
subprocess.run(["taskkill", "/F", "/T", "/PID", str(java_process.pid)], capture_output=True)
else:
os.killpg(os.getpgid(java_process.pid), 15) # Send SIGTERM
java_process.wait(timeout=5)
# Clean up temporary files
os.remove(java_file_name) if os.path.exists(java_file_name) else None
os.remove(class_file_name) if os.path.exists(class_file_name) else None
# Also remove AdditionApplication$*.class files if they exist
for f in os.listdir('.'):
if f.startswith('AdditionApplication$') and f.endswith('.class'):
os.remove(f)