Friday, December 25, 2009

The Written Word Is Dead. Long Live the Written Word!

It used to be fashionable as each new medium of communication appeared to proclaim that it would kill off all previous media. In particular, the democratization of video was supposed to make text obsolete. Why type “hello”, when you can make a video of yourself saying “hello”? That was the thinking, back when the videophone was The Future.

Well, video may have killed the radio star, but it certainly hasn't killed text. People, those perverse entities whose job it is to make prognosticators look foolish, have been voting with their thumbs, en masse, for text. Most of us who navigate urban sidewalks can barely pass a day without colliding with someone madly typing away on a Barbie-sized keyboard. And most of us have tales of observing two kids sitting next to each other, texting away, only to realize that they were texting to each other. People text even when it would be just as easy to communicate by voice, or for that matter video.

Has the written word killed the spoken word? Well, no, and it probably won't, at least not any time soon. There are plenty of situations where we still want to evoke of the hardwired human responses to tone of voice, or combination of voice and body language. Babies aren't going to start babbling in ASCII, and not too many people are going to buy tickets to a text-only performance of King Lear. Voice is expressive in a way that text is not.

But after 5,000 years of experience with the written word, our species has refined it to the point where text, too, is highly expressive, and what's more, expressive in a way that voice is not. Would you appreciate that cool passions of Jane Austen as much if you were listening to her sitting next to you nattering away, instead of curled up with one of her novels on a rainy afternoon? Would J.R.R. Tolkien, after his voice had given out a tenth of the way through Lord of the Rings, inspire much interest as an oral storyteller?

The written word is also powerful as much for what it does not express as for what it does. It strips away the social cues of voice, letting readers appreciate an argument undistracted by how they feel about the arguer. Text is a hierarchy-busting medium in which the mailboy's good idea can (in at least some reader's minds) outweigh the CEO's bad idea.

All the above reasons for the persistence of text in the modern world are probably familiar, but there's another one that I have not seen discussed frequently, and that is that text offers a channel for conversation that does not have to compete with the same noise (literal and figurative) as speech does. In Second Life, for example, about a third of the people I've met seem to prefer voice to text in environments where both are available, but the rest prefer text. This is not particularly surprising: many Second Life environments are devoted to music (live or recorded), and it would be rude (as well as beside the point) to talk in voice over the music. But Real Life is also full of places where it's uncomfortably loud for speech, and that probably accounts for at least some of those who text where they could talk.

