Using Clojure To Debug Java Apps
I have been using the Clojure REPL to debug a large Java server app. It's great for exploratory testing and for validating assumptions about how the system works. I wanted to post the code here in case someone else finds this useful. 1. Stick this in a class that is loaded early in the server/app. public static class Repl { public static final String PORT = "18081"; public static final String NS = "user"; private final String initResult; public String getInitResult() { return initResult; } public Object invoke(String fn) { try { return clojure.lang.RT.var(NS, fn).invoke(); } catch (Exception e) { return null; } } public Object invoke(String fn, Object arg1) { try { return clojure.lang.RT.var(NS, fn).invoke(arg1); } catch (Exception e) { return null; } } public Object invoke(String fn, Object arg1, Object arg2) { try { return clojure.lang.RT.var(NS, fn).invoke(arg1, arg2); } catch (Exception e) { return null; } } public Object invoke(String fn, Object arg1, Object arg2, Object arg3) { try { return clojure.lang.RT.var(NS, fn).invoke(arg1, arg2, arg3); } catch (Exception e) { return null; } } public Repl() { String result; try { clojure.lang.Var eval = clojure.lang.RT.var("clojure.core", "eval"); clojure.lang.Var read = clojure.lang.RT.var("clojure.core", "read-string"); String create_repl_server = "(do " + "(use '[clojure.contrib.server-socket :only [create-repl-server]])" + "(create-repl-server " + PORT + ")" + ")"; result = eval.invoke(read.invoke(create_repl_server)).toString(); } catch (Exception e) { result = e.toString(); } initResult = result; } } public static final Repl REPL = new Repl(); 2. Use this on the command line to start the REPL: rlwrap --logfile $HOME/tmp/clj.log telnet localhost 18081 Now from the REPL you can create Java objects and call methods at will. 3. To call a Clojure function called some-function in "user" namespace from Java, use something like this: REPL.invoke("some-function", "arg1")); -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Using Clojure To Debug Java Apps
This is great !!! But you should posting it in a blog and compare it with other solutions. On Jul 12, 2:31 am, Asim Jalis wrote: > I have been using the Clojure REPL to debug a large Java server app. > It's great for exploratory testing and for validating assumptions > about how the system works. I wanted to post the code here in case > someone else finds this useful. > > 1. Stick this in a class that is loaded early in the server/app. > > public static class Repl { > public static final String PORT = "18081"; > public static final String NS = "user"; > > private final String initResult; public String getInitResult() { > return initResult; } > > public Object invoke(String fn) { try { return > clojure.lang.RT.var(NS, fn).invoke(); } catch (Exception e) { return > null; } } > public Object invoke(String fn, Object arg1) { try { return > clojure.lang.RT.var(NS, fn).invoke(arg1); } catch (Exception e) { > return null; } } > public Object invoke(String fn, Object arg1, Object arg2) { try { > return clojure.lang.RT.var(NS, fn).invoke(arg1, arg2); } catch > (Exception e) { return null; } } > public Object invoke(String fn, Object arg1, Object arg2, Object > arg3) { try { return clojure.lang.RT.var(NS, fn).invoke(arg1, arg2, > arg3); } catch (Exception e) { return null; } } > > public Repl() { > String result; > try { > clojure.lang.Var eval = clojure.lang.RT.var("clojure.core", > "eval"); > clojure.lang.Var read = > clojure.lang.RT.var("clojure.core", "read-string"); > String create_repl_server = > "(do " + > "(use '[clojure.contrib.server-socket :only > [create-repl-server]])" + > "(create-repl-server " + PORT + ")" + ")"; > result = eval.invoke(read.invoke(create_repl_server)).toString(); > } catch (Exception e) { > result = e.toString(); > } > initResult = result; > }} > > public static final Repl REPL = new Repl(); > > 2. Use this on the command line to start the REPL: > > rlwrap --logfile $HOME/tmp/clj.log telnet localhost 18081 > > Now from the REPL you can create Java objects and call methods at will. > > 3. To call a Clojure function called some-function in "user" namespace > from Java, use something like this: > > REPL.invoke("some-function", "arg1")); -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Using Clojure To Debug Java Apps
I wrote a tool called liverepl a while ago: https://github.com/djpowell/liverepl It effectively lets you get a repl into a Java or Clojure process, but it has the nice feature that it works with any Java processes without requiring any modifications to the code. It uses the Java Attach API, which jvisualvm and jconsole use to inject the repl server into the process, and then it connects the console to that server. It has some special support for Tomcat servers too, so that you can repl into a specific webapp. -- Dave -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Using Clojure To Debug Java Apps
That looks very interesting Dave - can you give a bit more information on what sorts of things you can actually do once you have a REPL connected? (in terms of how to access / explore things inside the running Java application) On Wed, Jul 13, 2011 at 4:06 PM, David Powell wrote: > I wrote a tool called liverepl a while ago: > https://github.com/djpowell/liverepl > It effectively lets you get a repl into a Java or Clojure process, but it > has the nice feature that it works with any Java processes without requiring > any modifications to the code. It uses the Java Attach API, which jvisualvm > and jconsole use to inject the repl server into the process, and then it > connects the console to that server. It has some special support for Tomcat > servers too, so that you can repl into a specific webapp. -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en
Re: Using Clojure To Debug Java Apps
Yet another way you can get a repl into an existing process running on the JVM: https://github.com/wirde/swank-inject Disclaimer: It's a hack It uses JDI to connect to the process (requires remote debugging on the target, but no other modifications) Won't work well for some classloader hierarchies The Swank repl *doesn't* work well (yet), uses clojure.contrib.server-socket/create-repl-server instead But: You do get a (remote) repl injected into the application You can get hooks into any (singleton) instances in the target process Johan On Thu, Jul 14, 2011 at 1:06 AM, David Powell wrote: > > I wrote a tool called liverepl a while ago: > > https://github.com/djpowell/liverepl > > It effectively lets you get a repl into a Java or Clojure process, but it > has the nice feature that it works with any Java processes without requiring > any modifications to the code. It uses the Java Attach API, which jvisualvm > and jconsole use to inject the repl server into the process, and then it > connects the console to that server. It has some special support for Tomcat > servers too, so that you can repl into a specific webapp. > > -- > Dave > > -- > You received this message because you are subscribed to the Google > Groups "Clojure" group. > To post to this group, send email to clojure@googlegroups.com > Note that posts from new members are moderated - please be patient with > your first post. > To unsubscribe from this group, send email to > clojure+unsubscr...@googlegroups.com > For more options, visit this group at > http://groups.google.com/group/clojure?hl=en > -- You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en