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?
Post your opinion in the discussion forum.Klocwork
http://www.klocwork.com/
Have an opinion? Readers have already posted 29 comments about this article. Why not add yours?
Frank Sommers is Editor-in-Chief of Artima Developer. He also serves as chief editor of the IEEE Technical Committee on Scalable Computing's newsletter, and is an elected member of the Jini Community's Technical Advisory Committee. Prior to joining Artima, Frank wrote the Jiniology and Web services columns for JavaWorld.
Artima provides consulting and training services to help you make the most of Scala, reactive
and functional programming, enterprise systems, big data, and testing.