cleanup();
    public boolean save(Savable object, OutputStream os) throws IOException {        classes = new HashMap<String, BinaryClassObject>();        contentTable = new IdentityHashMap<Savable, BinaryIdContentPair>();        locationTable = new HashMap<Integer, Integer>();        GZIPOutputStream zos = new GZIPOutputStream(os) {            {                def.setLevel(COMPRESSION);            }        };        int id = processBinarySavable(object);        // write out tag table        int ttbytes = 0;        int classNum = classes.keySet().size();        int aliasWidth = ((int) FastMath.log(classNum, 256) + 1); // make all                                                                // aliases a                                                                // fixed width        zos.write(ByteUtils.convertToBytes(classNum));        for (String key : classes.keySet()) {            BinaryClassObject bco = classes.get(key);                        // write alias            byte[] aliasBytes = fixClassAlias(bco.alias,                    aliasWidth);            zos.write(aliasBytes);            ttbytes += aliasWidth;            // write classname size & classname            byte[] classBytes = key.getBytes();            zos.write(ByteUtils.convertToBytes(classBytes.length));            zos.write(classBytes);            ttbytes += 4 + classBytes.length;            zos.write(ByteUtils.convertToBytes(bco.nameFields.size()));                        for (String fieldName : bco.nameFields.keySet()) {                BinaryClassField bcf = bco.nameFields.get(fieldName);                zos.write(bcf.alias);                zos.write(bcf.type);                                // write classname size & classname                byte[] fNameBytes = fieldName.getBytes();                zos.write(ByteUtils.convertToBytes(fNameBytes.length));                zos.write(fNameBytes);                ttbytes += 2 + 4 + fNameBytes.length;            }        }        ByteArrayOutputStream out = new ByteArrayOutputStream();        // write out data to a seperate stream        int location = 0;        // keep track of location for each piece        HashMap<String, ArrayList<BinaryIdContentPair>> alreadySaved = new HashMap<String, ArrayList<BinaryIdContentPair>>(                contentTable.size());        for (Savable savable : contentTable.keySet()) {            // look back at previous written data for matches            String savableName = savable.getClassTag().getName();            BinaryIdContentPair pair = contentTable.get(savable);            ArrayList<BinaryIdContentPair> bucket = alreadySaved                    .get(savableName + getChunk(pair));            int prevLoc = findPrevMatch(pair, bucket);            if (prevLoc != -1) {                locationTable.put(pair.getId(), prevLoc);                continue;            } else                locationTable.put(pair.getId(), location);            if (bucket == null) {                bucket = new ArrayList<BinaryIdContentPair>();                alreadySaved.put(savableName + getChunk(pair), bucket);            }            bucket.add(pair);            byte[] aliasBytes = fixClassAlias(classes.get(savableName).alias, aliasWidth);            out.write(aliasBytes);            location += aliasWidth;            BinaryOutputCapsule cap = contentTable.get(savable).getContent();            out.write(ByteUtils.convertToBytes(cap.bytes.length));            location += 4; // length of bytes            out.write(cap.bytes);            location += cap.bytes.length;        }        // write out location table        // tag/location        int locNum = locationTable.keySet().size();        zos.write(ByteUtils.convertToBytes(locNum));        int locbytes = 0;        for (Integer key : locationTable.keySet()) {            zos.write(ByteUtils.convertToBytes(key));            zos.write(ByteUtils.convertToBytes(locationTable.get(key)));            locbytes += 8;        }                // write out number of root ids - hardcoded 1 for now        zos.write(ByteUtils.convertToBytes(1));        // write out root id        zos.write(ByteUtils.convertToBytes(id));        // append stream to the output stream        out.writeTo(zos);        zos.finish();                out = null;        zos = null;        cleanup();        if (debug ) {            System.err.println("Stats:");            System.err.println("classes: " + classNum);            System.err.println("class table: " + ttbytes + " bytes");            System.err.println("objects: " + locNum);            System.err.println("location table: " + locbytes + " bytes");            System.err.println("data: " + location + " bytes");        }        return true;    }