final byte[] packObject(Object obj, boolean finalized) {
		ByteBuffer buf = new ByteBuffer(this, obj, finalized);
		int offs = ObjectHeader.sizeof;
		buf.extend(offs);
		ClassDescriptor desc = getClassDescriptor(obj.getClass());

		try {
			if (obj instanceof SelfSerializable) {
				((SelfSerializable) obj).pack(buf.getOutputStream());
				offs = buf.used;
			}
			else if (desc.customSerializable) {
				serializer.pack(obj, buf.getOutputStream());
				offs = buf.used;
			}
			else {
				offs = packObject(obj, desc, offs, buf);
			}
		}
		catch (Exception x) {
			throw new StorageError(StorageError.ACCESS_VIOLATION, x);
		}

		ObjectHeader.setSize(buf.arr, 0, offs);
		ObjectHeader.setType(buf.arr, 0, desc.getOid());
		return buf.arr;
	}