The written word isn't what it used to be. Published writing used to have to pass a series of literate gatekeepers, and that's no longer the case where any idiot (like yours truly) can start a blog. Fogeys who grumble that writing is a dying art have a point, in that the quality of writing most people are likely to encounter daily has gone down over the past few decades (although there's plenty of good writing available for those who look for it). But my guess is that people today are reading and writing more words each day than ever before, even if the style is not exactly Shakespearean. The written word has served us pretty well for 5,000 years, and I expect it will be going strong 5,000 years from now, if people are still around to write.

Wednesday, December 16, 2009

Scala Scrutinized in Israel

I've just returned from vacation, which is my excuse (besides laziness) for not posting for a while.

I've been reading the semi-official Scala manual, Programming in Scala by Odersky et al., and had it with me when we crossed the border from Jordan into Israel. Security at the border is rather thorough, as you might expect in Israel, and you have to put your possessions through an x-ray scanner, as at an airport.

We were traveling lightly, because we spent just one night on our excursion to Petra before returning to Eilat, Israel. I thought the contents of my backpack were unremarkable, but the guard at the scanner machine asked me to open my bag, and then to take out the Scala book. She took it and showed it to her supervisor, and riffled through the pages, and ran it through the scanner again before handing it back to me.

I'm not sure why the book attracted so much attention, but maybe the Israeli border guards are all Clojure fans.

Friday, October 16, 2009

Scala vs. Scala

One bit of fallout from the JVM Language Summit I attended last month was a resolve to learn Scala.

I've been trying to write an implementation of a game my cousin designed, and I decided to use Scala, because the scope of the project seemed small enough that I could combine it with learning a new language, but large enough that it would exercise a fair amount of that language.

And so far, I'm pretty fond of Scala. The underlying semantics are close to Java's, because the language was conceived to run on the Java Virtual Machine, but the Scala compiler does its utmost to infer anything (like the type of an expression, or whether an identifier is the name of a variable or zero-argument method) that would be obvious to a human reader. The result is a great deal less boilerplate than in Java. Furthermore, Scala traits have fewer arbitrary restrictions on their content than Java interfaces, which makes it easier to compose your code the way you think it, instead of the way the compiler wants it.

In the dispute between functional vs. imperative languages, Scala comes down squarely on both sides. Scala seems to have two ways to do almost everything; consider, for example, the imperative-looking for (obj <- mySet; if isGood(obj)) yield transform(obj) vs. its functional equivalent, mySet.filter(o => isGood(o)).map(o => transform(o)). Which is better? I'm not sure I have enough experience with Scala to give a definitive answer, but I do find myself using both imperative and functional forms in my code, and I think the imperative form is easier to follow when you're doing something complicated, and the functional form easier to read when you're doing something simple. Because the rules for transforming between the two syntaxes are pretty straightforward, having both options in the language doesn't seem to impose as much of a mental burden as I had expected.

By making it clear that the dichotomy between functional and imperative languages is a false one, Scala does us the favor of freeing up our energies to argue about something else. On to the next flame war!

Thursday, September 17, 2009

Unconstructable Token Spotted at JVM Language Summit

I've been attending the JVM Language Summit at Sun's campus in Santa Clara, not because I'm implementing a programming language on the JVM, but in my capacity as programming-language-junkie-at-large. The big fuss this year is over the invokedynamic bytecode instruction, which (unlike the other ways Java bytecode provides for invoking a method) can be retargeted at runtime.

This is (at least potentially) a great efficiency gain for implementors of dynamically dispatched languages. Such languages choose the target of a method invocation based on the runtime rather than the compiletime types of their arguments (or even on the arguments' values), and may choose methods to invoke based on method arguments other than the first (the receiver). Often they also let you modify an object's class at runtime to add or remove methods, which requires a dispatch algorithm that not only differs from Java's, but that can change over time.

The infrastructure around invokedynamic is the java.dyn package proposed for Java 7. Since I hadn't been paying much attention to invokedynamic, it took me all day yesterday to wrap my head around the magic that not only allows it to work, but often to do so very efficiently (if you're lucky enough to have the JVM inline everything that it could).

That magic derives from two sources:
  • MethodHandles, which, in their simplest form, are direct references to method bodies, and which the JVM is smart enough to inline; and
  • MethodHandles.guardWithTest, which composes a new MethdHandle from a test and two alternatives, the result of which the JVM is also smart enough to inline.


In effect, at each call site, you can inline a bunch of code (which you can change later, if you need to) that chooses an invocation target. This code will often look as if it's making a choice based on the runtime types of the method arguments originally given, but in practice, if enough gets inlined, those types will be known to the JVM when it's compiling your target-choosing code—so that the target is known at compiletime, meaning no invocation overhead at all if the target is also inlined.

Ever so sweet, if the JVM is aggressive enough about inlining. Which it sometimes isn't, but that's another topic, perhaps best left to people who know more about how the inlining decisions are made.

Anyway, what I really meant this post to be about was a spotting of the Unconstructable Token pattern in the java.dyn API, specifically in the MethodHandle constructor: this constructor is protected, because you may need to make language-specific subclasses of MethodHandle to keep track of whatever your language needs to keep track of—but you obviously can't let people construct a method handle just anywhere. Hence the Magic Token argument (currently of type sun.dyn.Access, but I assume they'll change the name to something less Sun-specific before release), which ensures that only The Authorities can can create a method handle.

I hadn't originally thought of Unconstructable Token in terms of restricting where user-supplied subclasses of framework classes can be allocated, but this is a fine use of it, and Java modules will do nothing to make this use of the pattern obsolete.

Thursday, September 10, 2009

Immutable, Keyable, Canonical

I've been trying to come up for a while with some general-purpose mechanisms for creating canonicalized classes. I ran into trouble trying to formulate the rules, and I realize now that was because I was trying to conflate three distinct concepts into one.

Canonicalization (also called “interning”) is a well-known design pattern; see, for example, the Wikipedia article on interning of strings. A canonical object must have a well-defined immutable identity (which I am calling the object's “key”, by analogy with the use of the term “primary key” in referring to relational databases), and an object with a given identity is stored just once. Canonicalization is useful for simplifying comparisons between objects (their references can be compared, instead of their contents) and also for saving space in applications where many identical objects might otherwise be allocated.

My realization was that I had been confusing the idea of an immutable object with the idea of an object with an immutable identity. Besides being candidates for canonicalization, objects with an immutable identity are also suitable as map keys, because two such objects, when equal, always look up the same value in a map. However, an object with an immutable identity need not be completely immutable. Consider, for example, this class:


final class C {

private final String s;

private int n;


C (String s) {
assert s != null;
this.s = s;
}


public boolean equals (Object o) {
if (o == this)
return true;
if (! (o instanceof C))
return false;
return ((C) o).s.equals(s);
}


public int hashCode () {
return s.hashCode();
}


public String toString () {
return s;
}


public synchronized int n () {
return n;
}


public synchronized void n (int n) {
this.n = n;
}

}


This class has an immutable identity, specified by the value of the final variable s: s is the only field examined by equals and hashCode, and so instances of this class are perfectly suitable for use as map keys. Nonetheless, this class also contains some mutable state, in the form of the variable i.

I'm not the only one to mix up the notions of immutable object and immutable identity. The javadoc for java.util.Map says:


Note: great care must be exercised if mutable objects are used as map keys....


the implication being that only completely immutable objects are suitable keys. The paragraph in question does go on to mention the equals and hashCode methods specifically, so the documentation is not incorrect; still, many other authors have carelessly used “immutable object” and “suitable for use as a map key” as synonymous.

In this post, then, I want to come up with usable definitions of these three concepts:


  • Immutable: Applied to an object, it means that all instance variables of the object are final, and all the object's instance variables of reference type are null or references to immutable objects; or, the object is an instance of a system class known to be immutable, like String.

    An immutable class is a class all of whose instances are known to be immutable; specifically, it is either a system class known to be immutable, or:


    • All instance variables of the class are final; and

    • All instance variables of the class are of an immutable type, where an immutable type is a primitive type or a reference to an immutable class; and

    • All subclasses of the class are also immutable.


    A possibly immutable class is a class that might have both mutable and immutable instances (because even though all its instance variables are declared final and of possibly immutable types, the class, or the class of a reference reachable through one of its instance variables, might have a subclass with non-final variables).

    Note that these definitions do not permit an array to be considered immutable, because Java does not have a way to declare an array element final.

  • Keyable: Applied to an object, it means that the object meets the usual Java criteria for a suitable key in a hashed data structure. Specifically, the object may be an instance of a system class known to be keyable, such as String; but if it is not an instance of such a class, then, for an instance a of class C and some subset K (the “key fields”) of C's instance variables, a is keyable if and only if:


    • a.equals(b) returns false if b is null or of a class other than C. Otherwise, it returns true if and only if all corresponding variables in K are equal.

    • a.hashCode() returns a deterministic value based only on the values of a's instance variables in K (the value returned is not affected by the values of instance variables of any other object, or of any class's static variables).

    • All variables in K are final, and if of a reference type, either are null or refer to keyable objects.


    A class C is a keyable class if every instance of the class is guranteed to be a keyable object. This requires that:


    • C's equals and hashCode behave as described above for keyable objects; and

    • All subclasses of C be keyable classes; and

    • All of C's key fields be final and of a keyable type, where a keyable type is a primitive type or a reference to a keyable class.


    A possibly keyable class is a class that might have both keyable and nonkeyable instances.

  • Canonical: Applied to a class, it means that the class is keyable and that some mechanism is used to avoid creating (except perhaps transiently) more than one instance of the class with the same key.

    An instance of a canonical class is called a canonical object. A canonical object a is necessarily the only one with its key, meaning that a.equals(b) is equivalent to a == b for any possible b.


The discussion above doesn't mention static variables, which clearly are not part of an individual object's state, and so can be ignored when deciding whether an object meets any of the above definitions. More problematic are transient variables—although these are treated for the most part as ordinary instance variables, they are not serialized and so are not part of an object's state when it is saved and restored (possibly in another process). I am inclined now to exclude transient variables from consideration when applying the above definitions to the facilities I'm working on.

Thursday, September 3, 2009

Reflecting Darkly on Generics

Although you can do reflection on generic types in Java, the information available from java.lang.Class and the java.lang.reflect classes is pretty raw.

I came across a situation the other day where I had something like:


interface I<T> {
T foo ();
}

abstract class C implements I<String> {
}


and I wanted to ask: what does C.foo() return? The answer, obvious to a human reader, is String, but deducing this using reflection requires traversing C's ancestry and explicitly resolving the type variable T.

It would be nice if there were some general-purpose facilities built into Java to answer questions like:


  • If a given Method m is invoked on an object declared to be of type T, what are the type bounds on the returned value?

  • If a given Method m that takes n arguments is invoked an object declared to be of type T with arguments of specified types Ui, but omitting one argument k, so that 0 ≤ i < k and k < i < n, what are the type bounds on argument k?


Without having made any attempt to write any such facilities myself, I can't say exactly how hard they would be to write, but my feeling is that they would not be easy.

But, if that's not bad enough, they might be impossible to write in a definitive way consistent with the Java language specification—see, for example, this article, which says that the Java generic type inference algorithm is underspecified.

Friday, August 14, 2009

Live from Second Life

“Live from Second Life!” That's how people who are broadcasting over Internet radio while logged into Second Life tend to announce themselves. Which, given the immersive nature of the medium, feels entirely natural until you think about it. Of course, they're actually broadcasting from wherever they are in Real Life. But since whatever they're saying usually concerns the people whose avatars they see in the vicinity of their own avatars, the feel of addressing an intimate gathering is inescapable.

But this weekend I'm blogging live from Second Life in an entirely different sense. I'm attending the Second Life Community Convention in San Francisco. The first sessions of the convention began yesterday afternoon.

I was afraid the convention might be a little dry—lots of people with Real Life or Second Life businesses nattering on about Synergies and Leveraging Brands and other buzzword-laden nebulosities—but it's been a lot more fun than that. I crashed a couple of Art track sessions yesterday. I know zip about art, but I had a blast: artists can be just as creative in conversation as on the metaphorical canvas. The high point of the afternoon was a few short scenes from plays prepared by Z. Sharon Glantz (Lailu Loon in Second Life), who had us read the scenes and then discuss how we'd stage them in Second Life. These were classic brainstorming sessions where wild ideas flew thick and fast. Lailu's stated focus was on how to make Second Life drama that would be accessible to people who weren't familiar with Second Life, but I'm afraid I kept coming up with ways to incorporate Second Life in-jokes into the scenes (are jokes actually funnier when only your friends get them?).

Making virtual worlds accessible to people who aren't familiar with them is a theme of several conversations I've had so far. I was talking with a Belgian journalist last night (whose name I failed to catch) and he was complaining about the number of job applicants he encounters—people in their 20s—who aren't familiar with new media. He says he asks them in interviews, Do you play World of Warcraft? Do you blog? Journalism isn't quite the manual-typewriter-in-an-exotic-location profession it used to be.

This morning's keynote address was from Ray Kurzweil, appearing to us from Second Life, projected on a screen at the front of the room. His presentation focused on the exponential growth of various technologies, including, in recent years, the use of virtual worlds. His contention that within 20 years or so many people will have neural implants that let them interface directly with virtual worlds seemed a little early to me—I'm not sure that many people will move into brain hacking that quickly—but it's clear to me that enough people find virtual worlds compelling that people will keep looking for lower-friction ways to inhabit them.

Sunday, August 9, 2009

Unconstructable Token

Here's a story about a problem, and about a pattern that solves the problem. Both the problem and the solution are specific to Java, because they involve Java's visibility rules.

I wrote a Java method m as part of a project at work. It was an implementation-detail method, not to be called by the client applications of the project, that needed to be called only in a certain context. I provided a public method p that set up the context and called m—but as happens so often, the project had evolved to have a structure more organic than organized, and p was in a different package from m, which meant that m had to be declared public.

