Inspecting objects in running app using CRaSH

71 views
Skip to first unread message

Łukasz Wiecheć

unread,
Apr 19, 2013, 4:20:55 AM4/19/13
to crash...@googlegroups.com
Hi,

sorry for my (possible) ignorance but I would like to use CRaSH shell to 'inspect' (ie. show the contents) of a data structure that is running inside JVM that I attach CRaSH to. I guess I can write a Groovy script that will parse the object and print the data in user-friendly way; the problem is how to access the data?

Łukasz

Julien Viet

unread,
Apr 19, 2013, 4:41:54 AM4/19/13
to crash...@googlegroups.com
you are totally right.

if you attach, you can only get objects using a static registry like System properties (there are additional possiblities to obtain a specific classloader of the JVM using the JVM Instrumentation object that is available when attaching).

The other way is to embed CRaSH into your runtime and pass it a context (like servlet context attributes , Spring beans, etc…)

How is your data available ?


--
Vous recevez ce message, car vous êtes abonné au groupe Google Groupes CRaSH User Group.
Pour vous désabonner de ce groupe et ne plus recevoir d'e-mails le concernant, envoyez un e-mail à l'adresse crash-users...@googlegroups.com.
Pour plus d'options, visitez le site https://groups.google.com/groups/opt_out .
 
 

Łukasz Wiecheć

unread,
Apr 19, 2013, 4:47:36 AM4/19/13
to crash...@googlegroups.com
Julien, thanks for a quick answer. In my application I would like to inspect the contents of a list - ideally I would like to see the contents and the size of it. The application is a very simple one - not a webapp, just a long running command-line app that processing data; I would like to be able to inspect the data container. The container is right now just a private field of a (non-static) class. I could of course make the private field accessible via a getter.

In the meantime I have been looking at JMX, as CRaSH provides access to it.

Embedding CraSH is also an option; I imagine that embedding would mean that, after starting my app, I could access the CRaSH in it by, say, telnet or ssh to a port, correct?


-- 
Łukasz 

Julien Viet

unread,
Apr 19, 2013, 4:52:58 AM4/19/13
to crash...@googlegroups.com
On Apr 19, 2013, at 10:47 AM, Łukasz Wiecheć <coquel...@gmail.com> wrote:

Julien, thanks for a quick answer. In my application I would like to inspect the contents of a list - ideally I would like to see the contents and the size of it. The application is a very simple one - not a webapp, just a long running command-line app that processing data; I would like to be able to inspect the data container. The container is right now just a private field of a (non-static) class. I could of course make the private field accessible via a getter.


if you make this field static then it is trivial to access it via crash

In the meantime I have been looking at JMX, as CRaSH provides access to it.

you mean expose part of your app as an mbean ?


Embedding CraSH is also an option; I imagine that embedding would mean that, after starting my app, I could access the CRaSH in it by, say, telnet or ssh to a port, correct?

yes, crash has notion of connector (telnet or ssh) then it's up to you to embed the connector of your choice.

we are currently working on improving this part and making it more documented (using the xwiki integration as basis). You can expect better documentation for this in the coming days, meanwhile we can help you on this list.

Łukasz Wiecheć

unread,
Apr 19, 2013, 5:05:06 AM4/19/13
to crash...@googlegroups.com
Ok, let's try the simple solution first - the one with static field.

Do I have to have something like that? Launcher is the class that I start; it has a static field obj1 of type ObjectType that provides a getter to get my List instance to inspect.

class Launcher {

  public static ObjectType obj1;

  public static void main(String[] argv) {
    // ...
    // init
    obj1 = new ObjectType(...);
  }
}


public class ObjectType {

  List a;

  // ...

  public List getA() { return a; }

Julien Viet

unread,
Apr 19, 2013, 5:20:44 AM4/19/13
to crash...@googlegroups.com
On Apr 19, 2013, at 11:05 AM, Łukasz Wiecheć <coquel...@gmail.com> wrote:

Ok, let's try the simple solution first - the one with static field.

Do I have to have something like that? Launcher is the class that I start; it has a static field obj1 of type ObjectType that provides a getter to get my List instance to inspect.

class Launcher {

  public static ObjectType obj1;

  public static void main(String[] argv) {
    // ...
    // init
    obj1 = new ObjectType(...);
  }
}


public class ObjectType {

  List a;

  // ...

