Using Clojure To Debug Java Apps

269 views
Skip to first unread message

Asim Jalis

unread,
Jul 11, 2011, 7:31:55 PM7/11/11
to clo...@googlegroups.com
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"));

cran1988

unread,
Jul 13, 2011, 7:00:01 PM7/13/11
to Clojure
This is great !!!
But you should posting it in a blog and compare it with other
solutions.

David Powell

unread,
Jul 13, 2011, 7:06:26 PM7/13/11
to clo...@googlegroups.com

I wrote a tool called liverepl a while ago:


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

Sean Corfield

unread,
Jul 13, 2011, 8:57:15 PM7/13/11
to clo...@googlegroups.com
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)

Johan Wirde

unread,
Jul 14, 2011, 3:06:07 AM7/14/11
to clo...@googlegroups.com
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
    

--
You received this message because you are subscribed to the Google
Groups "Clojure" group.
To post to this group, send email to clo...@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+u...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/clojure?hl=en

Reply all
Reply to author
Forward
0 new messages