My coworker, writing a client application of my project, wanted to invoke the operation that p performed, but didn't recall the name of the method he wanted to use. So, using his helpful IDE, he searched. Well, I had given m and p similar names—no, I didn't really call them m and p, but gave them names describing what they did—and so my coworker's IDE found m, and he wrote a call to m in his code. Since he didn't call p, the context required for m to work properly was not set up, and m blew up when he called it, and he wasted some time trying to figure out why before he came to me and I told him he should have called p instead.

In my defense, I had clearly stated in the Javadoc for m that it was to be called only from p, not from the client application. Unfortunately, my coworker searched for just an identifier in his IDE, and the IDE didn't know enough to read the caveats I had put in the Javadoc and wave red flags in front of my coworker when he called the wrong method.

(OK, I know what you're thinking. I shouldn't have set up my system so that m and p were in different packages in the first place. This kind of setup—a publicly visible method not meant to be invoked by the public—is one that should have been caught in the design phase, or been solved by something like the export controls in the eternally-not-quite-ready-for-prime-time Java Module System, JSR 277. And in this case, you're probably right, at least in a perfect world. But this problem can also occur where refactoring and modularity don't work, as I show below; so for now, please just accept the problem as legitimate.)

Now for the pattern I adopted to solve the problem. I haven't seen any discussion of a general solution to this problem elsewhere, so I'm going to take the initiative and name the pattern: Unconstructable Token.

In Unconstructable Token, a method m that is declared public but should be invoked only from a particular context takes a parameter of a type T that can be constructed only in that context. m verifies that the T is not null, and gives a sensible error message if it is null—a runtime enforcement of m's restricted visibility that is admittedly inferior to a compiletime enforcement, but the best that can be managed if m must be declared public. (In practice, this is almost as good as compiletime enforcement, because programmers are unlikely to try to pass null as a method argument without explicit permission.)

A schematic example:


package p1;

import p2.C2.T;

public class C1 {

public void m (C2.T token) {
if (token == null)
throw new IllegalStateException(
"Cannot call C1.m directly; call C2.p");
do something useful
}

}


package p2;

import p1.C1;

public class C2 {

public class T {

T () {
// constructor is *not* public, so can only be
// called from package p2
}

}

// The token doesn't have to be a singleton, but is here:
final T t = new T();

public void p (C1 c1) {
set something up
c1.m(t);
finish up
}

}


The example shows a token with no functionality of its own, but it is often convenient for C2 to place some of the data or actions needed to coordinate between m and p in the token itself.

The hoped-for result is that your documentation-ignoring coworkers will quickly realize they can't get a hold of a T, and so can't call m; and therefore they keep searching and stumble on p, which they should call. If they are so bold as to call m(null), they'll get an error message at runtime that points them in the right direction.

Of course this pattern is Java-specific. In C++, you wouldn't declare m public, but instead declare p to be a friend of m, and you'd be done. But the Java folks don't seem inclined to take the language in the direction of friend, so that's unlikely ever to be an option for Java.

