clojure 2025-10-07

If I'm doing some intentional, manual reflection to build up a small index of data for enhanced interop purposes, but only once when the JVM starts, would that cause concern for anyone? What if I rebound the warn on reflection var so it stays silent during this limited window and only during this window?

For what it's worth, I'm not a huge fan of rebinding the var because I'm concerned it can hide bugs.

You can (set! **warn-on-reflection** false) for the entire namespace where you do controlled reflection.

Another thought just occurred to me. What if my function that does controlled reflection is called in a macro? Then it only runs at source load / compile time. Once Clojure's runtime is bootstrapped we're finished. Perhaps then a binding is fine?

My concern is not so much the code locality of the reflection (e.g. the namespace), but the temporary locality of it (e.g. app lifecycle). I don't want it accidentally being invoked in the hot path.

You can always use clojure.reflect namespace and basic Java reflection methods directly and not care about anything else.

My concern is not so much the code locality of the reflection (e.g. the namespace), but the temporary locality of it (e.g. app lifecycle). I don't want it accidentally being invoked in the hot path.
Then it's better to split it into separate functions explicitly.

Does Clojure reflect have some optimizations or guards that would help me? I thought any form of JVM reflection, especially if you're iterating through classes and their methods, was expensive?

Or is the issue only when the Clojure compiler generates reflective code?

It's more expensive than direct calls, sure. But I assumed that your problem is only with the optics of using reflection where you know it's fine but you don't want spurious warnings.

Tbh, I don't understand how you can have the same piece of code that is going to reflect during startup/load-time but not reflect later.

It would just call the Java reflection APIs directly, maybe (bean ...) some methods, and extract data for use later on.

Maybe set up some functions for use inside proxies. Stuff like that.

So you just want to ensure this code is never called at runtime, after initialization?

If possible, yes.

I'm not sure there are a ton of options besides just stating it in the docstring.

You could update a reference to indicate that it's been called. Something like:

(let [have-run (atom false)]
  (defn initialize-only-once []
    (when-not @have-run
      (println "initializing...")
      (reset! have-run true))))

(initialize-only-once)
;; prints "initializing..."
;; => true
(initialize-only-once)
;; => nil

Actually that's a good point. I can probably use a delay in conjunction with a macro. Originally I wasn't fond of using a delay because I want this done at start time, not in response to the first query. But using both might be the way.