iiop-openjdk/src/main/java/org/wildfly/iiop/openjdk/rmi/Util.java
static long getClassHashCode(Class cls) {
        // The simple cases
        if (cls.isInterface())
            return 0;
        if (!Serializable.class.isAssignableFrom(cls))
            return 0;
        if (Externalizable.class.isAssignableFrom(cls))
            return 1;

        // Try cache
        Long l = (Long) classHashCodeCache.get(cls);
        if (l != null)
            return l.longValue();

        // Has to calculate the hash.

        ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
        DataOutputStream dos = new DataOutputStream(baos);

        // Step 1
        Class superClass = cls.getSuperclass();
        if (superClass != null && superClass != Object.class) {
            try {
                dos.writeLong(getClassHashCode(superClass));
            } catch (IOException ex) {
                throw IIOPLogger.ROOT_LOGGER.unexpectedException(ex);
            }
        }

        // Step 2
        boolean hasWriteObject = false;
        try {
            Method m;
            int mods;

            m = cls.getDeclaredMethod("writeObject",
                    new Class[]{ObjectOutputStream.class});
            mods = m.getModifiers();

            if (!Modifier.isPrivate(mods) && !Modifier.isStatic(mods))
                hasWriteObject = true;
        } catch (NoSuchMethodException ex) {
            // ignore
        }
        try {
            dos.writeInt(hasWriteObject ? 2 : 1);
        } catch (IOException ex) {
            throw IIOPLogger.ROOT_LOGGER.unexpectedException(ex);
        }

        // Step 3
        Field[] fields = cls.getDeclaredFields();
        SortedSet set = new TreeSet(new FieldComparator());

        for (int i = 0; i < fields.length; ++i) {
            int mods = fields[i].getModifiers();

            if (!Modifier.isStatic(mods) && !Modifier.isTransient(mods))
                set.add(fields[i]);
        }
        Iterator iter = set.iterator();
        try {
            while (iter.hasNext()) {
                Field f = (Field) iter.next();

                dos.writeUTF(f.getName());
                dos.writeUTF(getSignature(f.getType()));
            }
        } catch (IOException ex) {
            throw IIOPLogger.ROOT_LOGGER.unexpectedException(ex);
        }

        // Convert to byte[]
        try {
            dos.flush();
        } catch (IOException ex) {
            throw IIOPLogger.ROOT_LOGGER.unexpectedException(ex);
        }
        byte[] bytes = baos.toByteArray();

        // Calculate SHA digest
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("SHA");
        } catch (NoSuchAlgorithmException ex) {
            throw IIOPLogger.ROOT_LOGGER.unavailableSHADigest(ex);
        }
        digest.update(bytes);
        byte[] sha = digest.digest();

        // Calculate hash as per section 10.6.2
        long hash = 0;
        for (int i = 0; i < Math.min(8, sha.length); i++) {
            hash += (long) (sha[i] & 255) << (i * 8);
        }

        // Save in cache
        classHashCodeCache.put(cls, new Long(hash));

        return hash;
    }
static long getClassHashCode(Class cls) {
        // The simple cases
        if (cls.isInterface())
            return 0;
        if (!Serializable.class.isAssignableFrom(cls))
            return 0;
        if (Externalizable.class.isAssignableFrom(cls))
            return 1;

        // Try cache
        Long l = (Long) classHashCodeCache.get(cls);
        if (l != null)
            return l.longValue();

        // Has to calculate the hash.

        ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
        DataOutputStream dos = new DataOutputStream(baos);

        // Step 1
        Class superClass = cls.getSuperclass();
        if (superClass != null && superClass != Object.class) {
            try {
                dos.writeLong(getClassHashCode(superClass));
            } catch (IOException ex) {
                throw IIOPLogger.ROOT_LOGGER.unexpectedException(ex);
            }
        }

        // Step 2
        boolean hasWriteObject = false;
        try {
            Method m;
            int mods;

            m = cls.getDeclaredMethod("writeObject",
                    new Class[]{ObjectOutputStream.class});
            mods = m.getModifiers();

            if (!Modifier.isPrivate(mods) && !Modifier.isStatic(mods))
                hasWriteObject = true;
        } catch (NoSuchMethodException ex) {
            // ignore
        }
        try {
            dos.writeInt(hasWriteObject ? 2 : 1);
        } catch (IOException ex) {
            throw IIOPLogger.ROOT_LOGGER.unexpectedException(ex);
        }

        // Step 3
        Field[] fields = cls.getDeclaredFields();
        SortedSet set = new TreeSet(new FieldComparator());

        for (int i = 0; i < fields.length; ++i) {
            int mods = fields[i].getModifiers();

            if (!Modifier.isStatic(mods) && !Modifier.isTransient(mods))
                set.add(fields[i]);
        }
        Iterator iter = set.iterator();
        try {
            while (iter.hasNext()) {
                Field f = (Field) iter.next();

                dos.writeUTF(f.getName());
                dos.writeUTF(getSignature(f.getType()));
            }
        } catch (IOException ex) {
            throw IIOPLogger.ROOT_LOGGER.unexpectedException(ex);
        }

        // Convert to byte[]
        try {
            dos.flush();
        } catch (IOException ex) {
            throw IIOPLogger.ROOT_LOGGER.unexpectedException(ex);
        }
        byte[] bytes = baos.toByteArray();

        // Calculate SHA digest
        MessageDigest digest;
        try {
            digest = MessageDigest.getInstance("SHA");
        } catch (NoSuchAlgorithmException ex) {
            throw IIOPLogger.ROOT_LOGGER.unavailableSHADigest(ex);
        }
        digest.update(bytes);
        byte[] sha = digest.digest();

        // Calculate hash as per section 10.6.2
        long hash = 0;
        for (int i = 0; i < Math.min(8, sha.length); i++) {
            hash += (long) (sha[i] & 255) << (i * 8);
        }

        // Save in cache
        classHashCodeCache.put(cls, new Long(hash));

        return hash;
    }
Return the class hash code, as specified in "The Common Object
Request Broker: Architecture and Specification" (01-02-33),
section 10.6.2.