Using Clojure To Debug Java Apps

2011-07-11 Thread Asim Jalis
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

2011-07-13 Thread cran1988
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

2011-07-13 Thread David Powell
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

2011-07-13 Thread Sean Corfield
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

2011-07-14 Thread Johan Wirde
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