superClass.addSubClass(this);
  VM_Class(VM_TypeReference typeRef, DataInputStream input)     throws ClassFormatError, 	   IOException {    super(typeRef);    subClasses = emptyVMClass;    if (classLoadingDisabled) {      throw new RuntimeException("ClassLoading Disabled : "+this);    }    if (VM.TraceClassLoading && VM.runningVM) VM.sysWrite("VM_Class: (begin) load file " + this.getDescriptor() + "\n");        int magic = input.readInt();    if (magic != 0xCAFEBABE) {      throw new ClassFormatError("bad magic number " + Integer.toHexString(magic));    }    // Get the class file version number and check to see if it is a version    // that we support.    int minor = input.readUnsignedShort();    int major = input.readUnsignedShort();    switch (major) {    case 45: case 46: case 47:  // we support all variants of these major versions so the minor number doesn't matter.      break;    case 48: // we only support up to 48.0      if (minor == 0) break;    default:      throw new java.lang.UnsupportedClassVersionError("unsupported class file version " + major + "." + minor);    }        //    // pass 1: read constant pool    //    constantPool = new int[input.readUnsignedShort()];    byte tmpTags[] = new byte[constantPool.length];    // note: slot 0 is unused    for (int i = 1; i <constantPool.length; i++) {      switch (tmpTags[i] = input.readByte()) {      case TAG_UTF:  {	byte utf[] = new byte[input.readUnsignedShort()];	input.readFully(utf);	constantPool[i] = VM_Atom.findOrCreateUtf8Atom(utf).getId();	break;        }            case TAG_UNUSED:	if (VM.VerifyAssertions) VM._assert(NOT_REACHED);	break;      case TAG_INT:	constantPool[i] = VM_Statics.findOrCreateIntLiteral(input.readInt());	break;      case TAG_FLOAT:	constantPool[i] = VM_Statics.findOrCreateFloatLiteral(input.readInt());	break;      case TAG_LONG:	constantPool[i++] = VM_Statics.findOrCreateLongLiteral(input.readLong());	break;      case TAG_DOUBLE:	constantPool[i++] = VM_Statics.findOrCreateDoubleLiteral(input.readLong());	break;      case TAG_TYPEREF:	constantPool[i] = input.readUnsignedShort();	break;      case TAG_STRING:	constantPool[i] = input.readUnsignedShort();	break;      case TAG_FIELDREF:      case TAG_METHODREF:      case TAG_INTERFACE_METHODREF: {	int classDescriptorIndex         = input.readUnsignedShort();	int memberNameAndDescriptorIndex = input.readUnsignedShort();	constantPool[i] = (classDescriptorIndex << BITS_IN_SHORT) | memberNameAndDescriptorIndex;	break;       }      case TAG_MEMBERNAME_AND_DESCRIPTOR: {	int memberNameIndex = input.readUnsignedShort();	int descriptorIndex = input.readUnsignedShort();	constantPool[i] = (memberNameIndex << BITS_IN_SHORT) | descriptorIndex;	break;        }	      default:	throw new ClassFormatError("bad constant pool");      }    }    //    // pass 2: post-process type and string constant pool entries     // (we must do this in a second pass because of forward references)    //    try {      for (int i = 1; i<constantPool.length; i++) {	switch (tmpTags[i]) {	case TAG_LONG:	case TAG_DOUBLE: 	  ++i;	  break; 	case TAG_TYPEREF: { // in: utf index	  VM_Atom typeName = getUtf(constantPool[i]);	  constantPool[i] = VM_TypeReference.findOrCreate(getClassLoader(), typeName.descriptorFromClassName()).getId();	  break; 	} // out: type reference id	case TAG_STRING: { // in: utf index	  constantPool[i] = VM_Statics.findOrCreateStringLiteral(getUtf(constantPool[i]));	  break; 	} // out: jtoc slot number	}      }    } catch (java.io.UTFDataFormatException x) {      throw new ClassFormatError(x.toString());    }        //    // pass 3: post-process type field and method constant pool entries     //    for (int i = 1; i<constantPool.length; i++) {      switch (tmpTags[i]) {      case TAG_LONG:      case TAG_DOUBLE: 	++i;	break;       case TAG_FIELDREF:      case TAG_METHODREF:      case TAG_INTERFACE_METHODREF: { // in: classname+membername+memberdescriptor indices	int bits                         = constantPool[i];	int classNameIndex               = (bits >> BITS_IN_SHORT) & 0xffff;	int memberNameAndDescriptorIndex = bits & 0xffff;	int memberNameAndDescriptorBits  = constantPool[memberNameAndDescriptorIndex];	int memberNameIndex              = (memberNameAndDescriptorBits >> BITS_IN_SHORT) & 0xffff;	int memberDescriptorIndex        = (memberNameAndDescriptorBits       ) & 0xffff;		VM_TypeReference  tref   = getTypeRef(classNameIndex);	VM_Atom memberName       = getUtf(memberNameIndex);	VM_Atom memberDescriptor = getUtf(memberDescriptorIndex);	VM_MemberReference mr    = VM_MemberReference.findOrCreate(tref, memberName, memberDescriptor);	constantPool[i] = mr.getId();	break;       } // out: VM_MemberReference id      }    }    modifiers     = input.readUnsignedShort();    int myTypeIndex = input.readUnsignedShort();    VM_TypeReference myTypeRef = getTypeRef(myTypeIndex);    if (myTypeRef != typeRef) {      // eg. file contains a different class than would be       // expected from its .class file name      throw new ClassFormatError("expected class \"" + getDescriptor()                                 + "\" but found \"" + myTypeRef.getName() + "\"");    }        VM_TypeReference superType = getTypeRef(input.readUnsignedShort()); // possibly null    if (!(isInterface() || superType == null)) {      superClass = superType.resolve().asClass();      superClass.addSubClass(this);    }    int numInterfaces = input.readUnsignedShort();    if (numInterfaces == 0) {      declaredInterfaces = emptyVMClass;    } else {      declaredInterfaces = new VM_Class[numInterfaces];      for (int i = 0; i < numInterfaces; ++i) {	VM_TypeReference inTR = getTypeRef(input.readUnsignedShort());	declaredInterfaces[i] = inTR.resolve().asClass();      }    }    int numFields = input.readUnsignedShort();    if (numFields == 0) {      declaredFields = emptyVMField;    } else {      declaredFields = new VM_Field[numFields];      for (int i = 0; i<numFields; i++) {	int      fmodifiers      = input.readUnsignedShort();	VM_Atom  fieldName       = getUtf(input.readUnsignedShort());	VM_Atom  fieldDescriptor = getUtf(input.readUnsignedShort());	VM_MemberReference memRef= VM_MemberReference.findOrCreate(typeRef, fieldName, fieldDescriptor);	declaredFields[i] = new VM_Field(this, memRef, fmodifiers, input);      }    }    int numMethods = input.readUnsignedShort();    if (numMethods == 0) {      declaredMethods = emptyVMMethod;    } else {      declaredMethods = new VM_Method[numMethods];      for (int i = 0; i<numMethods; i++) {	int       mmodifiers       = input.readUnsignedShort();	VM_Atom   methodName       = getUtf(input.readUnsignedShort());	VM_Atom   methodDescriptor = getUtf(input.readUnsignedShort());	VM_MemberReference memRef  = VM_MemberReference.findOrCreate(typeRef, methodName, methodDescriptor);	VM_Method method           = VM_Method.readMethod(this, memRef, mmodifiers, input);	declaredMethods[i] = method;	if (method.isClassInitializer())	  classInitializerMethod = method;      }    }    // Read attributes.    for (int i = 0, n = input.readUnsignedShort(); i < n; ++i) {      VM_Atom attName   = getUtf(input.readUnsignedShort());      int     attLength = input.readInt();      // Class attributes      if (attName == VM_ClassLoader.sourceFileAttributeName && attLength == 2) {	sourceName = getUtf(input.readUnsignedShort());	continue;      }      if (attName == VM_ClassLoader.innerClassesAttributeName) {	// Parse InnerClasses attribute, and use the information to populate	// the list of declared member classes.  We do this so we can 	// support the java.lang.Class.getDeclaredClasses() 	// and java.lang.Class.getDeclaredClass methods.	int numberOfClasses = input.readUnsignedShort();	declaredClasses = new VM_TypeReference[numberOfClasses];	for (int j = 0; j < numberOfClasses; ++j) {	  int innerClassInfoIndex = input.readUnsignedShort();	  int outerClassInfoIndex = input.readUnsignedShort();	  int innerNameIndex = input.readUnsignedShort();	  int innerClassAccessFlags = input.readUnsignedShort();	  if (innerClassInfoIndex != 0 &&	      outerClassInfoIndex == myTypeIndex &&	      innerNameIndex != 0) {	    // This looks like a declared inner class.	    declaredClasses[j] = getTypeRef(innerClassInfoIndex);	  }	  if (innerClassInfoIndex == myTypeIndex) {	    if (outerClassInfoIndex != 0) {	      declaringClass = getTypeRef(outerClassInfoIndex);	    }	    if ((innerClassAccessFlags & (ACC_PRIVATE | ACC_PROTECTED)) != 0) {	      modifiers &= ~(ACC_PUBLIC | ACC_PRIVATE | ACC_PROTECTED);	    }	    modifiers |= innerClassAccessFlags;	  }	}	continue;      }      input.skipBytes(attLength);    }    state = CLASS_LOADED;    VM_Callbacks.notifyClassLoaded(this);    if (VM.TraceClassLoading && VM.runningVM) VM.sysWrite("VM_Class: (end)   load file " + 							  getDescriptor() + "\n");  }