Atom Feed SITE FEED   ADD TO GOOGLE READER

Discovering the platform profile from Java

What's the simplest way to get CPU speed, amount of RAM, OS version, and other hardware details from the running JVM? I'm putting together a yet-to-be-announced tool that will include hardware specs in its reporting.

So far, I've been able to get the hardware profile on Mac OS X using sysctl and on Linux using /proc/cpuinfo and /proc/meminfo:
java.version: 1.5.0_13
java.vm.name: Java HotSpot(TM) Client VM
os.arch: i386
os.name: Mac OS X
os.version: 10.5.1
user.name: jessewilson
host.name: jessewilson-macbookpro-2.local
os.kernel.version: 9.1.0
host.model: MacBookPro1,1
host.cpus: 2
host.cpu.speeds: 2000000000
host.cpu.arch: i386
host.cpu.bits.physical: 32
host.cpu.names: Genuine Intel(R) CPU 1500 @ 2.00GHz
host.cpu.caches.l2: 2097152
host.memory.physical: 2147483648

This comes from a quick-n-dirty Java app, HostInfo.java. Curious - anyone know of a simpler approach? Or a more reliable API? I'm not interested in JNI or nontrivial applications, since they complicate deployment.

Still to do - figure out what's necessary to discover this information on the Windows platform...

Coding in the small with Google Collections: ImmutableSet

Part 15 in a Series.

The Google Collections project has released an impressive new collection of features.

The new release has prompted me to continue this series. My favourite feature of the new release is ImmutableSet. It's a top-level implementation of Set that's full of features - this class alone justifies adding the entire .jar to your application's libraries folder...

For static constants


Before
  public static final Set<Integer> LUCKY_NUMBERS;
static {
Set<Integer> luckyNumbersMutable = new HashSet<Integer>();
luckyNumbersMutable.add(4);
luckyNumbersMutable.add(8);
luckyNumbersMutable.add(15);
luckyNumbersMutable.add(16);
luckyNumbersMutable.add(23);
luckyNumbersMutable.add(42);
LUCKY_NUMBERS = Collections.unmodifiableSet(luckyNumbersMutable);
}

After:
  public static final ImmutableSet<Integer> LUCKY_NUMBERS 
= ImmutableSet.of(4, 8, 15, 16, 23, 42);


For defensive copies


Before:
  private final Set<Integer> luckyNumbers;

public Hatch(Set<Integer> luckyNumbers) {
this.luckyNumbers = Collections.unmodifiableSet(new HashSet<Integer>(luckyNumbers));
}

public Set<Integer> getLuckyNumbers() {
return luckyNumbers;
}

After:
  private final ImmutableSet<Integer> luckyNumbers;

public Foo(Set<Integer> luckyNumbers) {
this.luckyNumbers = ImmutableSet.copyOf(luckyNumbers);
}

public ImmutableSet<Integer> getLuckyNumbers() {
return luckyNumbers;
}


For more defensive copies


ImmutableSet.copyOf has been heavily optimized when the argument is itself an ImmutableSet. It turns out that this method can no-op if the argument is itself an ImmutableSet, since copying immutable objects is redundant. The more you use ImmutableSet, the cheaper it is to do defensive copies!

For predictable insertion order


ImmutableSet's elements iterate in the same order that they're added in. That means there's less unpredictable behaviour in your application's business logic. There's no need to worry about tests that pass on one JVM and fail with another because of HashSet's unspecified iteration order.
    ImmutableSet<Integer> numbers = ImmutableSet.of(8, 6, 7, 5, 3, 0, 9);
assertEquals("[8, 6, 7, 5, 3, 0, 9]", numbers.toString());


For self-documenting APIs


Before:
  /**
* Returns numbers most likely to be selected in upcoming lottery drawings.
*
* @return an immutable, non-empty set
*/
public Set<Integer> getLuckyNumbers();

After:
  /**
* Returns numbers most likely to be selected in upcoming lottery drawings.
*
* @return a non-empty set
*/
public ImmutableSet<Integer> getLuckyNumbers();


For less memory allocation


ImmutableSet allocates fewer objects and smaller objects than either HashSet or LinkedHashSet. This makes your program's heap smaller. There's also less work for your garbage collector.

For non-null data


ImmutableSet does not permit null elements. This is almost always what you want, and helps to detect bugs early:
Before:
  public Hatch(Set<Integer> numbers) {
for (Integer number : numbers) {
if (number == null) {
throw new NullPointerException();
}
}

this.numbers = Collections.unmodifiableSet(new LinkedHashSet<Integer>(numbers));
}

After:
  public Hatch(Set<Integer> numbers) {
this.numbers = ImmutableSet.copyOf(numbers);
}


ImmutableSet is my new default collection, replacing ArrayList. It's that good. And as a special treat, when I do need a List, Google Collections also includes ImmutableList.

The 'anything goes' SecurityManager

As previously mentioned, my current 20% project involves some RMI hackery. Today I ran into an unfortunate error message:
java.lang.ClassNotFoundException: com.publicobject.m2x.Measurer (no security manager: RMI class loader disabled)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:371)
at sun.rmi.server.LoaderHandler.loadClass(LoaderHandler.java:165)
at java.rmi.server.RMIClassLoader$2.loadClass(RMIClassLoader.java:620)
at java.rmi.server.RMIClassLoader.loadClass(RMIClassLoader.java:247)
at sun.rmi.server.MarshalInputStream.resolveClass(MarshalInputStream.java:197)
Apparently Java RMI won't let me download remote code without a security manager installed. The standard workaround for this problem is to create a .policy like so:
grant {
permission java.security.AllPermission;
};
. . . and then I need to reference the file when I launch the app:
java -cp . -Djava.security.Policy=m2x.policy com.publicobject.m2x.Main
I don't like this solution because it forces me to change how my app is launched, complicating deployment. It adds another file to manage. And the deployment work needs to be solved in Unixland, far from my comfort zone of Javaland.

It turns out I can do the same thing in Java code by installing a no-op security manager:
    System.setSecurityManager(new SecurityManager() {
public void checkPermission(Permission permission) { }
public void checkPermission(Permission permission, Object context) { }
});
I like this better.

Java should be first on the Java Platform


When designing APIs for the Java platform, programmatic access must be a first-class citizen. APIs that require XML, configuration files, or System properties shouldn't be the only way to access functionality.

Java RMI without a webserver

One of the four steps to setup Java RMI is "Making classes network accessible." Since I'm new to Java RMI, I found this requirement surprising. We have a client and a server. Of the two of them, surely one of the two has a full set of classes. Why require a third server to host the classes?

I suppose they were thinking that somewhere near the RMI server would be a big expensive heavyweight J2EE container, and that thing can serve the classes. But even if I have the J2EE server setup, this is still annoying - I still need to configure the webserver, and then keep it's jars synchronized with the ones my RMI server is using.

Instead, I decided to do the Simplest Thing That Could Possibly Work. I wrote a tiny HTTP Server (168 lines of code) and used it to publish all the classes in my local JVM. Now in my RMI code, I simply need this:
    String currentHostname = "jessesmac.publicobject.com";
new RmiClassServer(currentHostname).run();

The RMI server serves classes to anyone who's interested. I don't need to tell it which classpath to use - it uses the exact same classes that the local classloader uses, via Class.getResource.

Sound useful for your RMI application? You'll need RmiClassServer.java and MiniHttpServer.java, both of which are available under your choice of Mozilla 1.1 or LGPL license.

A final word of caution - this server exposes everything on your application's classpath. Unless your classes themselves are public, please don't put this server (or your RMI server!) on your public website.

MiniHttpServer.java - an HTTP Server in 168 lines

For part of an project which I'll be announcing shortly, I needed an extremely lightweight HTTP server. Fortunately, HTTP is quite easy-to-implement. Tonight I hacked together MiniHttpServer.java, a simple server with zero third-party dependencies.

I was able to support the core of HTTP in with just 168 lines by doing only the bare-minimum. Here's the server's core:
        nextLine();
readUntil("GET\\s+");
String url = readUntil("\\s+HTTP/1.1");

do {
nextLine();
} while (readUntil("$").length() > 0);

InputStream responseData = handler.getResponse(url);
if (responseData != null) {
write("HTTP/1.1 200 OK\r\n\r\n");
int b;
while ((b = responseData.read()) != -1) {
connection.getOutputStream().write(b);
}

} else {
write("HTTP/1.1 404 Not Found\r\n\r\n");
write("404 Not Found: " + url);

}

connection.close();

If you need an embedded HTTP server, please help yourself to this code. It's fully open source, and available under your choice of Mozilla 1.1 or LGPL license.

Java Minutiae - Instantiating inner classes

Pop quiz - without reflection, access to private members, or changing the source, create an instance of Inner.
public final class Outer {
public static final Outer INSTANCE = new Outer();
private Outer() { }
public class Inner { }
}

Note that Inner is non-static, so each Inner has a reference to its containing Outer.

Show Answer

Java Minutiae - Map.remove()

Suppose you'd like to remove an entry from a Map, and perform some action only if the remove actually removed. Since Map.remove() returns the value associated with the removed key, we can do this:
  if (map.remove(key) != null) {
deleteAssociatedFiles(key);
}

Unfortunately, if the map tolerates null values, this approach doesn't differentiate between removing 'key→null' and not removing. The standard workaround is to do two map lookups (which fails for ConcurrentMaps):
  if (map.containsKey(key)) {
map.remove(key);
deleteAssociatedFiles(key);
}

But there is an elegant solution. Although Map.remove() doesn't know 'null' from 'nothing', it turns out that Set.remove() makes the distinction. That method returns true only if the set changed. We simply operate on the map's keys, which will write-through:
  if (map.keySet().remove(key)) {
deleteAssociatedFiles(key);
}


I learned this trick from Jared of the Google Collections team.

Java Minutiae - I love ternary

I love the ? : ternary operator. It makes my code feel tighter. Plus, I get to save code - fewer assignments, fewer return statements, and variable declarations are inline. In the code I was writing yesterday, a duplicated call to 'add()' made me itch for the ternary:
    for (String key : keys) {
if (getCardinality(key) == 1) {
singleValuedKeys.add(key);
} else {
multiValuedKeys.add(key);
}
}

Unfortunately, with standard use of a ternary, the code gets bigger instead of smaller:
    for (String key : keys) {
Set<String> setToAddTo = (getCardinality(key) == 1)
? singleValuedKeys
: multiValuedKeys;
setToAddTo.add(key);
}

Taking it one-step further, I inline the setToAddTo variable. This is where the code loses its familiar feel:
    for (String key : keys) {
((getCardinality(key) == 1)
? singleValuedKeys
: multiValuedKeys).add(key);
}

It's tight, but somehow I've written Java code that doesn't have the Java feel. So I ended up dropping the ternary, and went with the familiar if/else structure. What's your preference?

Guice wins Jolt Award!

From the Guice User's group,

Congratulations Bob, Kevin and the rest of the Guice team! Guice beat out rival Spring and several other worthy projects to win the 2008 Jolt Award for libraries and tools.

It was great to see the guys win - they deserve to be recognized for their hard work.

The award is also good news for Google's open source effort. It confirms Guice as a top-tier open source project, and encourages them to invest more in open source. Plus, the award should help to put some momentum into the development of Guice 2.0.

I'm looking forward to seeing Kevin & Bob's picture in an upcoming issue of Dr. Dobb's Journal. In the picture, they're holding the award: a giant can of Jolt encased in lucite. The award may also be recognized on one of the Google blogs.