Introduction

JavaShark is a new way to view/trace/analyze JVM applications. It's like an advanced debugger with Groovy support. What is more important - now you can share your knowledge about any system with people around the world - just share your handlers(breakpoints) bundle. Just imagine - you connect to the remote JVM, attach handlers bundle and now you know much more than any logs could ever give you. It's free and open source under MIT license. All debug power is in your hands now in a handy and cool way.

What you can do

  1. Set and handle breakpoints using Groovy script

  2. Access any object field or method parameter in a Groovy way

  3. Trace method entry/exit

  4. Trace object field access/modification

  5. Trace any exception - either caught or uncaught

  6. Share your knowledge - give others your handlers

  7. And much more - anything that JPDA allows you

Another debugger? No

It's much more than a usual debugger. It's combined Groovy and JPDA power. Code anything you like, get access to any field you like, share your knowledge.

Why did I make it?

  1. Cause logs don't show you all required info (often there are no logs at all in the most important places)

  2. Cause logs are messy and you can't just combine all messages in the same thread for example

  3. Cause standard debuggers are not good for anything more than stepping and viewing variables

  4. Cause I don't wanna forget what I have learned during investigation

Installation

  1. Make sure you have a Java 6+ JRE and the java command is available in your path

  2. Make sure you have a Gradle 2.x and the gradle command is available in your path

  3. Download and unzip JavaShark into a folder on your hard disk

  4. Since java still can't properly get current timezone...set your timezone in the run.bat

  5. Open a command prompt and run run

Welcome to the JavaShark 1.4 
>

Quick Start

Launch remote vm with debug options

-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5005

Connect to the remote vm

> vm.connect localhost 5005

Attach handlers to generate events (you can specify more than one separated by space)

> handler.attach mysql thread

Do something on the remote vm

View generated event stats

> event.stats

Open Swing app to view events

> frame.show

Startup

You can put commands to execute on startup to the file startup

vm.connect localhost 5005
handler.attach mysql

These commands will connect to the remote vm and attach mysql handler on startup

Colors

You can colorize your Swing app with the command

> frame.color "sheme name"

which searches for color schemes in the commands/.colors folder. It uses default.groovy without arguments. To define new color scheme create new groovy script in this folder and define one method

import net.javashark.events.Event
import java.awt.Color
Color process(Event event) {
  if (event.type == "mysql" && event.mysqlQueryType == "insert") {
    return new Color(255, 120, 180)
  }
}

Filters

You can filter your events with the command

> event.filter "filter name" | reset

It resets filtering with the reset arg. To define new filter create new groovy script in the commands/.filters folder and define one method

import net.javashark.events.Event
boolean accept(Event event) {
 event.type == "java"
}

Commands

To define new command you have to:

  1. Create file <command name>.groovy in the commands folder

  2. Define a method with name equal to the command name and annotate it with net.javashark.cli.Command

  3. You can define parameters with the following types and JavaShark will inject them before method invocation:

    1. net.javashark.GlobalContext
    2. net.javashark.Dao
    3. net.javashark.events.DebugSession
    4. net.javashark.RemoteVM
    5. net.javashark.events.EventStorage
    6. com.sun.jdi.VirtualMachine

  4. If you need any data from user you can define parameters and annotate them with net.javashark.cli.Parameter annotation. See other commands for examples.

    ALWAYS specify parameter type and don't use Object or def cause JavaShark checks parameter values before method invocation.

Handlers

To define new handler you have to:

  1. Give it a name - like hibernate3.1 for example

  2. Create folder with this name in the commands/.handlers directory (notice - names starting with "." are reserved)

  3. Create a file with the name equal to the class you want to set breakpoint at and with "handler" extension (e.g. org.apache.cxf.interceptor.AbstractLoggingInterceptor.handler)

  4. Important - handlers are updated automatically, to update handler just change handler file and save changes, no need to detach/attach to apply changes

  5. Very important - you should use JVM binary names for classes and method signatures.

    Download Intellij Idea plugin, install it, right click where you wanna set breakpoint and choose JavaShark - send breakpoint. You will see breakpoint definition in the JavaShark console

import net.javashark.events.Event
import net.javashark.ThisObject

breakAt "log", "(Ljava/lang/String;)V", 146, { ThisObject thiz ->

    def message = thiz.params.message.value()

    createEvent(message, thiz.thread, "log", 146)
}

Event createEvent(String value, Object thread, String methodName, Integer line) {
    def event = new Event()
    event.type = "java"
    event.threadName = thread.name()
    event.threadId = thread.uniqueID()
    event.value = value
    event.time = System.currentTimeMillis()

    event.className = this.class.name
    event.methodName = methodName
    event.line = line

    addEvent event
}

String getDescription() {
    "catches log messages (inbound and outbound)"
}

Class net.javashark.ThisObject is the way you get information about the remote vm state:

  1. ThisObject.thread is the reference to the current thread of the remote vm

  2. ThisObject.obj is the reference to the this object

  3. ThisObject.vm is the reference to the net.javashark.RemoteVM object

  4. ThisObject.params is the way you can get method parameter value. For example, to get value of the query param you just have to type thiz.params.query

Intellij Idea plugin

Download

You can use it to generate JavaShark breakpoint stubs for handlers and to navigate any source code location.

If you are writing handler you need to specify source code location in the handler. It can be quite difficult sometimes cause you have to use JVM binary names for classes, methods and signatures. To avoid spending tons of time with javap you can right click at the breakpoint location and choose JavaShark - send breakpoint and JavaShark will print file name for the handler and breakpoint stub to the console.

INFO  JavaShark Idea plugin listener [net.javashark.Main] file name: org.apache.tomcat.util.net.JIoEndpoint$Worker.handler
18:25:50,289 INFO  JavaShark Idea plugin listener [net.javashark.Main] breakpoint stub:
 breakAt "assign", "(Ljava/net/Socket;)V", 436, { thiz -> }
}

Also you can use it to trace thread execution. Just type

> thread.trace <thread name>

and then open thread trace with command

> thread.showTrace 

Double click any node and plugin will open and highlight corresponding source file.

Important - plugin has unique navigation port for each Idea instance so please choose right one before navigating. To get your navigation port right click anywhere and choose JavaShark - show navigation port

Directory structure

commands              - folder with commands and handlers
  .colors             - color schemes
  .filters            - event filters
  .handlers           - handler bundles
  frame               - commands to show/colorize Swing app
  handler             - commands to view/add/remove/disable handlers
  thread              - commands to view/suspend/resume threads
  event.groovy        - commands to work with events
  exit.groovy         - terminates JavaShark
  mysql.groovy        - commands to work with mysql events
  session.groovy      - commands to work with debug sessions
  vm.groovy           - commands to work with remote virtual machine
db                    - mapdb database
lib                   - dependencies
src                   - source code
build.gradle          - compiles JavaShark
license               - MIT license
run.bat               - compiles and launches JavaShark