I've spent a good chunk of my day trying to work out whether the behaviour described below is problematic or expected consequences of interface (heap?) pollution.
My conclusion is that it's expected behaviour due to the way interfaces are handled by the verifier and may, in limited places, be problematic enough to require an explicit check that an instance is or is not a value. In most cases, it's business as usual. I thought it worth putting this on record to ensure there are no other concerns about it. Longer writeup: ----- Pulling together threads from a couple of recent EG mail discussions to pose a concern I've been thinking about. This touches on the IO/VO interfaces, the new proposed ctor for WeakReferences, and the job of the verifier. Let's start with WeakReference. One potential path forward there is to have a new ctor that takes an IdentityObject rather than an Object. Javac can do the right thing and force all the callers to only pass IdentityObjects. class WeakReference<T extends IdentityObject> { T referent; public WeakReference(T o) { referent = o; } } Assuming I have the generics right, that ctor will take an IdentityObject in its descriptor. Everything's good from the language type-system's point of view. Along comes a classfile generator (or carefully crafted separate compilation) that passes a ValueObject to that WeakReference ctor. Since the Verifier has special handling of interfaces, this generated class verifies successfully. And if no checkcast or interface send occurs, nothing is required to validate that the referent is actually an IdentityObject. The source level invariant is lost at the bytecode level and we allow the `referent` field to be polluted with a wrong kind of instance. This can be patched by have the ctor check that the incoming object isn't a value: public WeakReference(T o) { if (o.getClass().isValue()) throw IAE; referent = o; } That kind of check is easy to miss (or assume isn't required) based on a straightforward reading of the source code. I like the IO/VO interfaces as they let us put the constraints "must be identity (or not)" in the type system but having them as interfaces means the guarantees aren't strictly enforced by the runtime. In most cases, this won't be that problematic - an unexpected exception at worst? - except for cases like WeakReference where there are invariants from the rest of the JVM that need to be enforced. So maybe not an issue. --Dan