babashka 2026-07-10

Is it possible to reify or proxy an interface in Babashka? I'm trying to figure out how to mimic (reify Closeable (close [_] ...)) .

Managed to get it all working 🎉, so I'll be submitting some issues and PRs to Babashka over the next few days.

🎉 1

Yes we can add support for it. It's a closed set that we have to add on a case by case basis. Do you have other interfaces or protocols in there too?

No, just java.io.Closeable, though java.lang.AutoCloseable would work too, and perhaps be more generic.

I guess I also need to proxy InputStream and OutputStream.

I'll update my local bb and see if that's the last thing that's needed to support TeensyP.

All possible I think under certain conditions. It's in impl-Java I think

Is proxy limited as well? I couldn't get that to work with Closeable.

Let me know if you're stuck or just post an issue and I’ll take care of it. Yes similar thing

I've opened up two issues for supporting more lock and more nio classes respectively, and I have the commits ready to go. However, I should try to get TeensyP working first with my local Babashka.

Hm... it seems to expect a babashka.impl.<interface name> for each interface defined, but I don't see where those are defined?

those are likely generated using insn, let me look it up

I had to do this in this way since clojure does not support generating interfaces with default methods

you can add your interface to the list, then regen the stuff, re-install the lib and it should kinda work. test it first by invoking bb on the JVM to save cycles

a PR would work but I'd have to bump the library and publish it first to CI to make the whole CI runnable. You can skip that part in a PR

So before I run script/uberjar I go into impl-java and run bb install?

Aha, that seems to have worked!

🎉 1

Hm, now I'm getting a reflection error for:

(.remove ^Iterator iter)
Is it just that Babashka uses reflection for everything, so even though that's type-hinted, Babashka ignores it?
org.graalvm.nativeimage.MissingReflectionRegistrationError: Cannot reflectively invoke method 'public default void java.util.Iterator.remove()'. To allow this operation, add the following to the 'reflection' section of 'reachability-metadata.json' and rebuild the native image:

  {
    "type": "java.util.Iterator",
    "methods": [
      {
        "name": "remove",
        "parameterTypes": []
      }
    ]
  }

lemme check

we have limited the amount of methods here for some reason but if you add remove to the list, it's going to start to work.

java.util.Iterator
    {:methods [{:name "hasNext"}
               {:name "next"}]}
this is in src/babashka/impl/classes.clj

I was just about to try that 🙂

That solved that issue, at least, but there's a bunch more errors I'll need to pick through.

Ah, some issue with the .attachment method on SelectionKey that Sci doesn't seem to like:

#error {
 :cause "Method attachment on class sun.nio.ch.SelectionKeyImpl not allowed!"
 :data {:type :sci/error, :line nil, :column nil, :file nil}
 :via
 [{:type clojure.lang.ExceptionInfo
   :message "Method attachment on class sun.nio.ch.SelectionKeyImpl not allowed!"
   :data {:type :sci/error, :line nil, :column nil, :file nil}
   :at [sci.impl.utils$throw_error_with_location invokeStatic "utils.cljc"

[sci.impl.evaluator$eval_instance_method_invocation invokeStatic "evaluator.cljc" 260] specifically, looks like

That's the public-fn issue in impl/classes.clj if you cast it to java.nio.channels.SelectionKey in there, (and add reflection support for it), then it'll probably work

Sorry, could you explain a little more?

This the stuff in base-custom-map? Or something else?

ah yes. in GraalVM a lot of type information is erased

soi it can't reflect on the class to see what it's super classes are and then invoke reflection on that instead

so we have to help it a little by upcasting before we do reflection

oh sorry :public-class doh

Ahh, I see

That's solved that one!

I'm now getting an issue where it can't find the wakeup field on the Selector class, unless I explicitly add some extra type hinting in. Do you think that means I need to add Selector to :public-class as well?

Specifically a java.lang.NoSuchFieldException

which class specifically?

java.nio.channels.Selector

It's one of the new ones I added.

how did you add it?

the config I mean

Come to think of it I had this issue in the test code, too, though at the time I assumed there was something I didn't understand about type hinting in bb.

I don't see wakeup mentioned there?

you can check with java.lang.reflect in bb to see if the field is there maybe>

.wakeup is a method on Selector. I was having issues with both Selector and SelectionKey requiring more aggressive type hinting. However, adding them to :public-class seems to have solved it.

oh I see then it maybe hit a non-public or non-listed subclass?

public reallly means "it's present in our configuration" ;)

Yes, now the test works too. Before I had to add in more type hints on things where the type should be known, which I assumed was just a quirk of bb.

yeah it's just a limitation of the native-image stripping all the things away

what is the subclass you hit, it didn't say?

It didn't say for Selector

Now the tests seem to pass, though the tests hang, so maybe it's not correctly cleaning up the executor. I'll continue to investigate, but looks like I'm almost there. Thank you for your help!

exciting :)

maybe autocloasable doesn't work properly yet or so? isolated test could help

Yes, perhaps! I'll call it a night for now though, and investigate tomorrow.

👍 1