Hello,
I am experiencing randomly failing pytests while using the orekit jpype interface.
For reference I am using:
orekit_jpype==13.1.4.0
pytest==9.0.3
pytest-cov==7.1.0
python==3.13.13
The crash looks like the following:
Thread 0x000000017f703000 (most recent call first):
Thread 0x0000000171737000 (most recent call first):
File “/Applications/miniforge3/envs/adcstools/lib/python3.13/threading.py”, line 363 in wait
File “/Applications/miniforge3/envs/adcstools/lib/python3.13/threading.py”, line 660 in wait
…
Thread 0x000000017072b000 (most recent call first):
File “/Applications/miniforge3/envs/adcstools/lib/python3.13/threading.py”, line 363 in wait
File “/Applications/miniforge3/envs/adcstools/lib/python3.13/threading.py”, line 660 in wait
…
Thread 0x000000016f71f000 (most recent call first):
File “/Users/pcaputo/.cursor/extensions/ms-python.debugpy-2025.18.0-darwin-arm64/bundled/libs/debugpy/_vendored/pydevd/_pydevd_bundle/pydevd_comm.py”, line 227 in _read_line
…
etc.
The steps to reproduce are simply to write any test that eventually calls orekit_jpype (e.g. propagating a simple orbit). This happens randomly and at different times, sometime it does not happen.
This most likely happens because of race conditions between the python garbage collector and the jpype JNI. I have noticed that this is a known issue already (c.f. Pytest fails with access violation? - #6 by bullat ) but I have found a workaround and want to share it though clearly a more proper solution would be better.
On the idea that is a race condition, I have tried to fully initialise Orekit as soon as possible when pytest starts as well as limit as possible things which could interfere. I found that the crashes basically stop if:
- pytest is run with the option `-p no:jaxtyping` ← this already improves a lot the crashes
- in the `conftest.py` which initialises the tests which eventually call orekit, make sure to initialise the JVM passing the following arguments to orekit_jpype.initVM(vmargs=_JVM_ARGS)
@conftest.py
_JVM_BASE_VMARGS = "-Xrs,-XX:-UsePerfData,-XX:+UseSerialGC,-XX:-UseCompressedOops"
orekit_jpype.initVM(vmargs=_JVM_ARGS)
I noticed that adding `-Xint` while running pytest with the debugger also help, though I did not verify if it is actually needed.
I also added the following to ensure classes are initialised in Java as soon as possible:
@conftest.py
_PRELOAD_CLASSES = [
"org.hipparchus.geometry.euclidean.threed.Vector3D",
"org.orekit.bodies.CelestialBodyFactory",
...
]
for _cn in _PRELOAD_CLASSES:
with contextlib.suppress(Exception):
jpype.JClass(_cn)
gc.collect()
gc.freeze()
gc.disable()
I suppose adding the preload of the classes is what fixed
This whole workaround is quite cumbersome, especially because the imports need to be updated twice, in the jpype JClass and in the python import. But it finally worked for me, making the difference of keep on using the python wrapper.
I hope this can help those who want to use the python orekit wrapper and give some insights on actually fixing the root cause. I will be looking forward a real fix!