Java Stuff

Run A Java Process to Listen to JVisualVM Requests from Other Hosts

Updated 28 Jan 2015

Let's say you have a Java program, testjmx.TestIt, on your machine that has IP address 192.168.1.148. Run it like so:

mwood@workstation:~/workspace/testjmx/bin$ java \
    -Dcom.sun.management.jmxremote.port=1234 \
    -Dcom.sun.management.jmxremote.authenticate=false \
    -Dcom.sun.management.jmxremote.ssl=false \
    -Djava.rmi.server.hostname=192.168.1.148 \
    testjmx.TestIt

The first three defines are well-documented; the last define, where you spell out to RMI what host it's runing on, is not very well documented, but there's a note about it here:

http://blogs.sun.com/jmxetc/entry/troubleshooting_connection_problems_in_jconsole

The hostname that you define in the java.rmi.server.hostname system property must match exactly the hostname you use when connecting from JVisualVM.

Then, on another machine, just do this:

mwood@laptop:~$ jvisualvm

Add a new JMX connection to localhost:1234, then find that new connection in the left-hand pane, and double-click on it to start monitoring.

Run Your JDK with Remote Debugging Enabled

Updated 28 Jan 2015

This will allow a Java debugger (including Eclipse or IntelliJ) to latch onto this process and debug it remotely:

java \
    -agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=1044 \
    -Xshare:off \
    com.manniwood.Hello

See Oracle's docs for more details.

Run Your JDK in Headless Mode

java -Djava.awt.headless=true

Importing a Server Certificate into Your JDK

default keystore is kept in $JAVA_HOME/jsr/lib/security/cacerts

default password to that keystor is "changeit"

certs created using openssl work fine, hence, it is easy to import the cert you made for your apache server.

[root@localhost ~]# keytool -import -file /home/mwood/server.crt \
-alias employer -keystore /usr/local/jdk1.5.0_04/jre/lib/security/cacerts
Enter keystore password:  changeit
Owner: CN=www.employer.com, OU=Development, O=Employer, L=Boston, ST=Massachusetts, C=US
Issuer: CN=www.employer.com, OU=Development, O=Employer, L=Boston, ST=Massachusetts, C=US
Serial number: 0
Valid from: Wed Feb 15 11:09:06 EST 2006 until: Sat Feb 13 11:09:06 EST 2016
Certificate fingerprints:
         MD5:  52:A9:14:8D:6F:80:9C:20:27:A2:92:D6:0B:AD:AF:1E
         SHA1: 31:56:AE:5A:5A:65:95:05:00:70:2D:07:32:B1:0A:6B:B4:9E:B0:F1
Trust this certificate? [no]:  yes
Certificate was added to keystore
[root@localhost ~]#

Tell Java not to compile code, so that you get line numbers, not "(Compiled Code)", in stack traces:

java -Djava.compiler=none

Get a thread dump from a JVM:

kill -s SIGQUIT <pid of JVM>

or

kill -3 <pid of JVM>

Or, for a JVM on a console, Ctrl-\. The thread dump will go to whereever STDOUT is going; if you started your JVM with nohup, check nohup.out.

grep the contents of a jar file:

jar -tvf my.jar 2>&1 | grep string

Java commands are excruciatingly stupid about writing what should be stdout stuff to stderr.

Find a class in any jar file in a directory tree:

First of all, unlike the above tip, it seems that newer versions of jar finally understand the difference between standard out and standard error. Yay! The following shell script takes one argument: a string (usually a class name) that you are looking for in the table of contents of every jar file in your current directory tree. The script is:

#!/bin/sh
for f in `find . -name '*jar'`
do
    jar -tvf $f | grep $1 && echo "was found in $f"
done

So just name this shell script find_in_jars.sh and run it like so:

./find_in_jars.sh SomeJavaClassName

Find all TODOs in a codebase (*.java files in this example):

find . -name '*.java' -exec grep -i -H -n "todo" {} \;