blog dds


Code Verification Scripts

Which of my classes contain instance variables? Which classes call the method userGet, but don't call the method userRegister? These and similar questions often come up when you want to verify that your code is free from some errors. For example, instance variable can be a problem in servlet classes. Or you may have found a bug related to the userGet and userRegister methods, and you want to look for other places where this occurs. Your IDE is unlikely to answer such questions, and this is where a few lines in the Unix shell can save you hours of frustration.

Classes with Instance Variables

To locate classes containing instance variables, run the following Bourne shell script on the directory containing your compiled classes.

find . -name *.class |
sed 's,\(.*\)\/\([^/]*\)\.class,\1 \2,' |
while read dir class
do (
	cd $dir
	echo -n "In $dir "
	javap $class |
	egrep -v '\);|{|}|  throws '
done |
perl -pe 'BEGIN {undef $/;} s/In [^\n]+\n\n//gs;'

The script depends on a neat trick for analyzing code: sometimes it's easier to process object code than to parse the source code. Here I'm using Java's javap program to display the contents of compiled classes in a printable format. The script works by changing the paths of class files into the directory of the class file and the class's name. A loop then reads the two, goes into the directory and invokes javap on the class. We then remove from javap's output lines that containing methods, braces, and exceptions, so that only instance variables remain. Finally, we read the results as a single Perl line, and remove the listing of classes that don't contain any instance variables.

Calls to One Method but not Another

To locate classes that call the method userGet, but don't call the method userRegister we process their source code with the following bash script.

comm -23 \
<(find . -name \*.java -print0 | xargs -0 grep -l userGet | sort) \
<(find . -name \*.java -print0 | xargs -0 grep -l userRegister | sort)

The script depends on a wonderful feature of the bash shell: the ability to make the output of a command appear as a file. The script's second line creates a list of all Java files and prints those that contain userGet. Similarly, the script's third line creates a list of all Java files and prints those that contain userRegister. The $(...) syntax makes the output of both commands appear in the form of a file name (actually a file descriptor /dev/fd/N or a named pipe), so that we can pass it a command as an argument. Furthermore, both command sequences sort the output, so that we can process them with comm — a command that can print lines common (or not) in two sorted files. The -23 argument passed to comm will make it print only lines that appear in the first command's output, which is exactly what we want.

Read and post comments, or share through   

Creative Commons License Last modified: Saturday, May 21, 2011 9:40 pm
Unless otherwise expressly stated, all original material on this page created by Diomidis Spinellis is licensed under a Creative Commons Attribution-Share Alike 3.0 Greece License.