cemerick / austin

The ClojureScript browser-REPL rebuilt stronger, faster, easier.
510 stars 31 forks source link

Typing (cemerick.austin/repl-env) in Clojure REPL causes OutOfMemoryError #39

Closed ivan closed 10 years ago

ivan commented 10 years ago

Example session: https://www.refheap.com/7d37150b0fbe017920682f9ee/raw

It took me some time to figure out that the problem was caused by the printing of the object, not due to some problem with the repl-env itself.

Not sure if this deserves some kind of warning in the README or a fix to not try to print an infinite amount of text.

If this does not reproduce on your machine, try this on Ubuntu 13.10

git clone https://github.com/ludios/reworld
cd reworld
git checkout 1483b1a6350ef2c950cf2447d940ad308a273b2c
lein repl
(cemerick.austin/repl-env)
ivan commented 10 years ago

jvisualvm shows one thread doing this:

"nREPL-worker-2" #19 daemon prio=5 os_prio=0 tid=0x00007fd78806e000 nid=0x380c runnable [0x00007fd7b0be8000]
java.lang.Thread.State: RUNNABLE
    at clojure.core$meta.invoke(core.clj:205)
    at clojure.core$print_meta.invoke(core_print.clj:65)
    at clojure.core$print_simple.invoke(core_print.clj:127)
    at clojure.core$fn__5398.invoke(core_print.clj:131)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$fn__5406.invoke(core_print.clj:143)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$fn__5426.invoke(core_print.clj:194)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$fn__5426.invoke(core_print.clj:194)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$fn__5426.invoke(core_print.clj:194)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$fn__5426.invoke(core_print.clj:194)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$fn__5406.invoke(core_print.clj:143)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$fn__5426.invoke(core_print.clj:194)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$fn__5406.invoke(core_print.clj:143)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5431.invoke(core_print.clj:207)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$fn__5497.invoke(core_print.clj:383)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$print_map$fn__5428.invoke(core_print.clj:200)
    at clojure.core$print_sequential.invoke(core_print.clj:58)
    at clojure.core$print_map.invoke(core_print.clj:203)
    at clojure.core$fn__5449.invoke(core_print.clj:260)
    at clojure.lang.MultiFn.invoke(MultiFn.java:231)
    at clojure.core$pr_on.invoke(core.clj:3322)
    at clojure.core$pr.invoke(core.clj:3334)
    at clojure.tools.nrepl.middleware.pr_values$pr_values$fn$reify__570$fn__572.invoke(pr_values.clj:23)
    at clojure.tools.nrepl.middleware.pr_values$pr_values$fn$reify__570.send(pr_values.clj:23)
    at clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__591$fn__602.invoke(interruptible_eval.clj:67)
    at clojure.main$repl$read_eval_print__6588.invoke(main.clj:260)
    at clojure.main$repl$fn__6597.invoke(main.clj:277)
    at clojure.main$repl.doInvoke(main.clj:277)
    at clojure.lang.RestFn.invoke(RestFn.java:1096)
    at clojure.tools.nrepl.middleware.interruptible_eval$evaluate$fn__591.invoke(interruptible_eval.clj:56)
    at clojure.lang.AFn.applyToHelper(AFn.java:159)
    at clojure.lang.AFn.applyTo(AFn.java:151)
    at clojure.core$apply.invoke(core.clj:617)
    at clojure.core$with_bindings_STAR_.doInvoke(core.clj:1788)
    at clojure.lang.RestFn.invoke(RestFn.java:425)
    at clojure.tools.nrepl.middleware.interruptible_eval$evaluate.invoke(interruptible_eval.clj:41)
    at clojure.tools.nrepl.middleware.interruptible_eval$interruptible_eval$fn__632$fn__635.invoke(interruptible_eval.clj:171)
    at clojure.core$comp$fn__4154.invoke(core.clj:2330)
    at clojure.tools.nrepl.middleware.interruptible_eval$run_next$fn__625.invoke(interruptible_eval.clj:138)
    at clojure.lang.AFn.run(AFn.java:24)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at java.lang.Thread.run(Thread.java:744)

Locked ownable synchronizers:
    - <0x0000000081253778> (a java.util.concurrent.ThreadPoolExecutor$Worker) 
ivan commented 10 years ago

Looks like the env/*compiler* is unprintable; specifically, the value for the :cljs.analyzer/namespaces key in it.

ivan commented 10 years ago

Some additional debugging info for tracking down the possible ClojureScript problem

user=> (require '[clojure.java.io :refer [writer]])
nil
user=> (def defs (:defs ('cljs.core (:cljs.analyzer/namespaces @(:cljs.env/compiler (cemerick.austin/repl-env))))))
Browser-REPL ready @ http://localhost:52620/4703/repl/start
#'user/defs
user=> (def w (writer "/tmp/cycle"))
#'user/w
user=> (binding [*out* w] (doseq [k defs] (prn k)))
[hit ctrl-c to stop]

I see it looping forever trying to print info about an autogenerated symbol ->t9461, in my case https://www.refheap.com/0361fd0b3d226feb946076d98/raw

dparoulek commented 10 years ago

In case it's helpful: When I use [org.clojure/clojurescript "0.0-2030"], then (cemerick.austin/repl-env) works fine. But when I use [org.clojure/clojurescript "0.0-2134"], I also see a Java Heap Space OutOfMemory error.

cemerick commented 10 years ago

256MB is the recommended heap size when doing ClojureScript compilation; that's likely overkill, but should resolve any OutOfMemoryErrors encountered when using Austin. Add :jvm-opts ["-Xmx256m"] to your project.clj.

dparoulek commented 10 years ago

When I switch to 2134, I can still run lein cljsbuild once and lein trampoline cljsbuild auto so I don't think it's a compilation issue.

The OutOfMemory error happens when I try to eval (cemerick.austin/repl-env).

With max heap size set to 256, I get OutOfMemoryError. When I set max heap size to 1024 I have to wait a bit longer, but I still see the OutOfMemoryError.

I can consistently reproduce this by creating a project:

lein new replenv

And then use the project.clj here (and also pasted an example of a repl session): https://gist.github.com/dparoulek/8919700

I'm using a new mac book pro, with jdk1.6.0_65.

I'm pretty new to clojurescript so I definitely might be overlooking something obvious, but seems to be an issue between newer clojurescript versions and austin, maybe? Please let me know if I can help by sending more info or testing with different versions.

repl-env works great with v2030 and it's so much fun to do live coding and see it show up in the browser! Thanks again!

Dave

cemerick commented 10 years ago

Try binding the REPL environment to a var to prevent it from printing, e.g. (def env (cemerick.austin/repl-env)).

I'm using 2156 at the moment, which works well. Give that a shot.

dparoulek commented 10 years ago

New it must be something simple. That worked, thanks!

cursork commented 10 years ago

It seems fairly easy to accidentally print a repl-env? It has happened a few times for me and is something I tend to forget that I shouldn't do.

I'm currently using this as a work-around:

(defmethod print-method cemerick.austin.BrowserEnv
  [b w]
  (.write w (str "#<BrowserEnv " b ">")))