  public List getA() { return a; }
}

if that is available in the system classloader of the JVM, it should be found in a script using

def o = org.foo.Launcher.obj1

(assuming org.foo is the package of Launcher)

Łukasz Wiecheć

unread,
Apr 19, 2013, 9:06:04 AM4/19/13
to crash...@googlegroups.com
Hi again,

thanks - that works. I think even though I don't like static variables 'hanging' around too much, I can live with that approach! :)

Now - how hard would it be to include the CRaSH into my application - so that when I start the app, I can ssh/telnet to it from the outside and do all my 'cool' inspections?...

cheers,

Łukasz

Julien Viet

unread,
Apr 19, 2013, 10:19:39 AM4/19/13
to crash...@googlegroups.com
On Apr 19, 2013, at 3:06 PM, Łukasz Wiecheć <coquel...@gmail.com> wrote:

Hi again,

thanks - that works. I think even though I don't like static variables 'hanging' around too much, I can live with that approach! :)

glad to hear that


Now - how hard would it be to include the CRaSH into my application - so that when I start the app, I can ssh/telnet to it from the outside and do all my 'cool' inspections?…

this is not too hard to do but it is not yet documented, and what you can do depends on the level of integration you want.

For now you can try to use the org.crsh.standalone.Bootstrap class:

Bootstrap bootstrap = new Bootstrap(ClassLoader.getSystemClassLoader());
bootstrap.addToConfPath(new File("conf"));
bootstrap.addToCmdPath(new File("cmd"));
bootstrap.bootstrap();

this should recreate a crash (but without the shell in command line) and for having access to SSH or telnet you would need to SSH or telnet jars in your classpath.

I think this should work (but not 100% sure).

That's one part of CRaSH we need to improve and document.

Łukasz Wiecheć

unread,
Apr 24, 2013, 4:06:15 AM4/24/13
to crash...@googlegroups.com
Julien,

as my project is built using maven, I have added crsh.shell.core and crsh.shell.telnet to my pom file (the JARs end up correctly in JAR) but I still can't connect to the shell using telnet.

Here's what logging says about that:

Apr 24, 2013 10:04:25 AM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO: Loaded plugin Plugin[type=CRaSHShellFactory,interface=ShellFactory]
Apr 24, 2013 10:04:25 AM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO: Loaded plugin Plugin[type=ProcessorIOHandler,interface=TermIOHandler]
Apr 24, 2013 10:04:25 AM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO: Loaded plugin Plugin[type=JaasAuthenticationPlugin,interface=AuthenticationPlugin]
Apr 24, 2013 10:04:25 AM org.crsh.plugin.ServiceLoaderDiscovery getPlugins
INFO: Loaded plugin Plugin[type=SimpleAuthenticationPlugin,interface=AuthenticationPlugin]
Apr 24, 2013 10:04:25 AM org.crsh.plugin.PluginManager getPlugins
INFO: Initialized plugin Plugin[type=CRaSHShellFactory,interface=ShellFactory]
Apr 24, 2013 10:04:25 AM org.crsh.plugin.PluginManager getPlugins
INFO: Initialized plugin Plugin[type=ProcessorIOHandler,interface=TermIOHandler]
Apr 24, 2013 10:04:25 AM org.crsh.plugin.PluginManager getPlugins
INFO: Initialized plugin Plugin[type=JaasAuthenticationPlugin,interface=AuthenticationPlugin]
Apr 24, 2013 10:04:25 AM org.crsh.plugin.PluginManager getPlugins
INFO: Initialized plugin Plugin[type=SimpleAuthenticationPlugin,interface=AuthenticationPlugin]

Any help will be appraciated :)

Lukasz

Julien Viet

unread,
Apr 24, 2013, 4:27:22 AM4/24/13
to crash...@googlegroups.com
The telnet plugin does not seem to be loaded, can you show us how you did embed CRaSH ?

Łukasz Wiecheć

unread,
Apr 24, 2013, 4:53:10 AM4/24/13
to crash...@googlegroups.com
Julien,

I tried to follow you advice:

...
// add CRaSH
Bootstrap bootstrap = new Bootstrap(ClassLoader.getSystemClassLoader());
bootstrap.addToConfPath(new File("crash-conf"));
bootstrap.addToCmdPath(new File("crash-commands"));
bootstrap.bootstrap();
...

Julien Viet

unread,
Apr 24, 2013, 5:23:28 AM4/24/13
to crash...@googlegroups.com
can you access the class org.crsh.telnet.TelnetPlugin at runtime ?

Normally the plugins are loaded using the ServiceLoaderDiscovery that finds the plugin using:

      ServiceLoader<CRaSHPlugin> loader = ServiceLoader.load(CRaSHPlugin.class, classLoader);