Anyway, are you sold yet, or is Unconstructable Token more antipattern than pattern? I think that depends on context. In the distant, shining world of JSR 277, this system could be a single module that publishes C2, but not C1 or T. m would still be declared public, but because it's in a module that doesn't export it, it's not visible to the client application. But in the real world of deadlines and pointy-haired bosses, we can't wait for Java 7 (which will surely include an implementation of the module system—won't it?), and we don't necessarily have the luxury of refactoring the system to put all the relevant mechanism into one package (if that even makes sense), and we probably don't want to get bogged down in something as heavyweight as OSGi (which is an existing module framework specification, but more oriented towards modules that may be added and removed during execution).

I may be displaying undue favoritism because I invented Unconstructable Token, but I think it's not so ugly that you need to be ashamed of using it, especially if you document that you're doing so.

Now, as promised, a situation where Unconstructable Token can be indispensable: the case of synthesized code. If you are writing a class loader that modifies or generates code to implement the rules of some framework, you may want the generated code to call methods in the framework (ordinary methods that you write as part of the framework, not generated methods). However, even though the framework methods may perform actions that don't make sense except when called from the generated code, you must make them public in Java—otherwise, you won't be able to call them from code loaded by your class loader.

If you invoke the generated code in question directly from the framework, you can just pass an Unconstructable Token to the generated code, and the generated code can pass it back when it calls back into the framework.

The solution is more complicated if your framework methods can be called from arbitrary places in the generated code. I haven't dealt with such a situation in practice, but it seems to me you could add some generated code to each class to wind up putting the Unconstructable Token in a private variable in each class containing generated code. Since I'm too lazy to figure out whether this really works, or how to do it tidily, I'm going to decree this an Exercise for the Reader. At least, until such time as I need to do it myself.

Note that neither refactoring nor modularity gets us anywhere in the case of generated code. Assuming your framework doesn't load itself, the generated code you load with your class loader will necessarily be in a different package from any of the framework packages (because they have different class loaders). And how would you write a module so that it exported a method to the generated code, but not handwritten code in the same package? I'm not familiar enough with the module system proposals to say definitively that it's impossible, but it doesn't sound easy.

Saturday, August 8, 2009

The JSR 308 Story

OK, after a little reading, I think I've figured out what JSR 308 does and does not do.

Although there is a bit of speculative language scattered in the JSR 308 materials about runtime enforcement of the rules associated with various annotations, no enforcement mechanism is currently available. That is, JSR 308 (at least in its current incarnation) is all about compiletime, and not about runtime.

Besides the immutability-related annotations of Javari, the JSR 308 kit includes an alternative immutabilty checker, IGJ, and some other annotations for checking:
  • Nullness: @NonNull and @Nullable
  • Interning (whether two objects of which equals is true may be distinct instances): @Interned
  • Locks: @GuardedBy and @Holding
as well as a clunky-looking mechanism for subtyping by annotation, the Basic checker.

Tuesday, July 21, 2009

Immutability, Javari, and @ReadOnly: JSR 308

Behind the curve, as always, I'm only just realizing that Java is in the process of introducing an Official Way to assemble one of the important puzzle pieces for making systems with cooperating untrusted code: namely, immutability.

Enforced immutability makes it easy for you to share a data structure with a piece of code that should be allowed to read, but not write, the structure. There are a number of situations where this is useful. The Javari paper, for example, cites the way Class.getSigners was implemented in early versions of Java:


class Class {
private Object[] signers;
Object[] getSigners() {
return signers;
}
}


Because raw Java does not provide for read-only array elements, and because the method returns the array actually used to implement Java security, this is a security hole: all you need to do to make a class appear to have a different set of signers is alter elements in the returned array.

The conventional Java programming technique to avoid this problem is to make and return a copy of the array, but that adds verbosity to the code, is prone to errors (what if you forget to make a copy in just one place?), and is not efficient (if you invoke the method a lot, you make a lot of array copies).

Javari makes it easy to do something like this:


class Class {
private Object[] signers;
readonly Object[] getSigners() {
return signers;
}
}


which has the effect of prohibiting modification of the returned array elements, so that even untrusted code can invoke the method without ill effects.

JSR 308, coming up in Java 7, allows annotations on types. This extends Java annotations so that they can be used in place of the readonly keyword above, so that Javari can be turned into standard (JSR-308-extended) Java.

And now we come to the end of my expertise on the subject, because I've only just glanced at the main java page's blurb about JSR 308 and barely begun to read the Javari paper.

But I've got a question: is the Javari checker only a compiletime thing, and not a loadtime thing? Compiletime checking is great, of course; the earlier you can catch a potential error, in general, the better. But a compiletime-only mechanism is likely insufficient if you're interested in enforcing rules on untrusted code, because:

  • You may well not have access to the source for the untrusted code you'd like to run, and
  • Even if you have the source code, it may not be compilable with the Java compiler. With the recent proliferation of high-quality JVM-compatible languages, another language may express an algorithm better than Java itself, and you'd want to give people the freedom to submit untrusted code written in the language of their choice.
It may be that there's some straightforward way to put the pieces of the JSR 308 kit into a class loader and do loadtime verification of Javari's immutability rules, but I haven't yet spotted anything that says this is the case. Guess I've got my summer reading assignment.

Monday, July 20, 2009

Cooperating Untrusted Code in Java and LSL

I've been spending a fair amount of time in Second Life recently, and so I've had a chance to play with LSL, the Linden Scripting Language, which lets you program the behavior of objects in the world of Second Life. That means I've had the chance to look at LSL's solution to a problem I've given some thought to: how do you invite people to contribute code to a common environment, without worrying too much that malicious (or incompetent) contributors will hijack or crash the system?

This is an old question, and there are some well-established answers to it. From the beginning, the Java programming language has included a sandbox security model suitable, for example, for running applets in a browser. The default security level for an applet prevents most possible types of misbehavior—for example, it prohibits access to the local file system—but it doesn't have any provision for different applets to interact directly with each other; the security restrictions more or less make different applets running in the same process invisible to one another (although they could, for example, communicate with a common server). The Java security model also does not have provisions for restricting either the CPU time or memory consumption of untrusted code, and so does not deal with denial-of-service attacks that overuse those resources.

LSL, by contrast, includes explicit CPU time and memory restrictions on running scripts. Like Java, it doesn't let you access any of the underlying system (like local files)—but it does this not by having a security manager that explicitly prevents such operations, but just by omitting the operations from the language. Unlike Java, LSL doesn't also have to run general-purpose applications in a low-security environment.

And unlike Java applets, LSL does provide a fairly straightforward way for different programs to communicate with one another. Communication among running LSL scripts takes the form of text strings sent through channels, each channel denoted by a 32-bit integer. Publish the channel number and message format, and any object in the vicinity can talk with you. Objects in Second Life can interact with each other in ways independent of LSL, too. For example, objects with the physical attribute can collide with each other and push each other around.

Exciting though it is to be able to program things as visual and interactive as the content of Second Life, LSL has plenty of drawbacks. It is not a particularly full-featured language: it lacks, for example, proper arrays, which makes it impossible to build efficient higher-level data structures like hash tables. Worse, there is no way to share code across scripts; “libraries”, to the extent that such exist, are just pieces of source code that you can paste into a script.

LSL has security holes, too: for example, how do a set of cooperating LSL scripts open a private channel among themselves? Obviously, if you want to break some code that's communicating on a particular channel, and you know the channel, you can spoof a valid message, so there's a way to prevent that, right? Well, not really, no. The best you can do is set the permissions on a script that chooses a channel number so that other people can't edit the script and see the channel-choosing algorithm you used, but there's never any truly reliable way to guarantee that your channel won't collide with one used by some other object in the vicinity.

Another problem with interobject communication in LSL is speed: channels appear to be implemented with operating system sockets or some other relatively slow mechanism—certainly they don't seem to have the throughput you would expect if they were implemented as a message-delivering data structure within a single process. This means you can't treat message-sending as a sort of interobject method invocation: it's orders of magnitude too slow.

Neither Java nor LSL makes it really easy to create systems where pieces can cooperate closely with other pieces that are not fully trustworthy. What kind of implementation would be required to do that, and what kinds of things would you be able to build with it?

Friday, July 17, 2009

Who Am I? Why Am I Here?

You might recognize the title of this post as Admiral Stockdale's opening line from the 1992 vice-presidential debate. Stockdale was famously unprepared for the debate, and something in the tone of his opening rhetorical questions gave the impression that he really didn't know the answer.

It's cheap and easy to criticize someone else's mistake as a way of claiming that you're not making the same mistake. So of course I want you to believe that I do know who I am and why I'm here.

I write software, sometimes for a living, sometimes just because software is interesting and figuring out how to do something complicated that I've never done before is more satisfying than a lot of things. I mostly use Java, because I know it pretty well, and because it strikes a good balance between understandability and efficiency. I'm more interested in making big complex things run fast, and not so interested in the zillions of little workhorse programs that don't do anything particularly speedy or exotic but make the world run. I think in terms of frameworks more than applications, which is a rare luxury when you're writing software for money, which is something I'm not expecting to make from my own projects.

I'm starting this blog as a way of explaining to myself (and anyone bored enough to tune in) what I'm doing and why. There's no better way to discover that your ideas are full of holes than to try to give a coherent explanation of them.

I expect to be an inconstant poster, subject to the ebb and flow of distraction and concentration, enthusiasm and apathy.