CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pyjnius

A Python module to access Java classes as Python classes using JNI.

Pending
Overview
Eval results
Files

utilities.mddocs/

Object Management and Utilities

PyJNIus provides essential utilities for managing Java object lifecycle, type casting, class discovery, and exception handling. These functions enable fine-grained control over Java interoperability and proper resource management.

Capabilities

Type Casting

Function for casting Java objects between different Java class types.

def cast(target_class: type, obj: object) -> object:
    """
    Cast Java object to target Java class type.
    
    Args:
        target_class: Target Java class (created with autoclass or manual definition)
        obj: Java object to cast
        
    Returns:
        Java object cast to target type
        
    Raises:
        JavaException: If cast is invalid (ClassCastException)
    """

Usage Examples:

from jnius import autoclass, cast

# Get Java classes
Object = autoclass('java.lang.Object')
String = autoclass('java.lang.String')
ArrayList = autoclass('java.util.ArrayList')
List = autoclass('java.util.List')

# Create objects
text = String('Hello')
list_obj = ArrayList()

# Cast String to Object (upcast - always safe)
obj = cast(Object, text)
print(obj.toString())  # Hello

# Cast ArrayList to List interface (upcast - always safe)
list_interface = cast(List, list_obj)
list_interface.add('item')

# Cast Object back to String (downcast - requires runtime check)
try:
    original_text = cast(String, obj)
    print(original_text.length())  # 5
except JavaException as e:
    print(f"Cast failed: {e}")

# Invalid cast example
try:
    invalid = cast(ArrayList, text)  # Will fail
except JavaException as e:
    print(f"Invalid cast: {e}")  # ClassCastException

Class Discovery

Function for finding and loading Java classes by name.

def find_javaclass(class_name: str) -> object:
    """
    Find and load Java class by fully qualified name.
    
    Args:
        class_name: Fully qualified Java class name (dot notation)
        
    Returns:
        Java Class object, or None if not found
        
    Note:
        Used internally by autoclass and reflection system.
    """

Usage Examples:

from jnius import find_javaclass

# Find standard Java classes
string_class = find_javaclass('java.lang.String')
if string_class:
    print(f"Found class: {string_class.getName()}")  # java.lang.String

# Check if custom class exists
custom_class = find_javaclass('com.example.MyClass')
if custom_class is None:
    print("Custom class not found on classpath")

# Find array classes
string_array_class = find_javaclass('[Ljava.lang.String;')
int_array_class = find_javaclass('[I')

# Find nested classes (use $ separator)
nested_class = find_javaclass('java.util.Map$Entry')

Thread Management

Function for managing JVM thread attachment and detachment.

def detach() -> None:
    """
    Detach current thread from JVM.
    
    Required in multithreaded applications where threads that call Java
    methods need to be properly detached before thread termination.
    
    Note:
        Automatically called on Android for all threads.
        Should be called manually in desktop applications when using
        Java from background threads.
    """

Usage Examples:

import threading
from jnius import autoclass, detach

def background_task():
    try:
        # Use Java classes in background thread
        String = autoclass('java.lang.String')
        result = String('background task')
        print(result.toUpperCase())
    finally:
        # Always detach thread before termination
        detach()

# Start background thread
thread = threading.Thread(target=background_task)
thread.start()
thread.join()

# Example with thread pool
from concurrent.futures import ThreadPoolExecutor

def process_data(data):
    try:
        ArrayList = autoclass('java.util.ArrayList')
        list_obj = ArrayList()
        list_obj.add(data)
        return list_obj.size()
    finally:
        detach()

with ThreadPoolExecutor(max_workers=4) as executor:
    futures = [executor.submit(process_data, f"data_{i}") for i in range(10)]
    results = [future.result() for future in futures]

Exception Handling

Exception wrapper for Java exceptions with Python integration.

class JavaException(Exception):
    """
    Python exception wrapper for Java exceptions.
    
    Attributes:
        classname: Fully qualified name of Java exception class
        innermessage: Original Java exception message
        stacktrace: Java exception stack trace
    """
    
    classname: str      # Java exception class name
    innermessage: str   # Original Java exception message
    stacktrace: str     # Java exception stack trace

Usage Examples:

from jnius import autoclass, JavaException

try:
    # This will throw java.lang.StringIndexOutOfBoundsException
    String = autoclass('java.lang.String')
    text = String('hello')
    char = text.charAt(10)  # Index out of bounds
    
except JavaException as e:
    print(f"Java exception: {e.classname}")
    print(f"Message: {e.innermessage}")
    print(f"Stack trace: {e.stacktrace}")
    
    # Check specific exception types
    if 'StringIndexOutOfBoundsException' in e.classname:
        print("String index was out of bounds")
    
    # Re-raise as Python exception
    raise IndexError(f"Java string index error: {e.innermessage}")

# Exception handling with multiple Java operations
def safe_java_operation():
    try:
        ArrayList = autoclass('java.util.ArrayList')
        HashMap = autoclass('java.util.HashMap')
        
        # Multiple operations that could fail
        list_obj = ArrayList()
        map_obj = HashMap()
        
        # This could throw various exceptions
        list_obj.add(None)  # Might throw NullPointerException in some contexts
        value = map_obj.get('nonexistent')  # Returns null, safe
        
        return list_obj, map_obj
        
    except JavaException as e:
        print(f"Java operation failed: {e.classname} - {e.innermessage}")
        if e.stacktrace:
            print(f"Stack trace: {e.stacktrace}")
        return None, None

Memory Management

Constants and utilities for Java object memory management.

HASHCODE_MAX: int  # Maximum Java hash code value (2^31 - 1)

Usage in Custom Classes:

from jnius import PythonJavaClass, MetaJavaClass, HASHCODE_MAX

class MyPythonJavaClass(PythonJavaClass, metaclass=MetaJavaClass):
    __javaclass__ = 'com/example/MyClass'
    
    def custom_hash(self):
        # Use HASHCODE_MAX for consistent Java-compatible hashing
        return id(self) % HASHCODE_MAX

Advanced Object Management

Local Reference Management: PyJNIus automatically manages JNI local references, but for long-running operations with many Java objects, consider:

# Process objects in batches to avoid local reference exhaustion
def process_large_dataset(data_items):
    batch_size = 100
    results = []
    
    for i in range(0, len(data_items), batch_size):
        batch = data_items[i:i+batch_size]
        
        # Process batch
        batch_results = []
        for item in batch:
            java_obj = create_java_object(item)
            result = java_obj.process()
            batch_results.append(str(result))  # Convert to Python type
            
        results.extend(batch_results)
        
        # Optional: Force garbage collection between batches
        import gc
        gc.collect()
    
    return results

Resource Management Best Practices:

from jnius import autoclass

# Use context managers for closeable resources
def read_file_safely(filename):
    FileInputStream = autoclass('java.io.FileInputStream')
    
    try:
        stream = FileInputStream(filename)
        # Use the stream
        data = []
        while True:
            byte = stream.read()
            if byte == -1:  # EOF
                break
            data.append(byte)
        return bytes(data)
    finally:
        if 'stream' in locals():
            stream.close()

# Or leverage protocol_map for automatic cleanup
def read_file_with_context_manager(filename):
    FileInputStream = autoclass('java.io.FileInputStream')
    
    with FileInputStream(filename) as stream:
        # Stream automatically closed when exiting context
        data = []
        while True:
            byte = stream.read()
            if byte == -1:
                break
            data.append(byte)
        return bytes(data)

Install with Tessl CLI

npx tessl i tessl/pypi-pyjnius

docs

autoclass.md

environment.md

index.md

manual-classes.md

signatures.md

utilities.md

tile.json