class that shared a static variable, they could use that static variable to exchange information
between themselves. Thinking about this now, it doesn't seem like all that serious a security
problem. But at the time, it was seen as a crack in the Java security facade, and it needed to be
fixed quickly without breaking the code that already existed out in the world.
Here is how the problem was fixed. All Java classes get loaded by a classloader, which is a
part of the virtual machine that brings in the bytecodes for a class and dynamically links in
that class. So the first part of the fix was to make sure that each applet was loaded by a differ-
ent classloader; the actual restriction was that classes coming from different locations on the
Internet had to be loaded by different classloaders. So an applet that came from one website
would need to be loaded using a different classloader than an applet that came from a different
website. On top of this, the runtime type of an object was redefined to be the combination of
the compile-time type (that is, the combination of the class and the interfaces implemented by
the class) and the classloader. Since applets from different web pages would be loaded by dif-
ferent classloaders, they would be considered by the runtime system to be of different types,
even if they had the same compile-time type. Since they were of different runtime types, they
wouldn't share static fields, so the backdoor communication that led to the security worry
would be eliminated. The solution worked, would not break any code that was not relying on
insecure features, and was reasonably easy to implement.
But it also meant that there was now a difference between the definitions of the compile-time
type of an object and the runtime type of that object. Usually this doesn't matter. If you are
not loading objects over the network (more on that later) or introducing your own classloaders
(which is becoming more common as people decide that classloaders are a hook for all sorts
of things), two objects that have the same compile-time type will be of the same runtime type.
But God have mercy on your soul if you ever have a program or system where you cross class-
loader boundaries. Sometimes you won't notice (because the types you are passing across the
boundary are actually first defined in a common parent classloader). But when you do, you
will be told that the type of an object that you are using is incompatible with the declared type,
even though the source code says that they are the same. Good luck in finding the problem;
even more luck will be needed to fix the problem (which generally requires introducing more
classloaders, making it even more likely that another problem like this will pop up).
Still, the type system of the Java language overall is a great way to help you design, imple-
ment, and maintain a system. It gives a structure for describing the outside of an object, and
a separate way for constructing the inside. It lets the compiler tell you when things are out of
whack. And it gives you a way of building units of meaning that can be shared, extended, and
explained. It could be better, but as it is, it's pretty good.