Kubernetes & AI - Beauty and the Beast !?! @KCD Istanbul 2024
Jdj Foss Java Tools
1. FEATURE
Uncommon Java Bugs
Detecting them with FOSS tools
by S.G. Ganesh
A
ny large Java source base can have insidious and work schedules results in code that is often substandard
subtle bugs. Every experienced Java programmer and filled with bugs. So, because of practical problems,
knows that finding and fixing these bugs can be most code developed in the real world has bugs and it’s
difficult and costly. Fortunately, there are a large worthwhile using static analysis tools to find them and fix
number of free open source Java tools available that can them.
be used to find and fix defects early in the development In this article we’ll see an uncommon defect and intro-
lifecycle. In this article, we’ll look at a few examples of duce a tool that detects it. We do this for two reasons: to
specific uncommon or unusual defects that can happen in illustrate the kind of unusual problems that can happen
code and see how different Java static analysis tools detect in the code and to introduce a FOSS tool that’s suitable for
them. detecting this kind of problem.
Testing Jlint
As software gets more complex and ubiquitous, it What does this program print?
becomes more difficult to ensure high-quality code. One
common method of finding bugs is testing. But testing class LongVal {
can’t cover all paths and possibilities or enforce good public static void main(String[] s) {
programming practices. Expert knowledge in the form of long l = 0x1l;
manual code review by peers is one of the best ways to System.out.format(“%x”, l);
ensure good code quality. Code review is often used as a }
mandatory process step for improving the code and for }
finding the problems early in the software lifecycle.
Since testing and manual code review processes are When you run it, it prints 1, not 11 – why? Let’s use a
resource-intensive, it would be helpful to use automated
tools to review code. Static analysis tools help consid- Benefits of Using FOSS Java Static Analysis Tools
NEED erably in detecting the problems early in the software
HEAD lifecycle and help enhance the quality of the code Using Java static analysis tools can significantly improve the quality
significantly. of code. Although static analysis tools can’t cover all the paths or pos-
SHOT
There are many high-quality Java tools available in the sibilities, it provides significant help in providing coverage in detecting
open source domain. While it’s true that Java programs problems early in code; such tools can also point out programming prob-
S. G. Ganesh is a research don’t suffer from traditional C/C++ problems like memory lems and warn of violations of important and well-accepted program-
engineer at Siemens (Corpo- issues and major portability issues, Java software does suf- ming rules and recommendations.
rate Technology), Bangalore. fer quality problems like reliability, efficiency, maintain- Using static analysis tools has many attractive benefits. A few of the
Prior to Siemens, he worked ability, and security. A brief discussion on benefits of using salient benefits of most of these tools are listed here. Most of the Java
at Hewlett-Packard for FOSS Java tools is given in the sidebar. FOSS tools:
around five years. His areas Before getting into the meat of the matter, let’s discuss • Can cover code that’s not covered by testing or dynamic analysis
of interest are programming why bugs happen. First, it’s important to recognize that • Find many unusual or uncommon bugs that are usually missed
languages and compilers. His everyone makes mistakes, even experts. Second, compil- during testing or manual code review
latest book is 60 Tips on Ob- ers only check for syntax and semantic violations. Errors • Work even on partial code – fully compilable source isn’t always
ject Oriented Programming in language or API use, which manifest themselves as needed
(ISBN-13 978-0-07-065670-3) bugs, aren’t detected by compilers: This is left to static • Easily integrate with popular IDEs, so it’s comfortable to use them in
published by Tata McGraw- analysis tools and it’s important to use them to detect cod- your favorite environment
Hill, New Delhi. ing problems. Third, programmers and engineers are un- • Are usually easy-to-run –with just a button click from your IDE
der constant pressure to “get-the-work-done” under tight • Are absolutely free and high-quality
sgganesh@gmail.com schedules; working under “almost-impossible-to-meet”
10 May 2008 JDJ.SYS-CON.com
2. tool to detect the problem. The antic tool (that’s part of
JLint) finds it:
$antic –java LongVal.java
LongVal.java:3:26: May be ‘l’ is used instead of ‘1’ at the end of
integer constant
The programmer, possibly by mistake, typed ‘l’ (English
letter l) instead of ‘1’ (number one)!
long l = 0x1l;
To avoid this problem, it’s best to use ‘L’ (upper case
letter L) as the suffix for long constants instead of ‘l’ (lower
case letter l).
Antic is part of the Jlint tool that’s meant to find prob- Figure 1 FindBugs detects the check-for-equality-to-NaN problem
lems related to C syntax. There are quite a few coding
problems that are common to languages that use C-like
syntax. The problem we saw now is just one such problem.
Jlint ferrets out Java inconsistencies and bugs. It’s not a
very sophisticated tool and if you don’t have experience
using static analysis tools, JLint is a good tool to start with.
Antic works on Java source files and Jlint works on Java
class file builds. It’s a command line tool and easy-to-use.
It’s available at http://jlint.sourceforge.net.
Figure 2 Test.java program results in NullPointerException
FindBugs
What does this program print?
class NaNTest {
public static void main(String[] s) {
double d = getVal();
if(d == Double.NaN)
System.out.println(“d is NaN”);
} Figure 3 The DeadLock.java program results in a “deadlock condition”
private static double getVal() {
return Double.NaN;
} PMD
} What’s wrong with the program in Listing 1? If you
try to run it (as shown in Figure 2) you’ll get a NullPointer-
You might be surprised to find that it doesn’t print any- Exception!
thing! What went wrong? The FindBugs tool detects the What could have gone wrong? PMD detects it and warns
problem and warns us about it (see Figure 1). of the problem:
The bug is that the condition (NaN == NaN) evaluates
to false! In the condition (d == Double.NaN), this code $ pmd Test.java text design
checks to see if a floating-point value is equal to the spe- Test.java:3 Overridable method ‘foo’ called during object con-
cial “Not A Number” value. The IEEE 754 floating-point struction
standard provides the special semantics of NaN: no value
is equal to NaN, including NaN itself. So, the check (d == The bug in this program is that the constructor of
Double.NaN) always evaluates to false. The correct check the Base class calls an overridden method. Construc-
to use is the condition check Double.isNaN(x). tors don’t support runtime polymorphism since derived
The FindBugs tool detects this problem and aptly objects aren’t constructed when the base class constructor
names it “Doomed test for equality to NaN”. executes. The virtual method foo is called from the base
The FindBugs tool is excellent. It detects correctness class constructor. Since foo is overridden, the overridden
problems, multithreading issues, performance problems, foo calls the toString method from I, which isn’t initial-
and bad practices. It has less false positives and warns ized yet (note that i gets initialized only after the Derived
of only critical or important problems that are likely constructor has completed executing). Because of this, the
to be actual defects in code. So, if you’re pressed for time program terminates with a NullPointerException. For this
and want to look at only important problems, this tool reason, it’s not a recommended programming practice to
will suit you. It runs on Java class/jar files, so no Java call overridable methods from constructors.
source files are needed to use it. And it runs in a nice The PMD tool checks for problems like possible bugs,
standalone GUI. You can download it at http://findbugs. design rule violations, duplicates, sub-optimal or dead
sourceforge.net/. code, suggestions for migration to newer JDK versions,
JDJ.SYS-CON.com May 2008 11
3. FEATURE
J2EE, JavaBeans, JSP, and JUnit rules. It works on Java Acquiring multiple locks is not a recommended program-
source files and can be used from command lines. Plug- ming practice. However, it’s often required in practice, so
ins for popular IDEs like Eclipse, JBuilder, and JCreator when we need to acquire multiple locks, we should ensure
are also available. You can download it from http://pmd. that we acquire them in the same order in the code.
sourceforge.net/. Alternatively, we can consider using non-blocking locks
when we attempt to acquire multiple locks. The tryLock meth-
QJ-Pro od in the java.util.concurrent.locks.Lock interface provides
What’s wrong with the program in Listing 2? this ability. It’s also recommended to release locks quickly and
It’s likely that the program will hang after running success- not hold the locks for a long time; so, it’s not recommended to
fully for few times as shown in Figure 3; in other words, this use sleep/wait methods after acquiring a lock; consider using
program can lead to a “deadlocked condition” (the program the wait/notify mechanism instead to avoid deadlocks be-
actually hint at this: the name of the class is Deadlock!). cause of holding a lock for a long time waiting for a condition
The QJ-Pro tool detects it as shown in Figure 4. to occur.
The bug in this code is that the code acquires two locks in The QJ-Pro tool checks for problems like conformance to
opposite order; and after that a sleep/wait method is called coding standards, coding best practices, misuse of features,
– this condition will usually result in a deadlock. and APIs. It gives lots of violations by default, so you’d have to
Locks are the basic Java synchronization mechanism. Using spend some time selecting the list of rules you want to run for
locks ensures exclusive ownership for a thread while executing your project. It works on Java source files and is easy-to-use in
a critical section. Incorrect use of synchronization can lead to its standalone GUI version (shown in Figure 5). You can use its
deadlocks. plug-ins with popular IDEs like Eclipse, JBuilder, JDeveloper
A big problem with deadlocks (as with most multithreading plug-ins or Ant. You can get QJ-Pro from http://qjpro.source-
problems) is that deadlocks are “non-deterministic” – they forge.net/.
need not reproduce consistently, and so it’s difficult to detect,
reproduce, and fix problems related to deadlocks. Other Tools
Acquiring multiple locks is prone to deadlock, particularly Other than the four tools covered here – Jlint, FindBugs,
if not done in the same order or if the sleep()/wait() in the PMD, and QJ-Pro – there are many other FOSS tools avail-
Thread is called after acquiring locks. In this program, foo and able. For example, CheckStyle checks for adherence to coding
bar acquire locks in opposite order and call sleep(). Hence standards such as Sun’s. You can get it from http://checkstyle.
deadlock occurs. sourceforge.net/. JCSC (Java Coding Style Checker) checks for
coding style adherence and for common bugs. You can get it at
http://jcsc.sourceforge.net/. There are many more useful tools
like Classycle, Condenser, DoctorJ, and JarAnalyzer. More in-
formation and links on Java tools is provided in the Resource
section.
Conclusion
We saw four specific static analysis tools that can be used to
detect not-so-common defects in code. They are free, easy-to-
integrate with IDEs, and easy-to-use. It’s highly recommended
to use such tools to improve the quality of the software by
detecting and fixing bugs early in the software lifecycle.
Figure 4 QJ-Pro detects deadlock because of acquiring multiple locks
Resources
• If you’re interested in a list of the Java FOSS static analysis
tools available, check http://java-source.net/open-source/
code-analyzers.
• “A Comparison of Bug Finding Tools for Java” by Nick
Rutar, Christian B. Almazan, and Jeffrey S. Foster from
the University of Maryland provides a detailed technical
comparison of Bandera, ESC/Java, FindBugs, JLint and
PMD tools. See http://www.cs.umd.edu/~jfoster/papers/
issre04.pdf.
• If you’re using Eclipse, it’s very convenient to use Java
tools as plug-ins. The list of available plug-ins for Java is at
http://www.eclipseplugincentral.com/Web_Links-index-
req-viewcatlink-cid-14-orderby-rating.html.
• The book Java Puzzlers: Traps, Pitfalls, and Corner Cases
by Joshua Bloch and Neal Gafter covers many interesting
bugs that can happen in code. Check the link http://www.
Figure 5 QJ-Pro detects deadlock because of acquiring multiple locks javapuzzlers.com/.
12 May 2008 JDJ.SYS-CON.com
4. Listing 1 synchronized(That.class) {
class Base { Thread.currentThread().sleep(10);
public Base() { }
foo(); }
} }
public void foo() { public static void bar() throws InterruptedException {
System.out.println(“In Base’s foo “); synchronized(That.class) {
} synchronized(This.class) {
} Thread.currentThread().sleep(10);
}
class Derived extends Base { }
public Derived() { }
i = new Integer(10);
} public void run() {
public void foo() { try {
System.out.println(“In Derived’s foo “ foo();
+ i.toString()); bar();
} } catch (InterruptedException e) {
private Integer i; System.out.println(“Caught interrupted
} exception”);
}
class Test { }
public static void main(String [] s) { }
new Derived().foo();
} class DeadLock {
}
public static void main(String []s) {
DoSynchronize pc = new DoSynchronize();
Thread t1 = new Thread(pc);
Listing 2
class This {} Thread t2 = new Thread(pc);
class That {}
t1.start();
t2.start();
class DoSynchronize implements Runnable {
}
public static void foo() throws InterruptedException {
synchronized(This.class) { }
JDJ.SYS-CON.com May 2008 13