This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2022-02-10
Channels
- # announcements (6)
- # architecture (2)
- # babashka (30)
- # beginners (90)
- # calva (21)
- # cider (22)
- # clj-kondo (27)
- # cljs-dev (7)
- # clojure (132)
- # clojure-europe (51)
- # clojure-nl (12)
- # clojure-norway (3)
- # clojure-spec (3)
- # clojure-uk (5)
- # clojurescript (69)
- # cloverage (9)
- # conjure (5)
- # core-async (54)
- # cursive (14)
- # datomic (34)
- # emacs (7)
- # fulcro (10)
- # graalvm (40)
- # graalvm-mobile (2)
- # gratitude (2)
- # improve-getting-started (1)
- # introduce-yourself (1)
- # jobs-discuss (61)
- # leiningen (5)
- # malli (6)
- # off-topic (59)
- # pathom (11)
- # polylith (38)
- # reagent (3)
- # reitit (3)
- # rewrite-clj (3)
- # shadow-cljs (53)
- # tools-build (35)
- # transit (8)
- # vim (62)
- # web-security (26)
- # xtdb (4)
I'm trying to build a project using native-image, and I'm running into a few "Detected a started Thread in the image heap."
errors that seem to originate in clojure.lang.Agent.soloExecutor
(which I assume is due to top-level agent
calls somewhere). My project doesn't make use of agent
, so these errors have to be caused by some dependency. How can I figure out which dependency is causing this, and what can I do about it?
@wombawomba you can find out by excluding certain dependencies from your own program and then bisect and then check the dependencies' source
what you can do about it: fork and/or ask the maintainer to wrap the top level thread in a delay
hmm... it's a pretty complex project so just excluding random dependencies would be a lot of work
surely there must be some way of figuring it out automatically?
another way could be to alter-var-root agent
before you load anything and throw an exception in the agent call and then inspect the stacktrace :)
ah, now we're talking 🙂 I'll try that
another way could be to analyze all your deps with clj-kondo and then filter out the agent calls
alright, the relevant call seems to be here: https://github.com/clojure/tools.logging/blob/master/src/main/clojure/clojure/tools/logging.clj#L30
I can't imagine I'm the only person who's tried to use native-image with a project that uses clojure.tools.logging — could there be some sort of workaround here that doesn't involve patching that library?
perhaps I'm mistaken about what's causing the error?
the full error is:
Error: Detected a started Thread in the image heap. Threads running in the image generator are no longer running at image runtime. To see how this object got instantiated use --trace-object-instantiation=java.lang.Thread. The object was probably created by a class initializer and is reachable from a static field. You can request class initialization at image runtime by using the option --initialize-at-run-time=<class-name>. Or you can write your own initialization methods and call them explicitly from your main entry point.
Trace: Object was reached by
reading field java.util.concurrent.ThreadPoolExecutor$Worker.thread of
constant java.util.concurrent.ThreadPoolExecutor$Worker@61cb0266 reached by
reading field java.util.HashMap$Node.key of
constant java.util.HashMap$Node@21bfcd3e reached by
indexing into array
constant java.util.HashMap$Node[]@638fd262 reached by
reading field java.util.HashMap.table of
constant java.util.HashMap@4369073a reached by
reading field java.util.HashSet.map of
constant java.util.HashSet@599be4fb reached by
reading field java.util.concurrent.ThreadPoolExecutor.workers of
constant java.util.concurrent.ThreadPoolExecutor@3ac5047b reached by
reading field clojure.lang.Agent.soloExecutor
(let [f (binding-conveyor-fn f)
fut (.submit clojure.lang.Agent/soloExecutor ^Callable f)]
...I just realized I'd done a bad copy-paste — rebuilding now with --trace-object-instantiation=java.lang.Thread
to see if that helps
ah yeah that makes sense
I'll try the alter-var-root
trick with future
as well
I've certainly come across future calls on the top level which I had to patch. E.g. in reply
yeah that's actually it haha
@wombawomba btw, I think you'd have to patch future-call
since that's a function
the project has a dependency on reply
perhaps I'll just get rid of that for the native-image build
it's a web service
the reply dependency is for debugging/maintenence tasks
I have a native version of reply, made it for fun, but never released and and I changed the top level future's into delays, worked fine
but for images it's really the best if I you can get rid of dependencies if you don't need them
yeah I'm gonna try that
speaking of which, is there a way to exclude require
s just for the native-image build?
you can make the require conditional on some system property.
Property name: "org.graalvm.nativeimage.imagecode"
Values: "buildtime", "runtime"
Property name: "org.graalvm.nativeimage.kind"
Values: "shared", "executable"
I've also got a related library here: https://github.com/borkdude/dynaload that's designed for optimal graal images.
...custom reader conditionals sure would be useful for situations like these
I'll take a look at your library, thanks