If the TelnetPlugin is in your classpath then it should be discovered by the ServiceLoader discovery (http://docs.oracle.com/javase/6/docs/api/java/util/ServiceLoader.html)

Julien Viet

unread,
Apr 24, 2013, 8:53:32 AM4/24/13
to crash...@googlegroups.com
just made a quick check, we are missing configuration properties:

try with:

        Bootstrap bs = new Bootstrap(Thread.currentThread().getContextClassLoader());
        Properties config = new Properties();
        config.setProperty("crash.vfs.refresh_period", "1");
        config.setProperty("crash.telnet.port", "5000");
        bs.setConfig(config);
        bs.bootstrap();

Łukasz Wiecheć

unread,
Apr 24, 2013, 9:43:39 AM4/24/13
to crash...@googlegroups.com
Hi again,

I have added the code and the results are the same. I am pretty sure that the telnet JAR is in the classpath; I am making a super-jar using Maven shade plugin and I can see the TelnetPlugin class in org/crsh/telnet/TelnetPlugin.class. To verify that, I have explicitly added 

ServiceLoader<TelnetPlugin> loader = ServiceLoader.load(TelnetPlugin.class, classLoader);
loader.reload();

right after (and before) calling bootstrap.bootstrap(). There is no runtime error (so I guessTelnetPlugin class is in the classpath) but the logging does not show it; needless to say, 'telnet localhost 5000' results in 'Connection refused'.

Lukasz

Julien Viet

unread,
Apr 24, 2013, 9:48:27 AM4/24/13
to crash...@googlegroups.com
super jar is the issue, it may lose information.

the plugin are declared in META-INF/services/org.crsh.plugin.CRaSHPlugin file

can you check what is in your jar ?

are you using maven for creating this big jar ?

Łukasz Wiecheć

unread,
Apr 24, 2013, 9:52:03 AM4/24/13
to crash...@googlegroups.com
I was just about to write to you about that :) yes, the file 'META-INF/services/org.crsh.plugin.CRaSHPlugin' does not contain the TelnetPlugin; after adding it by hand, the plugin is loaded.

Does it mean that - i have to make sure that this file is updated each time I make the super-JAR?

Also, I am planning to include configuration and commands directory as a part of the super-JAR; how hard it is to tell that to Bootstrap class ? the API mentions only 'addToCmdPath(File())' and 'addToCmdPath(Path())'...

Julien Viet

unread,
Apr 24, 2013, 9:59:20 AM4/24/13
to crash...@googlegroups.com
On Apr 24, 2013, at 3:52 PM, Łukasz Wiecheć <coquel...@gmail.com> wrote:

I was just about to write to you about that :) yes, the file 'META-INF/services/org.crsh.plugin.CRaSHPlugin' does not contain the TelnetPlugin; after adding it by hand, the plugin is loaded.

Does it mean that - i have to make sure that this file is updated each time I make the super-JAR?

can't you make this part of your build system ?

if you are using maven there is a way to merge the various service files.


Also, I am planning to include configuration and commands directory as a part of the super-JAR; how hard it is to tell that to Bootstrap class ? the API mentions only 'addToCmdPath(File())' and 'addToCmdPath(Path())'…

You can do instead:

bootstrap.addToConfPath(Path.get("/crash/"));
bootstrap.addToCmdPath(Path.get("/crash/commands/"));

this will find configuration and commands from the classloader instead of the file system

Łukasz Wiecheć

unread,
Apr 24, 2013, 10:01:54 AM4/24/13
to crash...@googlegroups.com
you are right, I will tweak maven's shade plugin. And thanks for the tip with using Path() objects - I will give it a go!

L.

Łukasz Wiecheć

unread,
Apr 25, 2013, 5:26:04 AM4/25/13
to crash...@googlegroups.com
Julien,

thanks for all help - the suggestions worked. Now I can telnet to my app and call my commands.

However, the colors seems not to be working when using telnet - is that normal? 

Łukasz

Julien Viet

unread,
Apr 25, 2013, 5:34:04 AM4/25/13
to crash...@googlegroups.com
I think this depends on your client.

for example on OSX I have to do:

export TERM="xterm-color"

to declare my term to accept colors when I telnet

Coquelicot

unread,
Apr 25, 2013, 5:37:33 AM4/25/13
to crash...@googlegroups.com
the original TERM settings were 'xterm-256color'; after changing to 'xterm-color' I got the color - thanks!!!

Lukasz


--
Vous recevez ce message car vous êtes abonné à un sujet dans le groupe Google Groupes "CRaSH User Group".
Pour vous désabonner de ce sujet, visitez le site https://groups.google.com/d/topic/crash-users/Uonu2XN_XgQ/unsubscribe?hl=fr.
Pour vous désabonner de ce groupe et de tous ses sujets, envoyez un e-mail à l'adresse crash-users...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages