0
# Object Management and Utilities
1
2
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.
3
4
## Capabilities
5
6
### Type Casting
7
8
Function for casting Java objects between different Java class types.
9
10
```python { .api }
11
def cast(target_class: type, obj: object) -> object:
12
"""
13
Cast Java object to target Java class type.
14
15
Args:
16
target_class: Target Java class (created with autoclass or manual definition)
17
obj: Java object to cast
18
19
Returns:
20
Java object cast to target type
21
22
Raises:
23
JavaException: If cast is invalid (ClassCastException)
24
"""
25
```
26
27
**Usage Examples:**
28
29
```python
30
from jnius import autoclass, cast
31
32
# Get Java classes
33
Object = autoclass('java.lang.Object')
34
String = autoclass('java.lang.String')
35
ArrayList = autoclass('java.util.ArrayList')
36
List = autoclass('java.util.List')
37
38
# Create objects
39
text = String('Hello')
40
list_obj = ArrayList()
41
42
# Cast String to Object (upcast - always safe)
43
obj = cast(Object, text)
44
print(obj.toString()) # Hello
45
46
# Cast ArrayList to List interface (upcast - always safe)
47
list_interface = cast(List, list_obj)
48
list_interface.add('item')
49
50
# Cast Object back to String (downcast - requires runtime check)
51
try:
52
original_text = cast(String, obj)
53
print(original_text.length()) # 5
54
except JavaException as e:
55
print(f"Cast failed: {e}")
56
57
# Invalid cast example
58
try:
59
invalid = cast(ArrayList, text) # Will fail
60
except JavaException as e:
61
print(f"Invalid cast: {e}") # ClassCastException
62
```
63
64
### Class Discovery
65
66
Function for finding and loading Java classes by name.
67
68
```python { .api }
69
def find_javaclass(class_name: str) -> object:
70
"""
71
Find and load Java class by fully qualified name.
72
73
Args:
74
class_name: Fully qualified Java class name (dot notation)
75
76
Returns:
77
Java Class object, or None if not found
78
79
Note:
80
Used internally by autoclass and reflection system.
81
"""
82
```
83
84
**Usage Examples:**
85
86
```python
87
from jnius import find_javaclass
88
89
# Find standard Java classes
90
string_class = find_javaclass('java.lang.String')
91
if string_class:
92
print(f"Found class: {string_class.getName()}") # java.lang.String
93
94
# Check if custom class exists
95
custom_class = find_javaclass('com.example.MyClass')
96
if custom_class is None:
97
print("Custom class not found on classpath")
98
99
# Find array classes
100
string_array_class = find_javaclass('[Ljava.lang.String;')
101
int_array_class = find_javaclass('[I')
102
103
# Find nested classes (use $ separator)
104
nested_class = find_javaclass('java.util.Map$Entry')
105
```
106
107
### Thread Management
108
109
Function for managing JVM thread attachment and detachment.
110
111
```python { .api }
112
def detach() -> None:
113
"""
114
Detach current thread from JVM.
115
116
Required in multithreaded applications where threads that call Java
117
methods need to be properly detached before thread termination.
118
119
Note:
120
Automatically called on Android for all threads.
121
Should be called manually in desktop applications when using
122
Java from background threads.
123
"""
124
```
125
126
**Usage Examples:**
127
128
```python
129
import threading
130
from jnius import autoclass, detach
131
132
def background_task():
133
try:
134
# Use Java classes in background thread
135
String = autoclass('java.lang.String')
136
result = String('background task')
137
print(result.toUpperCase())
138
finally:
139
# Always detach thread before termination
140
detach()
141
142
# Start background thread
143
thread = threading.Thread(target=background_task)
144
thread.start()
145
thread.join()
146
147
# Example with thread pool
148
from concurrent.futures import ThreadPoolExecutor
149
150
def process_data(data):
151
try:
152
ArrayList = autoclass('java.util.ArrayList')
153
list_obj = ArrayList()
154
list_obj.add(data)
155
return list_obj.size()
156
finally:
157
detach()
158
159
with ThreadPoolExecutor(max_workers=4) as executor:
160
futures = [executor.submit(process_data, f"data_{i}") for i in range(10)]
161
results = [future.result() for future in futures]
162
```
163
164
### Exception Handling
165
166
Exception wrapper for Java exceptions with Python integration.
167
168
```python { .api }
169
class JavaException(Exception):
170
"""
171
Python exception wrapper for Java exceptions.
172
173
Attributes:
174
classname: Fully qualified name of Java exception class
175
innermessage: Original Java exception message
176
stacktrace: Java exception stack trace
177
"""
178
179
classname: str # Java exception class name
180
innermessage: str # Original Java exception message
181
stacktrace: str # Java exception stack trace
182
```
183
184
**Usage Examples:**
185
186
```python
187
from jnius import autoclass, JavaException
188
189
try:
190
# This will throw java.lang.StringIndexOutOfBoundsException
191
String = autoclass('java.lang.String')
192
text = String('hello')
193
char = text.charAt(10) # Index out of bounds
194
195
except JavaException as e:
196
print(f"Java exception: {e.classname}")
197
print(f"Message: {e.innermessage}")
198
print(f"Stack trace: {e.stacktrace}")
199
200
# Check specific exception types
201
if 'StringIndexOutOfBoundsException' in e.classname:
202
print("String index was out of bounds")
203
204
# Re-raise as Python exception
205
raise IndexError(f"Java string index error: {e.innermessage}")
206
207
# Exception handling with multiple Java operations
208
def safe_java_operation():
209
try:
210
ArrayList = autoclass('java.util.ArrayList')
211
HashMap = autoclass('java.util.HashMap')
212
213
# Multiple operations that could fail
214
list_obj = ArrayList()
215
map_obj = HashMap()
216
217
# This could throw various exceptions
218
list_obj.add(None) # Might throw NullPointerException in some contexts
219
value = map_obj.get('nonexistent') # Returns null, safe
220
221
return list_obj, map_obj
222
223
except JavaException as e:
224
print(f"Java operation failed: {e.classname} - {e.innermessage}")
225
if e.stacktrace:
226
print(f"Stack trace: {e.stacktrace}")
227
return None, None
228
```
229
230
### Memory Management
231
232
Constants and utilities for Java object memory management.
233
234
```python { .api }
235
HASHCODE_MAX: int # Maximum Java hash code value (2^31 - 1)
236
```
237
238
**Usage in Custom Classes:**
239
240
```python
241
from jnius import PythonJavaClass, MetaJavaClass, HASHCODE_MAX
242
243
class MyPythonJavaClass(PythonJavaClass, metaclass=MetaJavaClass):
244
__javaclass__ = 'com/example/MyClass'
245
246
def custom_hash(self):
247
# Use HASHCODE_MAX for consistent Java-compatible hashing
248
return id(self) % HASHCODE_MAX
249
```
250
251
### Advanced Object Management
252
253
**Local Reference Management:**
254
PyJNIus automatically manages JNI local references, but for long-running operations with many Java objects, consider:
255
256
```python
257
# Process objects in batches to avoid local reference exhaustion
258
def process_large_dataset(data_items):
259
batch_size = 100
260
results = []
261
262
for i in range(0, len(data_items), batch_size):
263
batch = data_items[i:i+batch_size]
264
265
# Process batch
266
batch_results = []
267
for item in batch:
268
java_obj = create_java_object(item)
269
result = java_obj.process()
270
batch_results.append(str(result)) # Convert to Python type
271
272
results.extend(batch_results)
273
274
# Optional: Force garbage collection between batches
275
import gc
276
gc.collect()
277
278
return results
279
```
280
281
**Resource Management Best Practices:**
282
283
```python
284
from jnius import autoclass
285
286
# Use context managers for closeable resources
287
def read_file_safely(filename):
288
FileInputStream = autoclass('java.io.FileInputStream')
289
290
try:
291
stream = FileInputStream(filename)
292
# Use the stream
293
data = []
294
while True:
295
byte = stream.read()
296
if byte == -1: # EOF
297
break
298
data.append(byte)
299
return bytes(data)
300
finally:
301
if 'stream' in locals():
302
stream.close()
303
304
# Or leverage protocol_map for automatic cleanup
305
def read_file_with_context_manager(filename):
306
FileInputStream = autoclass('java.io.FileInputStream')
307
308
with FileInputStream(filename) as stream:
309
# Stream automatically closed when exiting context
310
data = []
311
while True:
312
byte = stream.read()
313
if byte == -1:
314
break
315
data.append(byte)
316
return bytes(data)
317
```