Repository navigation
Error on JavaCall.init() with Julia >= 1.12 #170
Copy link
Copy link
Open
Description
julia> using JavaCall
julia> JavaCall.init()
ERROR: TaskFailedException
nested task error: BoundsError: attempt to access 1-element Vector{Ptr{JavaCall.JNI.JNIEnv}} at index [2]
Stacktrace:
[1] throw_boundserror(A::Vector{Ptr{JavaCall.JNI.JNIEnv}}, I::Tuple{Int64})
@ Base ./essentials.jl:15
[2] getindex
@ ./essentials.jl:917 [inlined]
[3] getindex
@ ./refpointer.jl:193 [inlined]
[4] attach_current_thread
@ ~/.julia/packages/JavaCall/IAoV2/src/JNI.jl:171 [inlined]
[5] macro expansion
@ ~/.julia/packages/JavaCall/IAoV2/src/JNI.jl:176 [inlined]
[6] (::JavaCall.JNI.var"#attach_threads##0#attach_threads##1"{…})(tid::Int64; onethread::Bool)
@ JavaCall.JNI ./threadingconstructs.jl:276
[7] #attach_threads##0
@ ./threadingconstructs.jl:243 [inlined]
[8] (::Base.Threads.var"#threading_run##0#threading_run##1"{…})()
@ Base.Threads ./threadingconstructs.jl:177
Stacktrace:
[1] threading_run(fun::JavaCall.JNI.var"#attach_threads##0#attach_threads##1"{…}, static::Bool)
@ Base.Threads ./threadingconstructs.jl:196
[2] macro expansion
@ ./threadingconstructs.jl:213 [inlined]
[3] attach_threads
@ ~/.julia/packages/JavaCall/IAoV2/src/JNI.jl:175 [inlined]
[4] init_new_vm(libpath::Tuple{String}, opts::OrderedCollections.OrderedSet{String})
@ JavaCall.JNI ~/.julia/packages/JavaCall/IAoV2/src/JNI.jl:164
[5] _init(opts::OrderedCollections.OrderedSet{String})
@ JavaCall ~/.julia/packages/JavaCall/IAoV2/src/jvm.jl:291
[6] init()
@ JavaCall ~/.julia/packages/JavaCall/IAoV2/src/jvm.jl:277
[7] top-level scope
@ REPL[2]:1
Some type information was truncated. Use `show(err)` to see complete types.
julia> versioninfo()
Julia Version 1.12.0-beta1
Commit c175ace780d (2025-04-02 11:19 UTC)
Build Info:
Official https://julialang.org release
Platform Info:
OS: Linux (x86_64-linux-gnu)
CPU: 16 × AMD Ryzen 7 8840HS w/ Radeon 780M Graphics
WORD_SIZE: 64
LLVM: libLLVM-18.1.7 (ORCJIT, znver3)
GC: Built with stock GC
Threads: 1 default, 1 interactive, 1 GC (on 16 virtual cores)
Environment:
JULIA_REVISE_POLL = 1
JULIA_COPY_STACKS = 1This is probably because of
Lines 168 to 178 in 2f1824f
| function attach_current_thread(ppenv_thread = Ref{Ptr{JNIEnv}}(C_NULL)) | |
| res = ccall(jvmfunc[].AttachCurrentThread, Cint, (Ptr{Nothing}, Ptr{Ptr{JNIEnv}}, Ptr{Nothing}), ppjvm[], ppenv_thread, C_NULL) | |
| res < 0 && throw(JNIError("Unable to attach thread id: $(Threads.threadid())")) | |
| return ppenv_thread[] | |
| end | |
| function attach_threads() | |
| Threads.@threads for i=1:Threads.nthreads() | |
| attach_current_thread(Ref(ppenv, Threads.threadid() )) | |
| end | |
| end |
See JuliaFolds2/OhMyThreads.jl#136 (comment) and https://julialang.org/blog/2023/07/PSA-dont-use-threadid/
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
mkitti commentedon Apr 22, 2025
While I think we might be able to fix the bounds error, this really deserves a full engineering review.
My priority here would be to address the "single-thread" case, which I'm not entirely sure exists anymore.
It may be that the Julia and Java signal handling facilities in each thread / task stack have now become incompatible. We would need to build some sort of signal chaining mechanism.
Could I ask about your application? How do you intend to use this?
mkitti commentedon Apr 22, 2025
As for fixing the bounds error, my current thought is that should consider putting for the JNI environment in a
Dict{Int}arnaud-ma commentedon Apr 22, 2025
I have a simple use case, I just want to be able to run JavaCall. If possible with Julia multithreading enabled, so I can use JavaCall in one place and multithreading in another unrelated place, all while being in the same Julia session. But if that's really not possible, having a clear warning/error message would be nice.
To summarize it would be good if it could work at least for the single-threaded case. And in the other case, give an explicit error message.
mkitti commentedon Apr 23, 2025
The most likely scenario is that might be able to support calling Java from a single thread / task, particular the root task running on thread 1, perhaps even without
JULIA_COPY_STACKSdepending on the operating system. One model would be to run a service on a sticky Julia root task that communicates with other Julia tasks while also remaining on the initial thread. To call Java, the other tasks, possibly on other threads, would first communicate with the service on the root task, which would then communicate with the JVM.I prototyped what such a service might look like here:
https://github.com/mkitti/TaskWorkers.jl
The issue is that both Julia and Java seem to be trying to use the same signalling resources (e.g.
sigaction) which requires installing a signal handler on the stack.Java actually does have a facility for this called signal chaining:
https://docs.oracle.com/javase/8/docs/technotes/guides/vm/signal-chaining.html
We might need to figure out how to implement a similar facility for Julia to keep this working.
I need to review this model in light of the interactive thread pool.
ViralBShah commentedon Nov 4, 2025
Works fine if you start Julia single threaded (as I am now doing in the CI). This needs to be noted in the README and the docs.