While the Java VM shields most developers from having to
think about the memory-management aspects their Java objects, the VM does not
completely manage other types of resources automatically, says Gwyn Fisher, CTO
of Klocwork in this interview with Artima. Great Java developers learn to understand exactly
what the JVM does, and does not do, for their objects.
There has been much discussion lately about code quality in
Java. Most developers would agree that the JVM provides an excellent
infrastructure for high-quality code, because it defines a uniform execution
model across operating systems and because of its automatic garbage collection capabilities.
The notion that the JVM somehow takes care of all aspects of
resources management have become wide-spread in the Java community, says Gwyn
Fisher, CTO of static analysis tool maker Klocwork.
While the VM does a good job managing resources for Java objects, it's not
designed to take care of all aspects of resource allocation and de-allocation.
When developers neglect to think through just what the VM does, and does not
do, for their objects, coding errors result:
Why do so many
developers still think it's reasonable to create code that doesn't work?In some ways, it has become
cheaper to deal with failure. What's the worst that happens? You just restart
your Web server. You may even try to mask failure with some form of redundancy.
Provided that you can make that work, software failure is no big deal, some
would say.
In the real world,
however, software failure is a very significant problem. To bring your own
denial-of-service attacks right into your own code, to accept to live with a
relatively low-quality code base, is less and less acceptable as the software
we write goes onto devices, cell phones, or something that even gets
implemented in your body.
In all of those
interaction points, it is no longer acceptable for your software to crash. The notion of consumer brand identify and consumer acceptance of
things also changes how we perceive software quality: If a device you bought
crashes every so often, it's only a matter of time before you return it. If your consumer-facing Web site performs poorly, or needs to
be periodically restarted, that is going to negatively affect your brand image.
In the Java space,
the notion that you didn't have to worry about failure has become especially
prevalent, because the Java language is so forgiving of runtime errors. And
it's very nice to operate within an abstraction such as the JVM.
The JVM takes care
of you in so many ways that you get used to the mentality that you don't have
to worry about much at all. The problem is, there are
edge-cases where the JVM isn't really taking care of you. Most people are
building JVMs on other software, the OS, which is on
hardware. At the end of the day, you're still dependent on that middle slice of
the cake.
For example,
relatively few [Java] developers understand that if they don't close a socket,
the JVM is going to garbage-collect objects, but in the underlying operating
system, the socket at the OS level, that never goes away. The JVM may manage
the memory for you, but it often doesn't manage other resources that your code
has consumed.
That gets worse
and worse the higher up in the stack you go in terms of language abstractions.
We try to stay out of the debate between dynamic and statically typed languages.
But how many developers in dynamic languages really, fundamentally, understand
what's going on in terms of resource consumption and use? At the end of the
day, you as a developer are responsible for knowing what's going on.
Tools can really
help in that environment. We provide a static analysis tool, for example. We
have our own compilers. Instead of Java bytecode, the
output of our compiler is a database. We can then analyze that database for
behavior, including erroneous behavior. We provide checks for about 175
different kinds of problems, and support Java, C and C++ out of the box.
Especially in a real-time environment, there is a lot of mixed code, not
one-hundred percent Java.
The difference in
focus between the C/C++ and Java platforms couldn't be more pronounced. Between
our C and Java environments, we have roughly the same number of code check
rules. In C and C++, the checks we're performing are very dependent on the code
you write: We're really worried about null pointers and memory leaks, and
buffer overflows, and things of that nature.
In Java, there's a handful of Java language checks. But what you
often don't get right are the things you're dependent
on, all the framework interaction, the platform interaction, the Web server
interaction. You almost never get that stuff right the first time. The vast
majority of the Java checks in our product are all platform and framework
interactions checks, not language checks: "Did you close that socket? Did
you close that SQL connection? You're injecting a String into something you
probably don't want to."
If you look at the
productivity improvements of Java, you don't have to worry about the language
you're writing in any more. The beautify of Java is there is so much code out
there that you can pick up and use in your projects. But you often don't know
what that code is doing, how that code behaves in the environment and, by
extension, how your code interacts with the environment.
The single most
important thing you can do as a developer, is to fundamentally understand what
the objects you're dealing with actually are, what they actually do, think
about them as a C developer would have to think about them. Think about what
those objects are doing under the covers, and in terms of the platform and the
operating system, and in terms of hardware resources. Try to think about them
as a piece of hardware: What is that thing going to do? If you don't switch it
off, what is going to happen?
You can be a good
Java developer and never worry about that stuff. Thinking outside the JVM is
the important thing for a great Java developer. To be a great Java developer,
you have to understand what the JVM is doing for you.
To what extent do you agree with Gwyn Fisher that great Java developers need to think about the interaction between the JVM and their environment, and about how the JVM interacts with Java objects?