0
# Classpath and Import Management
1
2
Manage Java classpath, configure import paths, and customize class loading behavior for Python-Java integration. This module provides comprehensive control over how Java classes are discovered and loaded within the JPype environment.
3
4
## Capabilities
5
6
### Classpath Management
7
8
Functions for managing Java classpath during runtime.
9
10
```python { .api }
11
def addClassPath(path):
12
"""Add paths to Java classpath.
13
14
Args:
15
path: String path or list of paths to add to classpath.
16
Can be JAR files, directories, or wildcards.
17
18
Raises:
19
RuntimeError: If JVM is already started (classpath must be set before JVM starts)
20
TypeError: If path is not string or list
21
22
Example:
23
addClassPath("/path/to/mylib.jar")
24
addClassPath(["/path/to/lib1.jar", "/path/to/lib2.jar"])
25
addClassPath("/path/to/libs/*")
26
"""
27
28
def getClassPath(env: bool = True) -> list:
29
"""Get full Java classpath.
30
31
Args:
32
env: If True, include system classpath from environment
33
34
Returns:
35
list: List of classpath entries
36
37
Example:
38
classpath = getClassPath()
39
print("Classpath entries:", classpath)
40
"""
41
```
42
43
### Import Customization and Standard Imports
44
45
Advanced import management, customization system, and Python-style Java imports.
46
47
```python { .api }
48
# From jpype.imports module - enables Python-style Java imports
49
import jpype.imports # Enables: from java.lang import String
50
51
def registerImportCustomizer(customizer):
52
"""Register a custom import handler.
53
54
Args:
55
customizer: Import customizer instance
56
"""
57
58
def registerDomain(domain: str):
59
"""Register an import domain.
60
61
Args:
62
domain: Domain name for import organization
63
"""
64
65
class JImportCustomizer:
66
"""Base class for import customizers.
67
68
Allows customization of how Java classes are imported and accessed.
69
"""
70
71
def canCustomize(self, name: str) -> bool:
72
"""Check if this customizer can handle the given name.
73
74
Args:
75
name: Class or package name
76
77
Returns:
78
bool: True if this customizer can handle the name
79
"""
80
81
def getClass(self, name: str):
82
"""Get customized class for the given name.
83
84
Args:
85
name: Class name to customize
86
87
Returns:
88
Customized class object
89
"""
90
```
91
92
## Usage Examples
93
94
### Basic Classpath Management
95
96
```python
97
import jpype
98
99
# Add classpath before starting JVM
100
jpype.addClassPath("/path/to/myapp.jar")
101
jpype.addClassPath("/path/to/libs/database-driver.jar")
102
jpype.addClassPath("/path/to/config/")
103
104
# Add multiple paths at once
105
library_paths = [
106
"/opt/myapp/lib/core.jar",
107
"/opt/myapp/lib/utils.jar",
108
"/opt/myapp/plugins/"
109
]
110
jpype.addClassPath(library_paths)
111
112
# Use wildcards for all JARs in directory
113
jpype.addClassPath("/opt/myapp/lib/*")
114
115
# Start JVM with configured classpath
116
jpype.startJVM()
117
118
# Verify classpath
119
classpath = jpype.getClassPath()
120
print("Active classpath entries:")
121
for entry in classpath:
122
print(f" {entry}")
123
124
jpype.shutdownJVM()
125
```
126
127
### Dynamic Library Loading
128
129
```python
130
import jpype
131
import os
132
133
def load_application_libraries(app_home):
134
"""Load all application libraries from standard layout."""
135
lib_dir = os.path.join(app_home, "lib")
136
config_dir = os.path.join(app_home, "config")
137
plugins_dir = os.path.join(app_home, "plugins")
138
139
# Add core libraries
140
if os.path.exists(lib_dir):
141
jpype.addClassPath(f"{lib_dir}/*")
142
143
# Add configuration directory
144
if os.path.exists(config_dir):
145
jpype.addClassPath(config_dir)
146
147
# Add plugin directory
148
if os.path.exists(plugins_dir):
149
jpype.addClassPath(f"{plugins_dir}/*")
150
151
# Configure application
152
app_home = "/opt/myapplication"
153
load_application_libraries(app_home)
154
155
jpype.startJVM()
156
157
# Now can access application classes
158
MyApp = jpype.JClass("com.mycompany.myapp.Application")
159
app = MyApp()
160
app.initialize()
161
162
jpype.shutdownJVM()
163
```
164
165
### Working with JAR Files
166
167
```python
168
import jpype
169
import zipfile
170
import os
171
172
def add_jar_with_verification(jar_path):
173
"""Add JAR file to classpath with verification."""
174
if not os.path.exists(jar_path):
175
print(f"Warning: JAR file not found: {jar_path}")
176
return False
177
178
# Verify it's a valid ZIP/JAR file
179
try:
180
with zipfile.ZipFile(jar_path, 'r') as jar:
181
# Check for manifest
182
if 'META-INF/MANIFEST.MF' in jar.namelist():
183
print(f"Adding JAR: {jar_path}")
184
jpype.addClassPath(jar_path)
185
return True
186
else:
187
print(f"Warning: No manifest found in {jar_path}")
188
return False
189
except zipfile.BadZipFile:
190
print(f"Error: Invalid JAR file: {jar_path}")
191
return False
192
193
# Add JARs with verification
194
jar_files = [
195
"/path/to/app-core-1.0.jar",
196
"/path/to/database-connector-2.1.jar",
197
"/path/to/logging-framework-3.0.jar"
198
]
199
200
for jar_file in jar_files:
201
add_jar_with_verification(jar_file)
202
203
jpype.startJVM()
204
jpype.shutdownJVM()
205
```
206
207
### Environment-Based Configuration
208
209
```python
210
import jpype
211
import os
212
213
def configure_classpath_from_environment():
214
"""Configure classpath from environment variables."""
215
216
# Standard Java classpath
217
java_classpath = os.environ.get('CLASSPATH', '')
218
if java_classpath:
219
for path in java_classpath.split(os.pathsep):
220
jpype.addClassPath(path)
221
222
# Application-specific classpath
223
app_classpath = os.environ.get('MYAPP_CLASSPATH', '')
224
if app_classpath:
225
for path in app_classpath.split(os.pathsep):
226
jpype.addClassPath(path)
227
228
# Library directory from environment
229
lib_home = os.environ.get('MYAPP_LIB_HOME')
230
if lib_home and os.path.exists(lib_home):
231
jpype.addClassPath(f"{lib_home}/*")
232
233
# Configure from environment
234
configure_classpath_from_environment()
235
236
jpype.startJVM()
237
238
# Check what was loaded
239
current_classpath = jpype.getClassPath()
240
print("Loaded classpath from environment:")
241
for entry in current_classpath:
242
print(f" {entry}")
243
244
jpype.shutdownJVM()
245
```
246
247
### Custom Import Handling
248
249
```python
250
import jpype
251
from jpype import JImportCustomizer, registerImportCustomizer
252
253
class DatabaseDriverCustomizer(JImportCustomizer):
254
"""Custom import handler for database drivers."""
255
256
def canCustomize(self, name):
257
return name.startswith("com.database.driver")
258
259
def getClass(self, name):
260
# Custom logic for loading database drivers
261
print(f"Loading database driver: {name}")
262
# Could add special initialization, connection pooling, etc.
263
return jpype.JClass(name)
264
265
class CacheFrameworkCustomizer(JImportCustomizer):
266
"""Custom import handler for caching framework."""
267
268
def canCustomize(self, name):
269
return name.startswith("com.cache.framework")
270
271
def getClass(self, name):
272
print(f"Loading cache framework class: {name}")
273
# Could add configuration, monitoring, etc.
274
return jpype.JClass(name)
275
276
# Register customizers before starting JVM
277
registerImportCustomizer(DatabaseDriverCustomizer())
278
registerImportCustomizer(CacheFrameworkCustomizer())
279
280
# Add required JARs
281
jpype.addClassPath("/opt/database/driver.jar")
282
jpype.addClassPath("/opt/cache/framework.jar")
283
284
jpype.startJVM()
285
286
# Import will use customizers
287
DatabaseConnection = jpype.JClass("com.database.driver.Connection")
288
CacheManager = jpype.JClass("com.cache.framework.Manager")
289
290
jpype.shutdownJVM()
291
```
292
293
### Classpath Debugging
294
295
```python
296
import jpype
297
import sys
298
import os
299
300
def debug_classpath():
301
"""Debug classpath configuration and class loading."""
302
303
print("=== Classpath Debug Information ===")
304
305
# Show system classpath
306
system_cp = os.environ.get('CLASSPATH', 'Not set')
307
print(f"System CLASSPATH: {system_cp}")
308
309
# Show JPype classpath before JVM start
310
print("\nJPype classpath (before JVM start):")
311
try:
312
cp_before = jpype.getClassPath()
313
for i, entry in enumerate(cp_before):
314
print(f" {i}: {entry}")
315
except:
316
print(" No classpath set yet")
317
318
# Start JVM
319
jpype.startJVM()
320
321
# Show final classpath
322
print("\nFinal JVM classpath:")
323
cp_after = jpype.getClassPath()
324
for i, entry in enumerate(cp_after):
325
exists = "✓" if os.path.exists(entry) else "✗"
326
print(f" {i}: {exists} {entry}")
327
328
# Test class loading
329
print("\n=== Class Loading Tests ===")
330
331
test_classes = [
332
"java.lang.String",
333
"java.util.ArrayList",
334
"java.sql.Connection"
335
]
336
337
for class_name in test_classes:
338
try:
339
cls = jpype.JClass(class_name)
340
print(f"✓ {class_name}: {cls}")
341
except Exception as e:
342
print(f"✗ {class_name}: {e}")
343
344
jpype.shutdownJVM()
345
346
# Add some test JARs
347
jpype.addClassPath("/usr/share/java/*") # Common system JARs
348
349
debug_classpath()
350
```
351
352
### Conditional Library Loading
353
354
```python
355
import jpype
356
import os
357
import platform
358
359
def load_platform_specific_libraries():
360
"""Load libraries based on platform and availability."""
361
362
system = platform.system().lower()
363
arch = platform.machine().lower()
364
365
# Platform-specific native libraries
366
native_lib_dirs = {
367
'windows': [
368
"C:/Program Files/MyApp/lib/windows",
369
f"C:/Program Files/MyApp/lib/windows-{arch}"
370
],
371
'linux': [
372
"/usr/lib/myapp",
373
f"/usr/lib/myapp/{arch}",
374
"/opt/myapp/lib"
375
],
376
'darwin': [
377
"/usr/local/lib/myapp",
378
"/opt/myapp/lib"
379
]
380
}
381
382
# Add platform-specific paths
383
for lib_dir in native_lib_dirs.get(system, []):
384
if os.path.exists(lib_dir):
385
jpype.addClassPath(f"{lib_dir}/*")
386
print(f"Added platform library: {lib_dir}")
387
388
# Feature-based loading
389
optional_features = {
390
'database': ['/opt/db-drivers/*', '/usr/share/java/jdbc/*'],
391
'xml': ['/opt/xml-libs/*', '/usr/share/java/xml/*'],
392
'crypto': ['/opt/crypto-libs/*', '/usr/share/java/security/*']
393
}
394
395
# Load based on environment flags
396
for feature, paths in optional_features.items():
397
env_var = f"ENABLE_{feature.upper()}"
398
if os.environ.get(env_var, '').lower() in ('1', 'true', 'yes'):
399
for path in paths:
400
# Extract directory from wildcard pattern
401
dir_path = path.rstrip('/*')
402
if os.path.exists(dir_path):
403
jpype.addClassPath(path)
404
print(f"Added {feature} libraries: {path}")
405
406
# Configure platform-specific loading
407
load_platform_specific_libraries()
408
409
jpype.startJVM()
410
411
# Verify loaded capabilities
412
print("Available capabilities:")
413
capabilities = []
414
415
# Test database
416
try:
417
jpype.JClass("java.sql.DriverManager")
418
capabilities.append("Database/JDBC")
419
except:
420
pass
421
422
# Test XML
423
try:
424
jpype.JClass("javax.xml.parsers.DocumentBuilderFactory")
425
capabilities.append("XML Processing")
426
except:
427
pass
428
429
for capability in capabilities:
430
print(f" ✓ {capability}")
431
432
jpype.shutdownJVM()
433
```
434
435
### Python-Style Java Imports
436
437
```python
438
import jpype
439
import jpype.imports # Enable Python-style imports
440
441
jpype.startJVM()
442
443
# Standard Python import syntax for Java classes
444
from java.lang import String, System, Math
445
from java.util import ArrayList, HashMap
446
from javax.swing import JFrame, JButton
447
448
# Use imported classes directly
449
text = String("Hello from Java")
450
list_obj = ArrayList()
451
list_obj.add("Python")
452
list_obj.add("Java")
453
454
# System access
455
System.out.println("Hello World")
456
result = Math.sqrt(16.0)
457
458
# Import with aliases
459
from java.util import ArrayList as JavaList
460
from java.util import HashMap as JavaMap
461
462
java_list = JavaList()
463
java_map = JavaMap()
464
465
# Import static methods and fields
466
from java.lang.Math import PI, sqrt, abs
467
from java.lang.System import out
468
469
print(f"PI = {PI}")
470
print(f"sqrt(25) = {sqrt(25.0)}")
471
out.println("Direct access to System.out")
472
473
jpype.shutdownJVM()
474
```