Monday, August 13, 2012

Generating a Java Core Dump

This post demonstrates how you can generate a Java core dump manually (using JNI).

1. Create a Java class

/**
 * A class to demonstrate core dumping.
 */
public class CoreDumper {

  // load the library
  static {
    System.loadLibrary("nativelib");
  }

  // native method declaration
  public native void core();

  public static void main(String[] args) {
    new CoreDumper().core();
  }
}
2. Compile the Java class
$ javac CoreDumper.java
$ ls
CoreDumper.class  CoreDumper.java
3. Generate the header file
$ javah -jni CoreDumper
$ ls
CoreDumper.class  CoreDumper.h  CoreDumper.java
4. Implement the native method
Copy the method declaration from the header file and create a new file called CoreDumper.c containing the implementation of this method:
#include "CoreDumper.h"

void bar() {
  // the following statements will produce a core
  int* p = NULL;
  *p = 5;

  // alternatively:
  // abort();
}

void foo() {
  bar();
}

JNIEXPORT void JNICALL Java_CoreDumper_core
  (JNIEnv *env, jobject obj) {
  foo();
}
5. Compile the native code
This command may vary based on your operating system. On my Red Hat Linux machine, I use the following command:
$ gcc -fPIC -o libnativelib.so -shared \
            -I$JAVA_HOME/include/linux/ \
            -I$JAVA_HOME/include/ \
             CoreDumper.c
$ ls
CoreDumper.class  CoreDumper.h  CoreDumper.java libnativelib.so
6. Run the program
$ java -Djava.library.path=. CoreDumper
#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x0000002b1cecf75c, pid=18919, tid=1076017504
#
# JRE version: 6.0_21-b06
# Java VM: Java HotSpot(TM) 64-Bit Server VM (17.0-b16 mixed mode linux-amd64 )
# Problematic frame:
# C  [libnativelib.so+0x75c]  bar+0x10
#
# An error report file with more information is saved as:
# /home/sharfah/tmp/jni/hs_err_pid18919.log
#
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Aborted (core dumped)
The core file
As shown above, running the program causes it to crash and a core file is produced. On my machine, the operating system writes out core files to /var/tmp/cores. You can use the following command to see what your core file directory is configured to:
$ cat /proc/sys/kernel/core_pattern
/var/tmp/cores/%e.%p.%u.core
$ ls /var/tmp/cores
java.21178.146385.core
In my next post, I will show you how can you perform some quick analysis on a core file to see what caused the crash.

Next Post:
Analysing a Java Core Dump

Thursday, August 09, 2012

Running a command on multiple hosts

There are different ways you can run a command on multiple machines.

1. For loop
If you want to execute the same command on a few hosts, you can use a for loop as shown below:

for host in host1 host2 host3
do
    ssh $host "hostname; who -b"
done
The example above iterates over a list of hosts, and runs two commands on each one to print the name of the host and the time it was rebooted.

2. While loop
If your list of hosts is stored in a file, you can use a while loop as shown below:

while IFS= read -r host
do
    ssh -n $host "hostname; who -b"
done < /tmp/myhosts
You must provide the -n option to ssh, otherwise it will only run on the first host in your file and then the loop will terminate.

3. Parallel ssh
Parallel ssh (pssh) allows you to run a command on several hosts at the same time and is much faster than using a sequential loop if the number of hosts is large. You can specify how many parallel processes it uses to ssh to the various hosts (default is 32).

$ pssh
Usage: pssh [OPTIONS] -h hosts.txt prog [arg0] ..

  -h --hosts   hosts file (each line "host[:port] [user]")
  -l --user    username (OPTIONAL)
  -p --par     max number of parallel threads (OPTIONAL)
  -o --outdir  output directory for stdout files (OPTIONAL)
  -t --timeout timeout in seconds to do ssh to a host (OPTIONAL)
  -v --verbose turn on warning and diagnostic messages (OPTIONAL)
  -O --options SSH options (OPTIONAL)

$ pssh -h /tmp/myhosts -o /tmp/output "hostname; who -b"

Saturday, August 04, 2012

bash error: value too great for base

I came across this interesting error today:
-bash: 08: value too great for base (error token is "08")
It was coming from a script which works out the previous month by extracting the current month from the current date and then decrementing it. The code looks like this:
today="$(date +%Y%m%d)"
month=${today:4:2}
prevmonth=$((--month))
This script throws an error only if the current month is 08 or 09. I found that the reason for this is that numbers starting with 0 are interpreted as octal numbers and 8 and 9 are not in the base-8 number system, hence the error. There are more details on the bash man page:
Constants with a leading 0 are interpreted as octal numbers. A leading 0x or 0X denotes hexadecimal. Otherwise, numbers take the form [base#]n, where base is a decimal number between 2 and 64 represent- ing the arithmetic base, and n is a number in that base. If base# is omitted, then base 10 is used.
To fix this issue, I specified the base-10 prefix as shown below:
today="$(date +%Y%m%d)"
month=10#${today:4:2}
prevmonth=$((--month))

Saturday, June 30, 2012

vim: Change statusline colour based on mode

Here is my vimrc statusline configuration:
" statusline
" format markers:
"   %t File name (tail) of file in the buffer
"   %m Modified flag, text is " [+]"; " [-]" if 'modifiable' is off.
"   %r Readonly flag, text is " [RO]".
"   %y Type of file in the buffer, e.g., " [vim]".
"   %= Separation point between left and right aligned items.
"   %l Line number.
"   %L Number of lines in buffer.
"   %c Column number.
"   %P percentage through buffer
set statusline=%t\ %m%r%y%=(ascii=\%03.3b,hex=\%02.2B)\ (%l/%L,%c)\ (%P)
set laststatus=2
" change highlighting based on mode
if version >= 700
  highlight statusLine cterm=bold ctermfg=black ctermbg=red
  au InsertLeave * highlight StatusLine cterm=bold ctermfg=black ctermbg=red
  au InsertEnter * highlight StatusLine cterm=bold ctermfg=black ctermbg=green
endif
It displays some useful information about the file and your position within it. It also automatically changes the colour of the statusline from red to green when you enter INSERT mode and back to red when you leave it.

This is what the status line looks like in INSERT mode:

Foo.java [RO][java] (ascii=097,hex=61) (158/667,23) (26%)

To see a description of all possible status line variables type :help statusline in vim.

To see my complete vimrc visit my GitHub dotfiles repository.

Saturday, May 26, 2012

MultiTail: Viewing Multiple Files with Custom Colorschemes

MultiTail is a program which allows you to tail multiple files in a single terminal. The feature I find most useful is its ability to highlight text in files using "colorschemes". There are a number of pre-defined colorschemes which can be found in the configuration file, multitail.conf.

Here is an example of using multitail. The command below tails two files: an apache access log and a tomcat catalina log using two different colorschemes.

$ multitail -cS apache /tmp/apache/access_log -cS log4j ${TOMCAT_HOME}/logs/catalina.out
You can also add additional colorschemes to your ~/.multitailrc. A colorscheme is simply a set of regular expressions to capture and highlight the text you are interested in. Here is my config file which contains my custom XML colour scheme.
check_mail:0

colorscheme:xml
# element text
cs_re_s:white:>([^<]*)<
# attribute key
cs_re_s:green: ([^ =]*)=
# attribute value
cs_re_s:red:=("[^"]*")
# element name
cs_re:blue,,bold:<[^>]*>
Used like this:
$  multitail -cS xml /var/log/config.xml
Related Post:
Highlighting Command Output with Generic Colouriser