private final void storeObject0(Object obj, boolean finalized) {
		if (obj instanceof IStoreable) {
			((IPersistent) obj).onStore();
		}

		if (listener != null) {
			listener.onObjectStore(obj);
		}

		int oid = getOid(obj);
		boolean newObject = false;

		if (oid == 0) {
			oid = allocateId();

			if (!finalized) {
				objectCache.put(oid, obj);
			}

			assignOid(obj, oid, false);
			newObject = true;
		}
		else if (isModified(obj)) {
			objectCache.clearDirty(obj);
		}

		byte[] data = packObject(obj, finalized);
		long pos;
		int newSize = ObjectHeader.getSize(data, 0);
		CustomAllocator allocator = (customAllocatorMap != null) ? getCustomAllocator(obj
				.getClass()) : null;

		if (newObject || (pos = getPos(oid)) == 0) {
			pos = allocator != null ? allocator.allocate(newSize) : allocate(
					newSize, 0);
			setPos(oid, pos | dbModifiedFlag);
		}
		else {
			int offs = (int) pos & (Page.pageSize - 1);

			if ((offs & (dbFreeHandleFlag | dbPageObjectFlag)) != 0) {
				throw new StorageError(StorageError.DELETED_OBJECT);
			}

			Page pg = pool.getPage(pos - offs);
			int size = ObjectHeader.getSize(pg.data, offs & ~dbFlagsMask);
			pool.unfix(pg);

			if ((pos & dbModifiedFlag) == 0) {
				if (allocator != null) {
					allocator.free(pos & ~dbFlagsMask, size);
					pos = allocator.allocate(newSize);
				}
				else {
					cloneBitmap(pos & ~dbFlagsMask, size);
					pos = allocate(newSize, 0);
				}

				setPos(oid, pos | dbModifiedFlag);
			}
			else {
				pos &= ~dbFlagsMask;

				if (newSize != size) {
					if (allocator != null) {
						long newPos = allocator.reallocate(pos, size, newSize);

						if (newPos != pos) {
							pos = newPos;
							setPos(oid, pos | dbModifiedFlag);
						}
						else if (newSize < size) {
							ObjectHeader.setSize(data, 0, size);
						}
					}
					else {
						if (((newSize + dbAllocationQuantum - 1) & ~(dbAllocationQuantum - 1)) > ((size
								+ dbAllocationQuantum - 1) & ~(dbAllocationQuantum - 1))) {
							long newPos = allocate(newSize, 0);
							cloneBitmap(pos, size);
							free(pos, size);
							pos = newPos;
							setPos(oid, pos | dbModifiedFlag);
						}
						else if (newSize < size) {
							ObjectHeader.setSize(data, 0, size);
						}
					}
				}
			}
		}

		modified = true;
		pool.put(pos, data, newSize);
	}