To equals() or not to equals()
“How to Write an Equality Method in Java” from Artima:
Class
java.lang.Objectdefines anequalsmethod, which subclasses may override. Unfortunately, it turns out that writing a correct equality method is surprisingly difficult in object-oriented languages. In fact, after studying a large body of Java code, the authors of a 2007 paper concluded that almost all implementations ofequalsmethods are faulty.
The article goes into some depth on how to write a good equals method, and on the pitfalls that surround such a method. The article also makes a reference to “Effective Java Second Edition” by Josh Bloch which I am currently reading:
In Item 8 of Effective Java1, Josh Bloch describes the difficulty of preserving the equals contract when subclassing as a “fundamental problem of equivalence relations in object-oriented languages.” Bloch writes:
There is no way to extend an instantiable class and add a value component while preserving the equals contract, unless you are willing to forgo the benefits of object-oriented abstraction.
C3P0, MySQL and ‘Error Reading Communication Packets’
I have been using C3P0 as my connection pool for iBatis to connect to a MySQL database (via the MySQL connector for Java) and have been dogged by an annoying issue where the client (presumably iBatis) drops the connection without closing it first causing MySQL to complain with the error message “Got an error reading communication packets”. Not a major issue because it was not causing the application to fail, but it was generating about 2GB of unnecessary log every month.
Basically what is going on is that the connection times out at the MySQL server end because it is idle (more than 60 seconds in this case). I set the idle timeout in C3P0 to 50 seconds to ensure that the connection was closed there before the timeout triggered in MySQL, obviously that was not working. As I mentioned above what I think is going on is that iBatis is dropping the connection without closing it properly first:
I get pages of error logs with this message -
“Got an error reading communication packets”. And the aborted clients
are easily in hundreds.You get that message in the log every time the server closes a client
connection because it was inactive too long. Too long is “longer than
wait_timeout”.
In fact C3P0’s author, Steve Waldman, mentions this:
Sometimes client applications are sloppy about close()ing all Connections they check out. Eventually, the pool grows to maxPoolSize, and then runs out of Connections, because of these bad clients.
I was not about to go grubbing around in the iBatis code (and whatever else) to figure out where the issue was, and found that ‘propertyCycle’ would probably help me:
propertyCycle
Default: 0
Maximum time in seconds before user configuration constraints are enforced. Determines how frequently maxConnectionAge, maxIdleTime, maxIdleTimeExcessConnections, unreturnedConnectionTimeout are enforced. c3p0 periodically checks the age of Connections to see whether they’ve timed out. This parameter determines the period. Zero means automatic: A suitable period will be determined by c3p0. [You can call getEffectivePropertyCycle...() methods on a c3p0 PooledDataSource to find the period automatically chosen.]
The ’suitable period’ chosen by C3P0 here was 12.5 seconds, which means that it is very likely for the cycle to fall outside my window of 50 and 60 seconds (see above.) Changing this to 5 seconds fixed the issue (10 still generated errors once in a while.) Interestingly the ’suitable period’ is stored internally as a float (as retrieved by getEffectivePropertyCycleDefaultUser()) but is set as an int (as set by setPropertyCycle()), go figure.
Revolting Code
<rant>
Ok, so there is no lack of Java style guides out there, you can get one from Sun, there is also a good one available from Geotechnical Software Services, and so on and so forth.
And so I am currently checking out this package (which shall remain nameless) where all the method names start with an upper case letter, why, oh why…
And you have classes where the method ‘EntityType()’ gets the entity type (see that upper case letter) and ‘EntityType(…)’ actually sets the entity type, why, oh why…
And the list goes on and on…
</rant>
JVM GC
Over the past couple of weeks I have digging into a JVM performance issue, specifically a process which would start off running fast and then slow down at some point.
Tracking the performance of the GC I was able to figure out that the tenured generation was getting swamped by a large allocation that would not let go causing GC to go into full GC over and over again thereby killing performance. Indeed the library I was using to parse sentences would allocate space in proportion to the size of the sentence, an always allocate up and never down, so over time it was inevitable that it would swamp the tenured generation.
Effectively the JVM was behaving like an operating system with too little memory and trashing.
The answer obviously is to prevent these unbounded allocations from happening.
JVM Options
I was looking for a list of the JVM options and a colleague provided me with a link to this great page documenting them.
HttpComponents Irritation
I have been using HttpComponents for making web calls in Java, I like it because it gives you various levels of access when putting together HTTP requests, so you can write as much code or as little code as you want, always a crowd-pleaser.
The only bummer I am running into so far is that it seems impossible to get back the final url used for a request if the initial request was redirected and you elected to have redirection handled automatically for you.
Code Reviews
I have not read this article “Automated code reviews with Checkstyle” yet, but the title really sparked my interest though because I am a great believer in code reviews as a tool for identifying bugs and for learning new techniques.
Yet the first paragraph set the hair on the back of my neck on end:
Code reviews are essential to code quality, but no team wants to review tens of thousands of lines of code, or should have to. In this two-part article, ShriKant Vashishtha and Abhishek Gupta show you how to overcome the challenges associated with code reviews by automating them. Find out why Checkstyle is one of the most popular tools used for code review automation, then learn how to quickly enhance its built-in rules with custom ones just for your project. Level: Intermediate
Surely doing automated code reviews miss the main points of doing a code review in the first place, one being that you want to get additional eyes to look at the code, and the other to get insight from other people as to what you could be doing differently and, hopefully, better. Or am I missing something.
Finally Pinned Down my Java Issue
I finally pinned down the Java issue that I have been dealing with, documented in this post.
I finally hit on it when I was doing some work to lazy-load data in a ket object, and found that performance was good when I was part done and went to hell when I was fully done. Back-tracking and digging through the code, effectively cutting out pieces until I narrowed it down to this:
Set urlSet = new HashSet();
#Loop... {
String href = "...";
urlSet.add(new URL(href)); # This kills the JVM
}
What I am doing is extracting the urls from a piece of html and using the Java Set to de-duplicate them. For some reason the last statement causes the JVM to slow down to a point where it is just idling from the CPU’s point of view (2%-5% usage).
However this works fine as a work-around:
Set urlSet = new HashSet();
#Loop... {
String href = "...";
urlSet.add(href);
}
List urlList = new ArrayList();
for ( String href : hrefSet ) {
urlList.add(new URL(href));
}
I am using the latest version of the JVM on Linux Centos 5.0, Dual 2.4GHz Xeon, 4GB RAM:
java version “1.6.0_10″
Java(TM) SE Runtime Environment (build 1.6.0_10-b33)
Java HotSpot(TM) Server VM (build 11.0-b15, mixed mode)
Finally, and not least, thanks to a colleague for suggesting testing the code with strings as opposed to URLs.
Updated – my colleague pushed me to check the Java source code and it turns out that the java.net.URL class uses the java.net.URLStreamHandler.hashCode() method which does a DNS lookup on line 337 to work out the hash code:
InetAddress addr = getHostAddress(u);
Nice…
Java Exceptions
Recently I asked a colleague what the current orthodoxy was regarding exception handling in Java. This is not covered at all well in any of the books I have read, besides which I suspected that this was shifting ground, so asking such a dumb question was in order.
I was pointed to three documents, the official Sun position, Bruce Eckel’s post and finally this (very good) article by Brian Goetz.
Having read all this, and based on my experience, I think this is probably the sanest approach (or least insane depending on your point of view), from the article by Brian Goetz:
Rod Johnson, author of J2EE Design and Development (see Resources), which is one of the best books I’ve read on Java development, J2EE or not, takes a less radical approach. He enumerates several categories of exceptions, and identifies a strategy for each. Some exceptions are basically secondary return codes (which generally signal violation of business rules), and some are of the “something went horribly wrong” variety (such as failure to make a database connection). Johnson advocates using checked exceptions for the first category (alternative return codes), and runtime exceptions for the latter category. In the “something went horribly wrong” category, the motivation is simply to recognize the fact that no caller is going to effectively handle this exception, so it might as well get propagated all the way up the stack with the minimum of impact on the intervening code (and minimize the chance of exception swallowing).
Johnson also enumerates a middle ground, for which he asks the question, “Will only a minority of callers want to handle the problem?” For these scenarios, he also suggests using unchecked exceptions. As an example for this category, he lists JDO exceptions — most of the time, JDO exceptions indicate a condition that the caller will not want to handle, but some cases occur where specific types of exceptions might usefully be caught and handled. Rather than make the rest of the JDO-consuming classes pay for this possibility in the form of catching and rethrowing these exceptions, he suggests using unchecked exceptions here instead.






2 comments