Skip to content

Error on JavaCall.init() with Julia >= 1.12 #170

Description

@arnaud-ma
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 = 1

This is probably because of

JavaCall.jl/src/JNI.jl

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/

Activity

  1. mkitti commented on Apr 22, 2025

    @mkitti
    Member

    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?

  2. mkitti commented on Apr 22, 2025

    @mkitti
    Member

    As for fixing the bounds error, my current thought is that should consider putting for the JNI environment in a Dict{Int}

  3. arnaud-ma commented on Apr 22, 2025

    @arnaud-ma
    Author

    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.

  4. mkitti commented on Apr 23, 2025

    @mkitti
    Member

    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_STACKS depending 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.

  5. ViralBShah commented on Nov 4, 2025

    @ViralBShah
    Member

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions