Archive for the tag: Java

Java Sockets: Detecting Lost Clients

Developer's Cave, Island Forge Comments Off
Running autonomous test clients against my game server, I kept generating a situation in which several client network connections (TCP) remained open. This resulted in those client sessions remaining active long after the client had disconnected. This had the potential to retain game state in the server, preventing memory from being reclaimed (effectively a memory leak). The player might not be able to log in later, because they still have an active (albeit bogus) session. No matter how many safety checks I put into the networking logic, I could not detect these broken, lingering connections. As it turns out, Java sockets cannot report they have closed when the socket was not shut down cleanly, without actively attempting to read/write data. My game server protocols are rather conservative, and do not chatter unnecessarily with clients. As a result, an abruptly disconnected client socket could idle indefinitely, so long as no data was destined to be sent its way. To alleviate this problem, the server networking logic now takes note of client communication times. After a configurable timeout with no activity, the server sends a ping, to which the client is to pong. This has one of three results. If the pong is not returned within another probationary timeout, the client is considered lost, and the session is forcibly closed. If the client is, in fact, alive and well, the pong refreshes its most recent activity. The third result is what I've most commonly found: the attempt to send the ping over a broken connection triggers a network error (IOException), which is caught and handled, more-or-less, cleanly. In a perfect world, client software would cleanly tear down all TCP connections. In the real world, several factors can prevent this ideal behavior (network failure, software crash, killed application). In any case, server systems cannot rely on clients to behave ideally. While I could spend the rest of my days improving network communication logic (resume available upon request), the above technique is simple enough and appears to be working well in ongoing tests.

Undesirable Characters Hanging About

Developer's Cave, Island Forge Comments Off
In my personal obsession to deallocate all unnecessary content from server memory, I was down to one or two Character objects still hanging around after all clients had exited. Notice that these aren't java.lang.Character objects, but instances of my gameplay Character class. The issue was that somewhere some subsystem was holding a (hard) reference to the Character object. I used VisualVM to create a heap dump of the running server. The heap showed a single Character object instance being held by the Pulse subsystem. Further investigation revealed flawed Character exit world logic, which neglected to signal the final departure of a Character in some cases. With the departure signal fixed, I have not been able to reproduce this problem (this is a good thing). When all game clients exit, all content objects are now deallocated. This should result in a more stable server, capable of longer uptime. In addition, this investigation revealed other areas of improvement to pursue. "Always... no, no... never... forget to check your references." -- Dr. Meredith

Thread Monitoring with java.lang.management

Developer's Cave, Island Forge Comments Off
I recently delved into the java.lang.management package, in order to measure thread activity in my Potential RPG server application. Tools like VisualVM offer real-time probing, but I also like to have my applications produce their own statistical results. In this case, I'm logging CPU time (and a bunch of other stats) from my server application, which I use to produce performance charts (using the JFreeChart library). In java.lang.management, OperatingSystemMXBean reports the CPU time of your application process. The ThreadMXBean class reports the CPU time of each active thread. CPU time measures time spent being executed by the CPU. Contrast this with wallclock time, which may include time when your process is swapped out for other work. In addition, you can query user time, which is the portion of CPU time spent executing your application, as opposed to performing system time events such as disk I/O. Java tip: How to get CPU, system, and user time for benchmarking is an excellent article on using these classes. In particular, notice that ThreadMXBean does not report on threads that have died. To avoid missing thread activity, it is important to poll for thread activity at some granularity. I'm trying a 500ms polling rate, but my initial results imply that the thread I'm using to do this polling is using a significant percentage of the overall CPU time. Any thread activity missed by the polling granularity can be reported by subtracting the sum of sampled thread time from the total process CPU time. By increasing the polling rate, you can catch more short-lived threads, at the expense of more overall CPU time spent polling. In some cases, I'm using a thread pool (Executors.newCachedThreadPool()). By default, each thread will have a unique name, but this is not a requirement. By passing in a custom thread factory, I can name all threads that perform a similar service the same. In my thread polling routine, I add the CPU time of each thread by name. This way, even if several threads are actively performing some task, the CPU time is reported for the group. By monitoring my thread activity, I've found which parts of my application are working the hardest. I've also identified a few rogue threads (probably quick-and-dirty cases in which I extend Thread itself), which need to be wrangled. These might account for the CPU time not being captured by my polling. Overall, these thread monitoring results give me a good idea where to improve performance.

Java Click Count: Windows vs Linux

Developer's Cave, Island Forge Comments Off
Mouse events from Java Swing report the click count. When mouse events are generated within some click threshold (which should be an operating system setting), the click count increases. One common problem is processing single- versus double-clicks. Java does not hold back the single-click event (click count of 1) even when a double-click (click count of 2) may be forthcoming. This is for good reason: As well designed of a programming language that it is, Java cannot see the future. There are techniques (documented elsewhere) for dealing with this aspect of mouse processing in Java. The impetus for this article is mouse event inconsistencies between platforms. Particularly, click counts seem to be reported differently for different events on different platforms. Read the rest of this entry »

Using JTextArea in a JList

Developer's Cave 5 Comments »
JTextArea is a convenient Swing component to use when word-wrapping is needed. To display a list of multi-line messages, for example, the obvious solution is to use a JTextArea as the ListCellRenderer Component for a JList (within a JScrollPane). However, you will soon find that the text often does not end up word-wrapped as expected. After reading post after post of mystic incantations, none of which actually seem to fully work, I present my solution for using a JTextArea in a JList: Don't. Read the rest of this entry »

Swing Model-View-Controller

Developer's Cave Comments Off
It's old news that Java's Swing GUI toolkit follows a deficient Model-View-Controller (MVC) architecture. In most cases, Swing fuses together the notion of the View and Controller, but offers a separate Model. At least, that's what the naming convention implies. For example, JComboBox should be a View-Controller to a ComboBoxModel. This particular case failed me today. Read the rest of this entry »

Comparable Max Function

Developer's Cave Comments Off
Here's a helpful method for returning the maximum of two Comparable objects. Do the Java APIs provide this somewhere?
/**
 * Return the <i>maximum</i> of the two arguments. If the arguments 
 * are <i>equal</i> (as defined by the Comparable contract), the
 * <i>left-hand-side</i> argument is returned.
 */
public static <T extends Comparable> T max(T lhs, T rhs)
{
    return rhs.compareTo(lhs) > 0 ? rhs : lhs;
}

Java AWT-Shutdown Thread Refuses to Die

Developer's Cave, Island Forge Comments Off
The cleanest way to close a Java GUI application is to dispose of all top-level resources (JFrame instances, for example) and allow the AWT/Swing thread to close itself. Calling System.exit(0) or Runtime.getRuntime().halt(0) is often prescribed, but not recommended, as it could preempt proper shutdown procedures in your application. If your Java GUI application uses DISPOSE_ON_CLOSE mode, check that your process is exiting cleanly. If it is not, the most likely culprit is that the AWT Event Dispatch Thread is still active. This is well-known AWT/Swing behavior, but there is a scenario in which Java will refuse to shut down this thread, even with all resources closed and disposed. Read the rest of this entry »

Java Font Changes (in Ubuntu)

Developer's Cave 2 Comments »
I updated my development platform to Java 1.6.0_18 and noticed a disturbing font alteration in all Java applications. I'm developing in Ubuntu 9.10, which currently bundles Java 1.6.0_15 (in the sun-java6-jdk package), so I manually installed the latest for testing. I have yet (since yesterday) to investigate whether this is Ubuntu specific. Font configuration changes were noted in the Java 1.6.0_18 Release Notes, associated with a particular bug. Preliminary investigation implies that Java's attitude toward font consistency has changed over time. Early Java 1.3 Physical Fonts documentation makes clear that:
The SDK's physical fonts offer ... Consistent Look and Feel: Your applications will look the same on all platforms because they will be using the same fonts. This makes testing, deployment, and support easier in a cross-platform environment.
In contrast, a more recent bug submission was thoroughly thrashed for suggesting that fonts should remain consistent across platforms and versions. This seems to contradict one of the primary tenets of the Java platform: "Write once, run anywhere" In the future, I'll be looking into explicitly loading a specific font set, possibly by embedding custom fonts within my application.

Why is LinkedList.clear() linear?

Developer's Cave 4 Comments »
I was just perusing the Java source code (because I don't read the morning newspaper), when I discovered that java.util.LinkedList.clear() is implemented to operate in linear time. The documentation does not specify its order of growth, and I intuitively assumed that a linked list clear implementation would be a constant time operation. Could this be an artifact of early Java development, leaving a legacy of poor performance? The remainder of this article explores the potential to significantly improve application performance when using the LinkedList.clear() operation. Read the rest of this entry »